Revision 6dc06f08 hw/scsi-bus.c

b/hw/scsi-bus.c
149 149
    .send_command = scsi_invalid_command
150 150
};
151 151

  
152
/* SCSIReqOps implementation for unit attention conditions.  */
153

  
154
static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
155
{
156
    if (req->dev && req->dev->unit_attention.key == UNIT_ATTENTION) {
157
        scsi_req_build_sense(req, req->dev->unit_attention);
158
    } else if (req->bus->unit_attention.key == UNIT_ATTENTION) {
159
        scsi_req_build_sense(req, req->bus->unit_attention);
160
    }
161
    scsi_req_complete(req, CHECK_CONDITION);
162
    return 0;
163
}
164

  
165
struct SCSIReqOps reqops_unit_attention = {
166
    .size         = sizeof(SCSIRequest),
167
    .send_command = scsi_unit_attention
168
};
169

  
152 170
/* SCSIReqOps implementation for REPORT LUNS and for commands sent to
153 171
   an invalid LUN.  */
154 172

  
......
344 362
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
345 363
                          uint8_t *buf, void *hba_private)
346 364
{
365
    SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
347 366
    SCSIRequest *req;
348 367
    SCSICommand cmd;
349 368

  
......
358 377
                                      cmd.lba);
359 378
        }
360 379

  
361
        if (lun != d->lun ||
380
        if ((d->unit_attention.key == UNIT_ATTENTION ||
381
             bus->unit_attention.key == UNIT_ATTENTION) &&
382
            (buf[0] != INQUIRY &&
383
             buf[0] != REPORT_LUNS &&
384
             buf[0] != GET_CONFIGURATION &&
385
             buf[0] != GET_EVENT_STATUS_NOTIFICATION)) {
386
            req = scsi_req_alloc(&reqops_unit_attention, d, tag, lun,
387
                                 hba_private);
388
        } else if (lun != d->lun ||
362 389
            buf[0] == REPORT_LUNS ||
363 390
            buf[0] == REQUEST_SENSE) {
364 391
            req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
......
377 404
    return req->ops->get_buf(req);
378 405
}
379 406

  
407
static void scsi_clear_unit_attention(SCSIRequest *req)
408
{
409
    SCSISense *ua;
410
    if (req->dev->unit_attention.key != UNIT_ATTENTION &&
411
        req->bus->unit_attention.key != UNIT_ATTENTION) {
412
        return;
413
    }
414

  
415
    /*
416
     * If an INQUIRY command enters the enabled command state,
417
     * the device server shall [not] clear any unit attention condition;
418
     * See also MMC-6, paragraphs 6.5 and 6.6.2.
419
     */
420
    if (req->cmd.buf[0] == INQUIRY ||
421
        req->cmd.buf[0] == GET_CONFIGURATION ||
422
        req->cmd.buf[0] == GET_EVENT_STATUS_NOTIFICATION) {
423
        return;
424
    }
425

  
426
    if (req->dev->unit_attention.key == UNIT_ATTENTION) {
427
        ua = &req->dev->unit_attention;
428
    } else {
429
        ua = &req->bus->unit_attention;
430
    }
431

  
432
    /*
433
     * If a REPORT LUNS command enters the enabled command state, [...]
434
     * the device server shall clear any pending unit attention condition
435
     * with an additional sense code of REPORTED LUNS DATA HAS CHANGED.
436
     */
437
    if (req->cmd.buf[0] == REPORT_LUNS &&
438
        !(ua->asc == SENSE_CODE(REPORTED_LUNS_CHANGED).asc &&
439
          ua->ascq == SENSE_CODE(REPORTED_LUNS_CHANGED).ascq)) {
440
        return;
441
    }
442

  
443
    *ua = SENSE_CODE(NO_SENSE);
444
}
445

  
380 446
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
381 447
{
448
    int ret;
449

  
382 450
    assert(len >= 14);
383 451
    if (!req->sense_len) {
384 452
        return 0;
385 453
    }
386
    return scsi_build_sense(req->sense, req->sense_len, buf, len, true);
454

  
455
    ret = scsi_build_sense(req->sense, req->sense_len, buf, len, true);
456

  
457
    /*
458
     * FIXME: clearing unit attention conditions upon autosense should be done
459
     * only if the UA_INTLCK_CTRL field in the Control mode page is set to 00b
460
     * (SAM-5, 5.14).
461
     *
462
     * We assume UA_INTLCK_CTRL to be 00b for HBAs that support autosense, and
463
     * 10b for HBAs that do not support it (do not call scsi_req_get_sense).
464
     * In the latter case, scsi_req_complete clears unit attention conditions
465
     * after moving them to the device's sense buffer.
466
     */
467
    scsi_clear_unit_attention(req);
468
    return ret;
387 469
}
388 470

  
389 471
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed)
......
983 1065
    }
984 1066
    req->dev->sense_len = req->sense_len;
985 1067

  
1068
    /*
1069
     * Unit attention state is now stored in the device's sense buffer
1070
     * if the HBA didn't do autosense.  Clear the pending unit attention
1071
     * flags.
1072
     */
1073
    scsi_clear_unit_attention(req);
1074

  
986 1075
    scsi_req_ref(req);
987 1076
    scsi_req_dequeue(req);
988 1077
    req->bus->ops->complete(req, req->status);

Also available in: Unified diff