Subject: Re: umass woe: sd0(umass0:0:0): readonly device & drive offline
To: Hubert Feyrer <feyrer@cs.stevens.edu>
From: Michael van Elst <mlelstv@serpens.de>
List: tech-kern
Date: 11/19/2005 10:03:45
On Sat, Nov 19, 2005 at 05:28:18AM +0100, Hubert Feyrer wrote:
> HF: sd_interpret_sense: flags=0x6, asc=0x28, ascq=0x0
>
> which seems to be some "message buffer full" thing
This is Unit Attention, Not-Ready-to-Ready Change, medium may have
changed. The device tells the initiator that it should query
the device parameters.
> 3) when I run "disklabel sd0", I get:
>
> HF: sd_interpret_sense: flags=0x5, asc=0x24, ascq=0x0
This is the illegal request / invalid field in CDB.
> }
> @@ -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;
> }
This is in the failure path. When the first scsipi_prevent
fails we try another one to "unlock the door".
> @@ -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);
This is in the close path. We ignore any errors.
> @@ -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)
This is an ioctl. It isn't used here.
> @@ -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 {
Again an ioctl. It isn't used here.
> @@ -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.
This is called from scsipi_interprete_sense or atapi_interpret_sense.
Anything != EJUSTRETURN is the resulting sense status. If you
pass back EJUSTRETURN the default code takes over.
If you want to ignore the error, just return 0.
--
Michael van Elst
Internet: mlelstv@serpens.de
"A potential Snark may lurk in every tree."