Subject: Re: umass woe: sd0(umass0:0:0): readonly device & drive offline
To: Michael van Elst <mlelstv@serpens.de>
From: Hubert Feyrer <feyrer@cs.stevens.edu>
List: tech-kern
Date: 11/19/2005 05:28:18
On Fri, 18 Nov 2005, Michael van Elst wrote:
> xs->sense.scsi_sense.response_code & SSD_RCODE_VALID != 0
> SSD_RCODE(xs->sense.scsi_sense.response_code) == SSD_RCODE_CURRENT
> SSD_SENSE_KEY(xs->sense.scsi_sense.flags) == SKEY_ILLEGAL_REQUEST
> xs->sense.scsi_sense.asc == 0x24
> xs->sense.scsi_sense.ascq == 0x00
>
> This tells you that the command failed, you have retrieved valid
> sense_data, the device did think the command was illegal, the
> reason was that there was an invalid field in the command control
> block.
>
> The only place where you can handle this error is in the
> callback sd_interpret_sense where you have match this with
> the command in question. The command is xs->cmd and the
> command code is xs->cmd->opcode.
After sitting more over this, I came up with the patch below to analyze
the whole situation more:
1) When I boot up the system with the cam not plugged in, I get none of
the added message.
2) When I plug in the cam, I get:
HF: sd_interpret_sense: flags=0x6, asc=0x28, ascq=0x0
which seems to be some "message buffer full" thing
3) when I run "disklabel sd0", I get:
HF: sd_interpret_sense: flags=0x5, asc=0x24, ascq=0x0
HF: OINK! SKEY_ILLEGAL_REQUEST/24/00
sd0(umass0:0:0): sdstart HF: scsipi_prevent #1 error=30
sd0(umass0:0:0): sdstart HF: scsipi_prevent #2 error=0
sd0(umass0:0:0): sdstart HF: scsipi_prevent #3 error=0
... but the same old error. Maybe just returning retval=EJUSTRETURN is bad
here, but I have no idea what would be right.
Interesting enough, when I move the test to the end of
sd_interpret_sense(), nothing is printed, and I guess something else exits
the function before that... no idea what though.
Oh while here: all those magic numbers don't make that file easier to
understand. :(
> Now, sdopen() specifies XS_CTL_IGNORE_ILLEGAL_REQUEST
> for scsipi_prevent() but this doesn't seem to be honored.
I saw that too... no idea.
Anybody got a clue on the whole scsipi framework? Manuel? :)
- Hubert
Here's the debugging patch I added for the messages above:
Index: sd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/sd.c,v
retrieving revision 1.216.2.3
diff -u -r1.216.2.3 sd.c
--- sd.c 11 Sep 2004 12:55:11 -0000 1.216.2.3
+++ sd.c 19 Nov 2005 04:13:40 -0000
@@ -539,6 +539,7 @@
error = scsipi_prevent(periph, PR_PREVENT,
XS_CTL_IGNORE_ILLEGAL_REQUEST |
XS_CTL_IGNORE_MEDIA_CHANGE);
+printf("HF: scsipi_prevent #1 error=%d\n", error);
if (error)
goto bad;
}
@@ -600,10 +601,12 @@
bad:
if (sd->sc_dk.dk_openmask == 0) {
- if (periph->periph_flags & PERIPH_REMOVABLE)
- scsipi_prevent(periph, PR_ALLOW,
+ if (periph->periph_flags & PERIPH_REMOVABLE) {
+ error = scsipi_prevent(periph, PR_ALLOW,
XS_CTL_IGNORE_ILLEGAL_REQUEST |
XS_CTL_IGNORE_MEDIA_CHANGE);
+printf("HF: scsipi_prevent #2 error=%d\n", error);
+ }
periph->periph_flags &= ~PERIPH_OPEN;
}
@@ -664,10 +667,12 @@
scsipi_wait_drain(periph);
- if (periph->periph_flags & PERIPH_REMOVABLE)
- scsipi_prevent(periph, PR_ALLOW,
+ if (periph->periph_flags & PERIPH_REMOVABLE) {
+ error = scsipi_prevent(periph, PR_ALLOW,
XS_CTL_IGNORE_ILLEGAL_REQUEST |
XS_CTL_IGNORE_NOT_READY);
+printf("HF: scsipi_prevent #3 error=%d\n", error);
+ }
periph->periph_flags &= ~PERIPH_OPEN;
scsipi_wait_drain(periph);
@@ -1175,8 +1180,10 @@
return (0);
case DIOCLOCK:
- return (scsipi_prevent(periph,
+ error = (scsipi_prevent(periph,
(*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0));
+printf("HF: scsipi_prevent #4 error=%d\n", error);
+ return (error);
case DIOCEJECT:
if ((periph->periph_flags & PERIPH_REMOVABLE) == 0)
@@ -1191,6 +1198,7 @@
sd->sc_dk.dk_openmask) {
error = scsipi_prevent(periph, PR_ALLOW,
XS_CTL_IGNORE_NOT_READY);
+printf("HF: scsipi_prevent #5 error=%d\n", error);
if (error)
return (error);
} else {
@@ -1366,6 +1374,22 @@
struct sd_softc *sd = (void *)periph->periph_dev;
int s, error, retval = EJUSTRETURN;
+ printf("HF: sd_interpret_sense: flags=0x%x, asc=0x%x, ascq=0x%x\n",
+ sense->flags & SSD_KEY, sense->add_sense_code,
+ sense->add_sense_code_qual);
+
+ /*
+ * Ignore errors from accessing fields
+ * (e.g. trying to lock the door of a digicam, which doesn't
+ * have a door that can be locked - HF)
+ */
+ if (((sense->flags & SSD_KEY) == SKEY_ILLEGAL_REQUEST) &&
+ (sense->add_sense_code == 0x24) &&
+ (sense->add_sense_code_qual == 0x00)) { /* Illegal field? *//*HF*/
+ printf("HF: OINK! SKEY_ILLEGAL_REQUEST/24/00\n");
+ return (retval); /* wild guess - HF */
+ }
+
/*
* If the periph is already recovering, just do the normal
* error processing.