diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-04-18 15:55:51 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-04-18 15:55:51 +0200 |
commit | 1d96a8256eece7b5ac290c732e009af8f68a702a (patch) | |
tree | 0676a7c092685b240d81b7a6dfe780b2fd9ea318 /sys | |
parent | 05be074413c9ff71c1853b8707f4eb6fe8ef4416 (diff) |
sdide: do drive probles the non-clever way, this got a-'s cdrom to working
Diffstat (limited to 'sys')
-rw-r--r-- | sys/src/9/pc/sdide.c | 165 |
1 files changed, 24 insertions, 141 deletions
diff --git a/sys/src/9/pc/sdide.c b/sys/src/9/pc/sdide.c index 58a86b8af..24ff84015 100644 --- a/sys/src/9/pc/sdide.c +++ b/sys/src/9/pc/sdide.c @@ -574,7 +574,8 @@ ataidentify(Ctlr*, int cmdport, int ctlport, int dev, int pkt, void* info) memset(info, 0, 512); inss(cmdport+Data, info, 256); - ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 3*1000); + + ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 3*1000); inb(cmdport+Status); return 0; @@ -621,7 +622,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 +687,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 +704,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 & 1) && (ctlr->drive[0] = atadrive(0, 0, cmdport, ctlport, Dev0))) + ctlr->drive[0]->ctlr = ctlr; + if((map & 2) && (ctlr->drive[1] = atadrive(0, 0, cmdport, ctlport, Dev1))) + ctlr->drive[1]->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 +749,12 @@ tryedd1: ctlr->sdev = sdev; return sdev; + +release: + iofree(cmdport); + iofree(ctlport+As); + + return nil; } static void @@ -1898,8 +1783,6 @@ 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) |