Module Name:    src
Committed By:   kardel
Date:           Fri Aug  9 19:51:29 UTC 2013

Modified Files:
        src/sys/dev/pci: mpii.c

Log Message:
fix issues when reading variable block sized tapes.

symptoms:
        generic HBA error on console when reading
        with a larger blocksize. blocks read
        are padded to requested block size with
        a 5a... a5... pattern.

problems fixed:
        - controller scsi_status values did not match
          the ones used by the spsipi layer.
          a mapping function was introduced.
        - when experiencing an underrun (read 64k and
          get a 63k block) the controller posted
          not a SUCCESS status but CHECK status. handle
          that like SUCCESS adjusting xs->resid and set
          XS_SENSE.
          now the correct data amount is returned and
          nothing is 'added' and no 'generic HBA error'
          occurs.
        - make decisions using variables and constants
          from the controller domain.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/pci/mpii.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/mpii.c
diff -u src/sys/dev/pci/mpii.c:1.2 src/sys/dev/pci/mpii.c:1.3
--- src/sys/dev/pci/mpii.c:1.2	Thu Aug  8 07:06:13 2013
+++ src/sys/dev/pci/mpii.c	Fri Aug  9 19:51:29 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: mpii.c,v 1.2 2013/08/08 07:06:13 kardel Exp $ */
+/* $NetBSD: mpii.c,v 1.3 2013/08/09 19:51:29 kardel Exp $ */
 /*	OpenBSD: mpii.c,v 1.51 2012/04/11 13:29:14 naddy Exp 	*/
 /*
  * Copyright (c) 2010 Mike Belopuhov <m...@crypt.org.ru>
@@ -20,7 +20,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mpii.c,v 1.2 2013/08/08 07:06:13 kardel Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mpii.c,v 1.3 2013/08/09 19:51:29 kardel Exp $");
 
 #include "bio.h"
 
@@ -790,18 +790,18 @@ struct mpii_msg_scsi_io_error {
 	u_int16_t		reserved3;
 
 	u_int8_t		scsi_status;
-	/* XXX JPG validate this */
-#if notyet
-#define MPII_SCSIIO_ERR_STATUS_SUCCESS
-#define MPII_SCSIIO_ERR_STATUS_CHECK_COND
-#define MPII_SCSIIO_ERR_STATUS_BUSY
-#define MPII_SCSIIO_ERR_STATUS_INTERMEDIATE
-#define MPII_SCSIIO_ERR_STATUS_INTERMEDIATE_CONDMET
-#define MPII_SCSIIO_ERR_STATUS_RESERVATION_CONFLICT
-#define MPII_SCSIIO_ERR_STATUS_CMD_TERM
-#define MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL
-#define MPII_SCSIIO_ERR_STATUS_ACA_ACTIVE
-#endif
+
+#define MPII_SCSIIO_ERR_STATUS_SUCCESS			(0x00)
+#define MPII_SCSIIO_ERR_STATUS_CHECK_COND		(0x02)
+#define MPII_SCSIIO_ERR_STATUS_BUSY			(0x04)
+#define MPII_SCSIIO_ERR_STATUS_INTERMEDIATE		(0x08)
+#define MPII_SCSIIO_ERR_STATUS_INTERMEDIATE_CONDMET	(0x10)
+#define MPII_SCSIIO_ERR_STATUS_RESERVATION_CONFLICT	(0x14)
+#define MPII_SCSIIO_ERR_STATUS_CMD_TERM			(0x22)
+#define MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL		(0x28)
+#define MPII_SCSIIO_ERR_STATUS_ACA_ACTIVE		(0x30)
+#define MPII_SCSIIO_ERR_STATUS_TASK_ABORTED		(0x40)
+
 	u_int8_t		scsi_state;
 #define MPII_SCSIIO_ERR_STATE_AUTOSENSE_VALID		(1<<0)
 #define MPII_SCSIIO_ERR_STATE_AUTOSENSE_FAILED		(1<<1)
@@ -4682,6 +4682,58 @@ mpii_scsi_cmd_tmo_done(struct mpii_ccb *
         mpii_put_ccb(tccb->ccb_sc, tccb);
 }
 
+static u_int8_t
+map_scsi_status(u_int8_t mpii_scsi_status)
+{
+	u_int8_t scsi_status;
+	
+	switch (mpii_scsi_status) 
+	{
+	case MPII_SCSIIO_ERR_STATUS_SUCCESS:
+		scsi_status = SCSI_OK;
+		break;
+		
+	case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
+		scsi_status = SCSI_CHECK;
+		break;
+		
+	case MPII_SCSIIO_ERR_STATUS_BUSY:
+		scsi_status = SCSI_BUSY;
+		break;
+		
+	case MPII_SCSIIO_ERR_STATUS_INTERMEDIATE:
+		scsi_status = SCSI_INTERM;
+		break;
+		
+	case MPII_SCSIIO_ERR_STATUS_INTERMEDIATE_CONDMET:
+		scsi_status = SCSI_INTERM;
+		break;
+		
+	case MPII_SCSIIO_ERR_STATUS_RESERVATION_CONFLICT:
+		scsi_status = SCSI_RESV_CONFLICT;
+		break;
+		
+	case MPII_SCSIIO_ERR_STATUS_CMD_TERM:
+	case MPII_SCSIIO_ERR_STATUS_TASK_ABORTED:
+		scsi_status = SCSI_TERMINATED;
+		break;
+
+	case MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL:
+		scsi_status = SCSI_QUEUE_FULL;
+		break;
+
+	case MPII_SCSIIO_ERR_STATUS_ACA_ACTIVE:
+		scsi_status = SCSI_ACA_ACTIVE;
+		break;
+
+	default:
+		/* XXX: for the lack of anything better and other than OK */
+		scsi_status = 0xFF;
+		break;
+	}
+
+	return scsi_status;
+}
 
 static void
 mpii_scsi_cmd_done(struct mpii_ccb *ccb)
@@ -4745,31 +4797,43 @@ mpii_scsi_cmd_done(struct mpii_ccb *ccb)
 	DNPRINTF(MPII_D_CMD, "%s:  bidirectional_transfer_count: 0x%08x\n",
 	    DEVNAME(sc), le32toh(sie->bidirectional_transfer_count));
 
-	xs->status = sie->scsi_status;
+	xs->status = map_scsi_status(sie->scsi_status);
+
 	switch (le16toh(sie->ioc_status) & MPII_IOCSTATUS_MASK) {
 	case MPII_IOCSTATUS_SCSI_DATA_UNDERRUN:
-		switch (xs->status) {
-		case SCSI_OK:
+		switch (sie->scsi_status) {
+		case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
+			xs->error = XS_SENSE;
+			/*FALLTHROUGH*/
+		case MPII_SCSIIO_ERR_STATUS_SUCCESS:
 			xs->resid = xs->datalen - le32toh(sie->transfer_count);
 			break;
+
 		default:
 			xs->error = XS_DRIVER_STUFFUP;
 			break;
 		}
 		break;
+
 	case MPII_IOCSTATUS_SUCCESS:
 	case MPII_IOCSTATUS_SCSI_RECOVERED_ERROR:
-		switch (xs->status) {
-		case SCSI_OK:
-			xs->resid = 0;
+		switch (sie->scsi_status) {
+		case MPII_SCSIIO_ERR_STATUS_SUCCESS:
+			/*
+			 * xs->resid = 0; - already set above
+			 *
+			 * XXX: check whether UNDERUN strategy
+			 * would be appropriate here too.
+			 * that would allow joining these cases.
+			 */
 			break;
 
-		case SCSI_CHECK:
+		case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
 			xs->error = XS_SENSE;
 			break;
-
-		case SCSI_BUSY:
-		case SCSI_QUEUE_FULL:
+			
+		case MPII_SCSIIO_ERR_STATUS_BUSY:
+		case MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL:
 			xs->error = XS_BUSY;
 			break;
 

Reply via email to