Browse Source

[scsi] Improve sense code parsing

Parse the sense data to extract the reponse code, the sense key, the
additional sense code, and the additional sense code qualifier.

Originally-implemented-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
e047811c85
5 changed files with 93 additions and 19 deletions
  1. 31
    3
      src/drivers/block/scsi.c
  2. 6
    5
      src/drivers/block/srp.c
  3. 47
    4
      src/include/ipxe/scsi.h
  4. 2
    3
      src/net/fcp.c
  5. 7
    4
      src/net/tcp/iscsi.c

+ 31
- 3
src/drivers/block/scsi.c View File

132
 	return 0;
132
 	return 0;
133
 }
133
 }
134
 
134
 
135
+/**
136
+ * Parse SCSI sense data
137
+ *
138
+ * @v data		Raw sense data
139
+ * @v len		Length of raw sense data
140
+ * @v sense		Descriptor-format sense data to fill in
141
+ */
142
+void scsi_parse_sense ( const void *data, size_t len,
143
+			struct scsi_sns_descriptor *sense ) {
144
+	const union scsi_sns *sns = data;
145
+
146
+	/* Avoid returning uninitialised data */
147
+	memset ( sense, 0, sizeof ( *sense ) );
148
+
149
+	/* Copy, assuming descriptor-format data */
150
+	if ( len < sizeof ( sns->desc ) )
151
+		return;
152
+	memcpy ( sense, &sns->desc, sizeof ( *sense ) );
153
+
154
+	/* Convert fixed-format to descriptor-format, if applicable */
155
+	if ( len < sizeof ( sns->fixed ) )
156
+		return;
157
+	if ( ! SCSI_SENSE_FIXED ( sns->code ) )
158
+		return;
159
+	sense->additional = sns->fixed.additional;
160
+}
161
+
135
 /******************************************************************************
162
 /******************************************************************************
136
  *
163
  *
137
  * Interface methods
164
  * Interface methods
468
 			underrun = -(response->overrun);
495
 			underrun = -(response->overrun);
469
 			DBGC ( scsidev, " underrun -%zd", underrun );
496
 			DBGC ( scsidev, " underrun -%zd", underrun );
470
 		}
497
 		}
471
-		DBGC ( scsidev, " sense %02x:%02x:%08x\n",
472
-		       response->sense.code, response->sense.key,
473
-		       ntohl ( response->sense.info ) );
498
+		DBGC ( scsidev, " sense %02x key %02x additional %04x\n",
499
+		       ( response->sense.code & SCSI_SENSE_CODE_MASK ),
500
+		       ( response->sense.key & SCSI_SENSE_KEY_MASK ),
501
+		       ntohs ( response->sense.additional ) );
474
 
502
 
475
 		/* Construct error number from sense data */
503
 		/* Construct error number from sense data */
476
 		rc = -EIO_SENSE ( response->sense.key & SCSI_SENSE_KEY_MASK );
504
 		rc = -EIO_SENSE ( response->sense.key & SCSI_SENSE_KEY_MASK );

+ 6
- 5
src/drivers/block/srp.c View File

476
 	const struct srp_rsp *rsp = data;
476
 	const struct srp_rsp *rsp = data;
477
 	struct srp_command *srpcmd;
477
 	struct srp_command *srpcmd;
478
 	struct scsi_rsp response;
478
 	struct scsi_rsp response;
479
-	const void *sense;
480
 	ssize_t data_out_residual_count;
479
 	ssize_t data_out_residual_count;
481
 	ssize_t data_in_residual_count;
480
 	ssize_t data_in_residual_count;
482
 
481
 
483
 	/* Sanity check */
482
 	/* Sanity check */
484
-	if ( len < sizeof ( *rsp ) ) {
483
+	if ( ( len < sizeof ( *rsp ) ) ||
484
+	     ( len < ( sizeof ( *rsp ) +
485
+		       srp_rsp_response_data_len ( rsp ) +
486
+		       srp_rsp_sense_data_len ( rsp ) ) ) ) {
485
 		DBGC ( srpdev, "SRP %p RSP too short (%zd bytes)\n",
487
 		DBGC ( srpdev, "SRP %p RSP too short (%zd bytes)\n",
486
 		       srpdev, len );
488
 		       srpdev, len );
487
 		return -EINVAL;
489
 		return -EINVAL;
523
 	} else if ( rsp->valid & SRP_RSP_VALID_DIUNDER ) {
525
 	} else if ( rsp->valid & SRP_RSP_VALID_DIUNDER ) {
524
 		response.overrun = -(data_in_residual_count);
526
 		response.overrun = -(data_in_residual_count);
525
 	}
527
 	}
526
-	sense = srp_rsp_sense_data ( rsp );
527
-	if ( sense )
528
-		memcpy ( &response.sense, sense, sizeof ( response.sense ) );
528
+	scsi_parse_sense ( srp_rsp_sense_data ( rsp ),
529
+			   srp_rsp_sense_data_len ( rsp ), &response.sense );
529
 
530
 
530
 	/* Report SCSI response */
531
 	/* Report SCSI response */
531
 	scsi_response ( &srpcmd->scsi, &response );
532
 	scsi_response ( &srpcmd->scsi, &response );

+ 47
- 4
src/include/ipxe/scsi.h View File

267
 	size_t data_in_len;
267
 	size_t data_in_len;
268
 };
268
 };
269
 
269
 
270
-/** SCSI sense data */
271
-struct scsi_sns {
270
+/** SCSI fixed-format sense data */
271
+struct scsi_sns_fixed {
272
 	/** Response code */
272
 	/** Response code */
273
 	uint8_t code;
273
 	uint8_t code;
274
 	/** Reserved */
274
 	/** Reserved */
277
 	uint8_t key;
277
 	uint8_t key;
278
 	/** Information */
278
 	/** Information */
279
 	uint32_t info;
279
 	uint32_t info;
280
+	/** Additional sense length */
281
+	uint8_t len;
282
+	/** Command-specific information */
283
+	uint32_t cs_info;
284
+	/** Additional sense code and qualifier */
285
+	uint16_t additional;
286
+} __attribute__ (( packed ));
287
+
288
+/** SCSI descriptor-format sense data */
289
+struct scsi_sns_descriptor {
290
+	/** Response code */
291
+	uint8_t code;
292
+	/** Sense key */
293
+	uint8_t key;
294
+	/** Additional sense code and qualifier */
295
+	uint16_t additional;
296
+} __attribute__ (( packed ));
297
+
298
+/** SCSI sense data */
299
+union scsi_sns {
300
+	/** Response code */
301
+	uint8_t code;
302
+	/** Fixed-format sense data */
303
+	struct scsi_sns_fixed fixed;
304
+	/** Descriptor-format sense data */
305
+	struct scsi_sns_descriptor desc;
280
 };
306
 };
281
 
307
 
308
+/** SCSI sense response code mask */
309
+#define SCSI_SENSE_CODE_MASK 0x7f
310
+
311
+/** Test if SCSI sense data is in fixed format
312
+ *
313
+ * @v code		Response code
314
+ * @ret is_fixed	Sense data is in fixed format
315
+ */
316
+#define SCSI_SENSE_FIXED( code ) ( ( (code) & 0x7e ) == 0x70 )
317
+
282
 /** SCSI sense key mask */
318
 /** SCSI sense key mask */
283
 #define SCSI_SENSE_KEY_MASK 0x0f
319
 #define SCSI_SENSE_KEY_MASK 0x0f
284
 
320
 
288
 	uint8_t status;
324
 	uint8_t status;
289
 	/** Data overrun (or negative underrun) */
325
 	/** Data overrun (or negative underrun) */
290
 	ssize_t overrun;
326
 	ssize_t overrun;
291
-	/** Autosense data (if any) */
292
-	struct scsi_sns sense;
327
+	/** Autosense data (if any)
328
+	 *
329
+	 * To minimise code size, this is stored as the first four
330
+	 * bytes of a descriptor-format sense data block (even if the
331
+	 * response code indicates fixed-format sense data).
332
+	 */
333
+	struct scsi_sns_descriptor sense;
293
 };
334
 };
294
 
335
 
295
 extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun );
336
 extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun );
337
+extern void scsi_parse_sense ( const void *data, size_t len,
338
+			       struct scsi_sns_descriptor *sense );
296
 
339
 
297
 extern int scsi_command ( struct interface *control, struct interface *data,
340
 extern int scsi_command ( struct interface *control, struct interface *data,
298
 			  struct scsi_cmd *command );
341
 			  struct scsi_cmd *command );

+ 2
- 3
src/net/fcp.c View File

551
 	struct fcp_device *fcpdev = fcpcmd->fcpdev;
551
 	struct fcp_device *fcpdev = fcpcmd->fcpdev;
552
 	struct scsi_cmd *command = &fcpcmd->command;
552
 	struct scsi_cmd *command = &fcpcmd->command;
553
 	struct fcp_rsp *rsp = iobuf->data;
553
 	struct fcp_rsp *rsp = iobuf->data;
554
-	struct scsi_sense *sense;
555
 	struct scsi_rsp response;
554
 	struct scsi_rsp response;
556
 	int rc;
555
 	int rc;
557
 
556
 
607
 		if ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN )
606
 		if ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN )
608
 			response.overrun = -response.overrun;
607
 			response.overrun = -response.overrun;
609
 	}
608
 	}
610
-	if ( ( sense = fcp_rsp_sense_data ( rsp ) ) != NULL )
611
-		memcpy ( &response.sense, sense, sizeof ( response.sense ) );
609
+	scsi_parse_sense ( fcp_rsp_sense_data ( rsp ),
610
+			   fcp_rsp_sense_data_len ( rsp ), &response.sense );
612
 
611
 
613
 	/* Free buffer before sending response, to minimise
612
 	/* Free buffer before sending response, to minimise
614
 	 * out-of-memory errors.
613
 	 * out-of-memory errors.

+ 7
- 4
src/net/tcp/iscsi.c View File

412
 		= &iscsi->rx_bhs.scsi_response;
412
 		= &iscsi->rx_bhs.scsi_response;
413
 	struct scsi_rsp rsp;
413
 	struct scsi_rsp rsp;
414
 	uint32_t residual_count;
414
 	uint32_t residual_count;
415
+	size_t data_len;
415
 	int rc;
416
 	int rc;
416
 
417
 
417
 	/* Buffer up the PDU data */
418
 	/* Buffer up the PDU data */
418
 	if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
419
 	if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
419
-		DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
420
+		DBGC ( iscsi, "iSCSI %p could not buffer SCSI response: %s\n",
420
 		       iscsi, strerror ( rc ) );
421
 		       iscsi, strerror ( rc ) );
421
 		return rc;
422
 		return rc;
422
 	}
423
 	}
432
 	} else if ( response->flags & ISCSI_DATA_FLAG_UNDERFLOW ) {
433
 	} else if ( response->flags & ISCSI_DATA_FLAG_UNDERFLOW ) {
433
 		rsp.overrun = -(residual_count);
434
 		rsp.overrun = -(residual_count);
434
 	}
435
 	}
435
-	if ( ISCSI_DATA_LEN ( response->lengths ) )
436
-		memcpy ( &rsp.sense, ( iscsi->rx_buffer + 2 ),
437
-			 sizeof ( rsp.sense ) );
436
+	data_len = ISCSI_DATA_LEN ( response->lengths );
437
+	if ( data_len ) {
438
+		scsi_parse_sense ( ( iscsi->rx_buffer + 2 ), ( data_len - 2 ),
439
+				   &rsp.sense );
440
+	}
438
 	iscsi_rx_buffered_data_done ( iscsi );
441
 	iscsi_rx_buffered_data_done ( iscsi );
439
 
442
 
440
 	/* Check for errors */
443
 	/* Check for errors */

Loading…
Cancel
Save