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."