|
@@ -93,6 +93,8 @@ static const char *scsi_debug_version_date = "20141022";
|
|
|
#define THRESHOLD_EXCEEDED 0x5d
|
|
|
#define LOW_POWER_COND_ON 0x5e
|
|
|
#define MISCOMPARE_VERIFY_ASC 0x1d
|
|
|
+#define MICROCODE_CHANGED_ASCQ 0x1 /* with TARGET_CHANGED_ASC */
|
|
|
+#define MICROCODE_CHANGED_WO_RESET_ASCQ 0x16
|
|
|
|
|
|
/* Additional Sense Code Qualifier (ASCQ) */
|
|
|
#define ACK_NAK_TO 0x3
|
|
@@ -183,7 +185,9 @@ static const char *scsi_debug_version_date = "20141022";
|
|
|
#define SDEBUG_UA_MODE_CHANGED 2
|
|
|
#define SDEBUG_UA_CAPACITY_CHANGED 3
|
|
|
#define SDEBUG_UA_LUNS_CHANGED 4
|
|
|
-#define SDEBUG_NUM_UAS 5
|
|
|
+#define SDEBUG_UA_MICROCODE_CHANGED 5 /* simulate firmware change */
|
|
|
+#define SDEBUG_UA_MICROCODE_CHANGED_WO_RESET 6
|
|
|
+#define SDEBUG_NUM_UAS 7
|
|
|
|
|
|
/* for check_readiness() */
|
|
|
#define UAS_ONLY 1 /* check for UAs only */
|
|
@@ -329,6 +333,7 @@ static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
|
|
|
static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
|
|
|
static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
|
|
|
static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
|
|
|
+static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
|
|
|
|
|
|
struct opcode_info_t {
|
|
|
u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff
|
|
@@ -483,8 +488,9 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
|
|
|
{0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10,
|
|
|
NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7,
|
|
|
0, 0, 0, 0, 0, 0} },
|
|
|
- {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* WRITE_BUFFER */
|
|
|
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
|
|
|
+ {0, 0x3b, 0, F_D_OUT_MAYBE, resp_write_buffer, NULL,
|
|
|
+ {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0,
|
|
|
+ 0, 0, 0, 0} }, /* WRITE_BUFFER */
|
|
|
{1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10,
|
|
|
write_same_iarr, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
|
|
|
0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
|
|
@@ -836,6 +842,19 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
|
|
|
if (debug)
|
|
|
cp = "capacity data changed";
|
|
|
break;
|
|
|
+ case SDEBUG_UA_MICROCODE_CHANGED:
|
|
|
+ mk_sense_buffer(SCpnt, UNIT_ATTENTION,
|
|
|
+ TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ);
|
|
|
+ if (debug)
|
|
|
+ cp = "microcode has been changed";
|
|
|
+ break;
|
|
|
+ case SDEBUG_UA_MICROCODE_CHANGED_WO_RESET:
|
|
|
+ mk_sense_buffer(SCpnt, UNIT_ATTENTION,
|
|
|
+ TARGET_CHANGED_ASC,
|
|
|
+ MICROCODE_CHANGED_WO_RESET_ASCQ);
|
|
|
+ if (debug)
|
|
|
+ cp = "microcode has been changed without reset";
|
|
|
+ break;
|
|
|
case SDEBUG_UA_LUNS_CHANGED:
|
|
|
/*
|
|
|
* SPC-3 behavior is to report a UNIT ATTENTION with
|
|
@@ -3069,6 +3088,55 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
|
|
|
return resp_write_same(scp, lba, num, ei_lba, unmap, ndob);
|
|
|
}
|
|
|
|
|
|
+/* Note the mode field is in the same position as the (lower) service action
|
|
|
+ * field. For the Report supported operation codes command, SPC-4 suggests
|
|
|
+ * each mode of this command should be reported separately; for future. */
|
|
|
+static int
|
|
|
+resp_write_buffer(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
|
|
|
+{
|
|
|
+ u8 *cmd = scp->cmnd;
|
|
|
+ struct scsi_device *sdp = scp->device;
|
|
|
+ struct sdebug_dev_info *dp;
|
|
|
+ u8 mode;
|
|
|
+
|
|
|
+ mode = cmd[1] & 0x1f;
|
|
|
+ switch (mode) {
|
|
|
+ case 0x4: /* download microcode (MC) and activate (ACT) */
|
|
|
+ /* set UAs on this device only */
|
|
|
+ set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
|
|
|
+ set_bit(SDEBUG_UA_MICROCODE_CHANGED, devip->uas_bm);
|
|
|
+ break;
|
|
|
+ case 0x5: /* download MC, save and ACT */
|
|
|
+ set_bit(SDEBUG_UA_MICROCODE_CHANGED_WO_RESET, devip->uas_bm);
|
|
|
+ break;
|
|
|
+ case 0x6: /* download MC with offsets and ACT */
|
|
|
+ /* set UAs on most devices (LUs) in this target */
|
|
|
+ list_for_each_entry(dp,
|
|
|
+ &devip->sdbg_host->dev_info_list,
|
|
|
+ dev_list)
|
|
|
+ if (dp->target == sdp->id) {
|
|
|
+ set_bit(SDEBUG_UA_BUS_RESET, dp->uas_bm);
|
|
|
+ if (devip != dp)
|
|
|
+ set_bit(SDEBUG_UA_MICROCODE_CHANGED,
|
|
|
+ dp->uas_bm);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 0x7: /* download MC with offsets, save, and ACT */
|
|
|
+ /* set UA on all devices (LUs) in this target */
|
|
|
+ list_for_each_entry(dp,
|
|
|
+ &devip->sdbg_host->dev_info_list,
|
|
|
+ dev_list)
|
|
|
+ if (dp->target == sdp->id)
|
|
|
+ set_bit(SDEBUG_UA_MICROCODE_CHANGED_WO_RESET,
|
|
|
+ dp->uas_bm);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* do nothing for this command for other mode values */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
|
|
|
{
|