From bf5a5d018c79bb458493aa7732f4aa8f5f221396 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 5 Apr 1995 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1995-04-05 --- pc/scsi.c | 61 +++++++++++++++++++++++------------------ port/devsd.c | 74 ++++++++++++++++++++++++++++++-------------------- port/portfns.h | 2 +- 3 files changed, 80 insertions(+), 57 deletions(-) diff --git a/pc/scsi.c b/pc/scsi.c index bd927c3296d17bfe50c0d2b5720ecf5ff9ec5bbd..c9eb371c906f82eb04b918801fa4afd08e86b09c 100644 --- a/pc/scsi.c +++ b/pc/scsi.c @@ -136,7 +136,9 @@ scsiprobe(Ctlr *ctlr) * Determine if the drive exists and is not ready or * is simply not responding */ - if((s = scsireqsense(t, 0, 0)) != STok){ + nbytes = Nscratch; + s = scsireqsense(t, 0, t->scratch, &nbytes, 0); + if(s != STok){ print("scsi%d: unit %d unavailable, status %d\n", t->ctlrno, i, s); continue; } @@ -152,7 +154,7 @@ scsiprobe(Ctlr *ctlr) print("scsi%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s); continue; } - print("scsi%d: unit %d:%2.2ux: %s\n", t->ctlrno, i, t->inq[0], t->inq+8); + print("scsi%d: unit %d: %s\n", t->ctlrno, i, t->inq+8); t->ok = 1; } } @@ -260,15 +262,12 @@ scsicap(Target *t, char lun, ulong *size, ulong *bsize) return -1; nbytes = 8; - s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); - if(s < 0) { - free(d); - return s; + if((s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes)) == STok){ + *size = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|(d[3]<<0); + *bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|(d[7]<<0); } - *size = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|(d[3]<<0); - *bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|(d[7]<<0); free(d); - return 0; + return s; } int @@ -304,7 +303,8 @@ scsibio(Target *t, char lun, int dir, void *b, long n, long bsize, long bno) nbytes = n*bsize; s = scsiexec(t, dir, cmd, cdbsiz, b, &nbytes); if(s < 0) { - scsireqsense(t, lun, 0); + nbytes = Nscratch; + scsireqsense(t, lun, t->scratch, &nbytes, 0); return -1; } return nbytes; @@ -331,37 +331,44 @@ static char *key[] = }; int -scsireqsense(Target *t, char lun, int quiet) +scsireqsense(Target *t, char lun, void *data, int *nbytes, int quiet) { char *s; - int sr, try, nbytes; + int status, try; uchar cmd[6], *sense; - sense = t->scratch; + sense = malloc(*nbytes); for(try = 0; try < 5; try++) { memset(cmd, 0, sizeof(cmd)); cmd[0] = CMDreqsense; cmd[1] = lun<<5; - cmd[4] = Nscratch; - memset(sense, 0, sizeof(sense)); + cmd[4] = *nbytes; + memset(sense, 0, *nbytes); - nbytes = Nscratch; - sr = scsiexec(t, SCSIread, cmd, sizeof(cmd), sense, &nbytes); - if(sr != STok) - return sr; + status = scsiexec(t, SCSIread, cmd, sizeof(cmd), sense, nbytes); + if(status != STok){ + free(sense); + return status; + } + *nbytes = sense[0x07]+8; + memmove(data, sense, *nbytes); /* * Unit attention. We can handle that. */ - if((sense[2] & 0x0F) == 0x00 || (sense[2] & 0x0F) == 0x06) + if((sense[2] & 0x0F) == 0x00 || (sense[2] & 0x0F) == 0x06){ + free(sense); return STok; + } /* * Recovered error. Why bother telling me. */ - if((sense[2] & 0x0F) == 0x01) + if((sense[2] & 0x0F) == 0x01){ + free(sense); return STok; + } /* * Unit is becoming ready @@ -372,12 +379,12 @@ scsireqsense(Target *t, char lun, int quiet) delay(5000); } - if(quiet) - return STcheck; - - s = key[sense[2]&0xf]; - print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", - t->ctlrno, t->target, s, sense[12], sense[13]); + if(quiet == 0){ + s = key[sense[2]&0x0F]; + print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", + t->ctlrno, t->target, s, sense[12], sense[13]); + } + free(sense); return STcheck; } diff --git a/port/devsd.c b/port/devsd.c index 4e97c59fb0332a7e4c481293876843f8f9ad4e9b..07e5c6ac9b4baa9b620d21a9118ca76162c69f57 100644 --- a/port/devsd.c +++ b/port/devsd.c @@ -100,8 +100,7 @@ void sdinit(void) { Disk *d; - ulong s, b; - uchar inq[255]; + uchar scratch[0xFF], type; int dev, i, nbytes; dev = 0; @@ -111,43 +110,48 @@ sdinit(void) if(dev < 0) break; - if(scsitest(d->t, 0) < 0) - scsireqsense(d->t, 0, 0); - if(scsistart(d->t, 0, 1) < 0) - scsireqsense(d->t, 0, 0); -print("sd1|"); - - /* Search for other lun's */ + /* + * Search for all the lun's. + */ for(i = 0; i < Nlun; i++) { d->lun = i; -print("sd2|"); /* * A SCSI target does not support a lun if the * the peripheral device type and qualifier fields * in the response to an inquiry command are 0x7F. */ - memset(inq, 0, sizeof(inq)); - nbytes = sizeof(inq); - if(scsiinquiry(d->t, d->lun, inq, &nbytes) != STok || inq[0] == 0x7F) + nbytes = sizeof(scratch); + memset(scratch, 0, nbytes); + if(scsiinquiry(d->t, d->lun, scratch, &nbytes) != STok) continue; -print("sd3|"); - - s = 0; - b = 0; - if(scsicap(d->t, d->lun, &s, &b) != STok) { - scsireqsense(d->t, 0, 0); + if(scratch[0] == 0x7F) continue; - } -print("sd4/%d/%d|", s, b); + type = scratch[0] & 0x1F; - if(s == 0 || b == 0) - continue; -print("sd5/0x%2.2ux|", d->inquire[0]); + /* + * Read-capacity is mandatory for TypeDA, TypeMO and TypeCD. + * It may return 'not ready' if TypeDA is not spun up, + * TypeMO or TypeCD are not loaded or just plain slow getting + * their act together after a reset. + * If 'not ready' comes back, try starting a TypeDA and punt + * the get capacity until the drive is attached. + * It might be possible to be smarter here, and look at the + * response from a test-unit-ready which would show if the + * target was in the process of becoming ready. + */ + if(scsicap(d->t, d->lun, &d->size, &d->bsize) != STok) { + nbytes = sizeof(scratch); + memset(scratch, 0, nbytes); + scsireqsense(d->t, 0, scratch, &nbytes, 1); + if((scratch[2] & 0x0F) != 0x02) + continue; + if(type == TypeDA) + scsistart(d->t, d->lun, 0); + d->size = d->bsize = 0; + } - d->size = s; - d->bsize = b; - switch(d->inquire[0] & 0x1F){ + switch(type){ case TypeDA: case TypeMO: @@ -161,7 +165,6 @@ print("sd5/0x%2.2ux|", d->inquire[0]); default: continue; } -print("sd6|"); if(++ndisk >= Ndisk) break; @@ -281,10 +284,23 @@ sdrdpart(Disk *d) char *b, *line[Npart+2], *field[3]; static char MAGIC[] = "plan9 partitions"; + /* + * If the drive wasn't ready when we tried to do a + * read-capacity earlier (in sdinit()), try again. + * It might be possible to be smarter here, and look at the + * response from a test-unit-ready which would show if the + * target was in the process of becoming ready. + */ + if(d->size == 0 || d->bsize == 0){ + if(scsicap(d->t, d->lun, &d->size, &d->bsize) != STok){ + d->size = d->bsize = 0; + error(Eio); + } + } + b = scsialloc(d->bsize); if(b == 0) error(Enomem); - qlock(d); p = d->table; diff --git a/port/portfns.h b/port/portfns.h index c77d7bd32a6f85fe77d5c52e37759c8b84d8ebb7..b5c30c4845cc8c13e775259aa99fab88d5fbff56 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -241,7 +241,7 @@ int scsiexec(Target*, int, uchar*, int, void*, int*); #define scsifree(p) free(p) int scsiinquiry(Target*, char, void*, int*); int scsiinv(int, int*, Target**, uchar**, char*); -int scsireqsense(Target*, char, int); +int scsireqsense(Target*, char, void*, int*, int); int scsistart(Target*, char, int); int scsitest(Target*, char); Target* scsiunit(int, int);