From 069da4207c6e31a2f33e5393e002e6284de5e380 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 10 Feb 1996 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1996-02-10 --- pc/dat.h | 2 ++ pc/devata.c | 47 ++++++++++++++++++++++++++++++++++++----------- pc/scsi.c | 51 ++++++++++++++++++++++++++++++--------------------- 3 files changed, 68 insertions(+), 32 deletions(-) diff --git a/pc/dat.h b/pc/dat.h index 5a3379778a249b9247dcb3cd7a669d122f7f5f84..9d978318a6cf857cebd489e6b743b1f40ca756bc 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -228,6 +228,8 @@ struct Target { uchar* inq; uchar* scratch; + Rendez rendez; + int ok; }; typedef int (*Scsiio)(Target*, int, uchar*, int, void*, int*); diff --git a/pc/devata.c b/pc/devata.c index 6d69a32a3d200e39fdce83cdae0fa9e96afb422a..f875d92fef41c618a5008f0ca9cd9ccf4880de08 100644 --- a/pc/devata.c +++ b/pc/devata.c @@ -49,6 +49,10 @@ enum Serr= (1<<0), Pcmd= 7, /* cmd port (write) */ + Pctrl= 0x206, /* device control, alternate status */ + nIEN= (1<<1), + Srst= (1<<2), + /* commands */ Cfirst= 0xFF, /* pseudo command for initialisation */ Cread= 0x20, @@ -152,7 +156,7 @@ struct Controller int pbase; /* base port */ uchar ctlrno; - uchar noatapi; + uchar resetok; /* * current operation @@ -354,7 +358,7 @@ atactlrprobe(int ctlrno, int irq) { Controller *ctlr; int atapi, mask, port; - uchar error, status; + uchar error, status, msb, lsb; /* * Check the existence of a controller by verifying a sensible @@ -377,12 +381,13 @@ atactlrprobe(int ctlrno, int irq) ctlr->ctlrno = ctlrno; ctlr->lastcmd = 0xFF; + /* * Attempt to check the existence of drives on the controller * by issuing a 'check device diagnostics' command. * Issuing a device reset here would possibly destroy any BIOS * drive remapping and, anyway, some controllers (Vibra16) don't - * seem to implement the control-block registers. + * seem to implement the control-block registers; do it if requested. * Unfortunately the vector must be set at this point as the Cedd * command will generate an interrupt, which means the ataintr routine * will be left on the interrupt call chain even if there are no @@ -392,6 +397,17 @@ atactlrprobe(int ctlrno, int irq) * ATAPI signature straight off. If we find it there will be no probe * done for a slave. Tough. */ + if(ctlr->resetok){ + outb(port+Pctrl, Srst|nIEN); + microdelay(1); + outb(port+Pctrl, 0); + if(atactlrwait(ctlr, DHmagic, 0, 100)){ + DPRINT("ata%d: Srst status %ux/%ux/%ux\n", ctlrno, + inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); + xfree(ctlr); + } + } + atapi = 0; mask = 0; status = inb(port+Pstatus); @@ -405,8 +421,8 @@ atactlrprobe(int ctlrno, int irq) goto skipedd; } if(atactlrwait(ctlr, DHmagic, 0, MS2TK(1)) || waserror()){ - DPRINT("ata%d: Cedd status %ux/%ux/%ux\n", - ctlrno, inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); + DPRINT("ata%d: Cedd status %ux/%ux/%ux\n", ctlrno, + inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); xfree(ctlr); return -1; } @@ -447,9 +463,15 @@ atactlrprobe(int ctlrno, int irq) DPRINT("ata%d: slave diag status %ux, error %ux\n", ctlr->ctlrno, status, error); if(status && (status & (Sbusy|Serr)) == 0 && (error & ~0x80) == 0x01) mask |= 0x02; - else if(status == 0 && inb(port+Pcylmsb) == 0xEB && inb(port+Pcyllsb) == 0x14){ - atapi |= 0x02; - mask |= 0x02; + else if(status == 0){ + msb = inb(port+Pcylmsb); + lsb = inb(port+Pcyllsb); + DPRINT("ata%d: ATAPI slave %uX %uX %uX\n", ctlrno, status, + inb(port+Pcylmsb), inb(port+Pcyllsb)); + if(msb == 0xEB && lsb == 0x14){ + atapi |= 0x02; + mask |= 0x02; + } } skipedd: @@ -514,8 +536,8 @@ atactlrreset(void) DPRINT("ata%d: opt spindownmask %ux\n", ctlrno, spindownmask); } - else if(strcmp(isa.opt[i], "noatapi") == 0) - atactlr[ctlrno]->noatapi = 1; + else if(strcmp(isa.opt[i], "reset") == 0) + atactlr[ctlrno]->resetok = 1; } } } @@ -1091,7 +1113,10 @@ retryatapi: IUNLOCK(&cp->reglock); DPRINT("%s: ident command %ux sent\n", dp->vol, cmd); - atasleep(cp, 1000); + if(cmd == Cident) + atasleep(cp, 3000); + else + atasleep(cp, 30000); if(cp->status & Serr){ DPRINT("%s: bad disk ident status\n", dp->vol); diff --git a/pc/scsi.c b/pc/scsi.c index a86d1506332ae3370ae767bcf70565381a4cd874..564e40d9d9490d4088a5de01d5cc50258dbd1947 100644 --- a/pc/scsi.c +++ b/pc/scsi.c @@ -339,7 +339,7 @@ scsireqsense(Target *t, char lun, void *data, int *nbytes, int quiet) sense = malloc(*nbytes); - for(try = 0; try < 5; try++) { + for(try = 0; try < 20; try++) { memset(cmd, 0, sizeof(cmd)); cmd[0] = CMDreqsense; cmd[1] = lun<<5; @@ -354,32 +354,41 @@ scsireqsense(Target *t, char lun, void *data, int *nbytes, int quiet) *nbytes = sense[0x07]+8; memmove(data, sense, *nbytes); - /* - * Unit attention. We can handle that. - */ - if((sense[2] & 0x0F) == 0x00 || (sense[2] & 0x0F) == 0x06){ - free(sense); - return STok; - } + switch(sense[2] & 0x0F){ - /* - * Recovered error. Why bother telling me. - */ - if((sense[2] & 0x0F) == 0x01){ + case 6: /* unit attention */ + if(sense[12] != 0x29) /* power on, reset */ + goto buggery; + /*FALLTHROUGH*/ + case 0: /* no sense */ + case 1: /* recovered error */ free(sense); return STok; - } - /* - * Unit is becoming ready, rather than not ready - */ - if((sense[2] & 0x0F) != 0x02 && - (sense[12] != 0x04 || sense[13] != 0x01)) - break; - - delay(5000); + case 2: /* not ready */ + if(sense[12] == 0x3A) /* medium not present */ + goto buggery; + /*FALLTHROUGH*/ + + default: + /* + * If unit is becoming ready, rather than not ready, + * then wait a little then poke it again; should this + * be here or in the caller? + */ + if((sense[12] == 0x04 && sense[13] == 0x01)){ + while(waserror()) + ; + tsleep(&t->rendez, return0, 0, 500); + poperror(); + scsitest(t, lun); + break; + } + goto buggery; + } } +buggery: if(quiet == 0){ s = key[sense[2]&0x0F]; print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n",