Subject: kern/6903: new quirks for ch(4)
To: None <gnats-bugs@gnats.netbsd.org>
From: Chris Jones <cjones@hideo.nervana.montana.edu>
List: netbsd-bugs
Date: 01/28/1999 11:03:15
>Number:         6903
>Category:       kern
>Synopsis:       new quirks for ch(4)
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Jan 28 10:20:01 1999
>Last-Modified:
>Originator:     Chris Jones
>Organization:
Center for Computational Biology, Montana State University
>Release:        Jan 27, 1999
>Environment:
	
System: NetBSD hideo 1.3I NetBSD 1.3I (HIDEO) #11: Thu Jan 28 10:52:10 MST 1999 root@hideo:/usr/src/sys/arch/i386/compile/HIDEO i386


>Description:
I have the honor of being the owner of a changer device that has some
fun quirks.

1.  It doesn't respond to either the 6 or 10 byte MODE SENSE commands,
meaning that ch(4) can't discover its capabilities.

2.  When executing a MOVE MEDIUM command, it always has to have the
medium transport element address set to 0.  In other words, you can
move from address 4 (a storage slot) to 5 (another storage slot) by
way of 0, but not by way of 1.  You can move from 4 to 1 by way of 0,
but not by way of 1, which is silly.  And you can move from 1 back to
4 by way of 0.
>How-To-Repeat:
	
>Fix:
I put in some new quirk fields in sys/dev/scsipi/ch.c, and I added a
quirk entry for my device.  Thanks to Michael Hitch for helping me
feel my way around the SCSI spec.

*** ch.c-orig	Thu Jan 28 08:09:33 1999
--- ch.c	Thu Jan 28 10:51:09 1999
***************
*** 1,4 ****
! /*	$NetBSD: ch.c,v 1.37 1998/12/17 22:28:07 gibbs Exp $	*/
  
  /*
   * Copyright (c) 1996, 1997, 1998 Jason R. Thorpe <thorpej@and.com>
--- 1,4 ----
! /*	$NetBSD: $	*/
  
  /*
   * Copyright (c) 1996, 1997, 1998 Jason R. Thorpe <thorpej@and.com>
***************
*** 87,93 ****
  	 * Quirks; see below.
  	 */
  	int		sc_settledelay;	/* delay for settle */
! 
  };
  
  /* sc_flags */
--- 87,94 ----
  	 * Quirks; see below.
  	 */
  	int		sc_settledelay;	/* delay for settle */
! 	int		sc_no_mode_sense; /* doesn't support MODE SENSE */
! 	int		sc_always_picker0; /* always use default picker */
  };
  
  /* sc_flags */
***************
*** 129,140 ****
  struct chquirk {
  	struct	scsipi_inquiry_pattern cq_match; /* device id pattern */
  	int	cq_settledelay;	/* settle delay, in seconds */
  };
  
  struct chquirk chquirks[] = {
  	{{T_CHANGER, T_REMOV,
  	  "SPECTRA",	"9000",		"0200"},
! 	 75},
  };
  
  int
--- 130,166 ----
  struct chquirk {
  	struct	scsipi_inquiry_pattern cq_match; /* device id pattern */
  	int	cq_settledelay;	/* settle delay, in seconds */
+ 	int	cq_always_picker0; /* always use default picker */
+ 	int	cq_no_mode_sense; /* doesn't support MODE SENSE command */
+ 	int	cq_firsts[4];
+ 	int	cq_counts[4];
+ 	u_int8_t cq_movemask[4];
+ 	u_int8_t cq_exchangemask[4];
  };
  
  struct chquirk chquirks[] = {
  	{{T_CHANGER, T_REMOV,
  	  "SPECTRA",	"9000",		"0200"},
! 	 75, 0,
! 	 0, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
! 	{{T_CHANGER, T_REMOV,
! 	  "CEDAR",	"DESKTOP P100",	"1.10"},
! 	 0, 1,
! 	 1,
! 	 {1, 2, 6, 6},
! 	 {1, 4, 0, 4},
! 	 {MOVE_TO_MT | MOVE_TO_ST | MOVE_TO_IE | MOVE_TO_DT,
! 	  MOVE_TO_MT | MOVE_TO_ST | MOVE_TO_IE | MOVE_TO_DT,
! 	  MOVE_TO_MT | MOVE_TO_ST | MOVE_TO_IE | MOVE_TO_DT,
! 	  MOVE_TO_MT | MOVE_TO_ST | MOVE_TO_IE | MOVE_TO_DT},
! 	 {EXCHANGE_WITH_MT | EXCHANGE_WITH_ST | EXCHANGE_WITH_IE |
! 	  EXCHANGE_WITH_DT,
! 	  EXCHANGE_WITH_MT | EXCHANGE_WITH_ST | EXCHANGE_WITH_IE |
! 	  EXCHANGE_WITH_DT,
! 	  EXCHANGE_WITH_MT | EXCHANGE_WITH_ST | EXCHANGE_WITH_IE |
! 	  EXCHANGE_WITH_DT,
! 	  EXCHANGE_WITH_MT | EXCHANGE_WITH_ST | EXCHANGE_WITH_IE |
! 	  EXCHANGE_WITH_DT}},
  };
  
  int
***************
*** 189,197 ****
--- 215,226 ----
  	 * Get information about the device.  Note we can't use
  	 * interrupts yet.
  	 */
+ 	if(sc->sc_no_mode_sense == 1)
+ 		goto printinfo;
  	if (ch_get_params(sc, SCSI_AUTOCONF))
  		printf("%s: offline\n", sc->sc_dev.dv_xname);
  	else {
+ printinfo:
  #define PLURAL(c)	(c) == 1 ? "" : "s"
  		printf("%s: %d slot%s, %d drive%s, %d picker%s, %d portal%s\n",
  		    sc->sc_dev.dv_xname,
***************
*** 213,219 ****
  	}
  
  	/* Default the current picker. */
! 	sc->sc_picker = sc->sc_firsts[CHET_MT];
  }
  
  int
--- 242,251 ----
  	}
  
  	/* Default the current picker. */
! 	if(sc->sc_always_picker0)
! 		sc->sc_picker = 0;
! 	else
! 		sc->sc_picker = sc->sc_firsts[CHET_MT];
  }
  
  int
***************
*** 254,261 ****
  	/*
  	 * Make sure our parameters are up to date.
  	 */
! 	if ((error = ch_get_params(sc, 0)) != 0)
! 		goto bad;
  
  	return (0);
  
--- 286,294 ----
  	/*
  	 * Make sure our parameters are up to date.
  	 */
! 	if(sc->sc_no_mode_sense == 0)
! 		if ((error = ch_get_params(sc, 0)) != 0)
! 			goto bad;
  
  	return (0);
  
***************
*** 320,326 ****
  		break;
  
  	case CHIOGPICKER:
! 		*(int *)data = sc->sc_picker - sc->sc_firsts[CHET_MT];
  		break;
  
  	case CHIOSPICKER:	{
--- 353,363 ----
  		break;
  
  	case CHIOGPICKER:
! 		if(sc->sc_always_picker0)
! 			*(int *)data = 0;
! 		else
! 			*(int *)data = sc->sc_picker -
! 				sc->sc_firsts[CHET_MT];
  		break;
  
  	case CHIOSPICKER:	{
***************
*** 328,340 ****
  
  		if (new_picker > (sc->sc_counts[CHET_MT] - 1))
  			return (EINVAL);
! 		sc->sc_picker = sc->sc_firsts[CHET_MT] + new_picker;
  		break;		}
  
  	case CHIOGPARAMS:	{
  		struct changer_params *cp = (struct changer_params *)data;
  
! 		cp->cp_curpicker = sc->sc_picker - sc->sc_firsts[CHET_MT];
  		cp->cp_npickers = sc->sc_counts[CHET_MT];
  		cp->cp_nslots = sc->sc_counts[CHET_ST];
  		cp->cp_nportals = sc->sc_counts[CHET_IE];
--- 365,385 ----
  
  		if (new_picker > (sc->sc_counts[CHET_MT] - 1))
  			return (EINVAL);
! 		if(sc->sc_always_picker0)
! 			sc->sc_picker = 0;
! 		else
! 			sc->sc_picker = sc->sc_firsts[CHET_MT] +
! 				new_picker;
  		break;		}
  
  	case CHIOGPARAMS:	{
  		struct changer_params *cp = (struct changer_params *)data;
  
! 		if(sc->sc_always_picker0)
! 			cp->cp_curpicker = 0;
! 		else
! 			cp->cp_curpicker = sc->sc_picker -
! 				sc->sc_firsts[CHET_MT];
  		cp->cp_npickers = sc->sc_counts[CHET_MT];
  		cp->cp_nslots = sc->sc_counts[CHET_ST];
  		cp->cp_nportals = sc->sc_counts[CHET_IE];
***************
*** 679,684 ****
--- 724,734 ----
  	int error, from;
  	u_int8_t *moves, *exchanges;
  
+ #ifdef DIAGNOSTIC
+ 	if(sc->sc_no_mode_sense)
+ 	    panic("Called ch_get_params for no MODE SENSE device");
+ #endif
+ 
  	/*
  	 * Grab info from the element address assignment page.
  	 */
***************
*** 758,763 ****
  	    (caddr_t)chquirks,
  	    sizeof(chquirks) / sizeof(chquirks[0]),
  	    sizeof(chquirks[0]), &priority);
! 	if (priority != 0)
  		sc->sc_settledelay = match->cq_settledelay;
  }
--- 808,828 ----
  	    (caddr_t)chquirks,
  	    sizeof(chquirks) / sizeof(chquirks[0]),
  	    sizeof(chquirks[0]), &priority);
! 	if (priority != 0) {
  		sc->sc_settledelay = match->cq_settledelay;
+ 		sc->sc_always_picker0 = match->cq_always_picker0;
+ 		if(match->cq_no_mode_sense) {
+ 			bcopy(match->cq_firsts, sc->sc_firsts,
+ 			      sizeof(sc->sc_firsts));
+ 			bcopy(match->cq_counts, sc->sc_counts,
+ 			      sizeof(sc->sc_counts));
+ 			bcopy(match->cq_movemask, sc->sc_movemask,
+ 			      sizeof(sc->sc_movemask));
+ 			bcopy(match->cq_exchangemask,
+ 			      sc->sc_exchangemask,
+ 			      sizeof(sc->sc_exchangemask));
+ 			sc->sc_no_mode_sense =
+ 				match->cq_no_mode_sense;
+ 		}
+ 	}
  }
>Audit-Trail:
>Unformatted: