@@ -439,19 +439,23 @@ struct SCSITargetReq {
static void store_lun(uint8_t *outbuf, int lun)
{
if (lun < 256) {
+ /* Simple logical unit addressing method*/
+ outbuf[0] = 0;
outbuf[1] = lun;
- return;
+ } else {
+ /* Flat space addressing method */
+ outbuf[0] = 0x40 | (lun >> 8);
+ outbuf[1] = (lun & 255);
}
- outbuf[1] = (lun & 255);
- outbuf[0] = (lun >> 8) | 0x40;
}
static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
{
BusChild *kid;
- int i, len, n;
int channel, id;
- bool found_lun0;
+ uint8_t tmp[8] = {0};
+ int len = 0;
+ GByteArray *buf;
if (r->req.cmd.xfer < 16) {
return false;
@@ -459,48 +463,41 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
if (r->req.cmd.buf[2] > 2) {
return false;
}
+
+ /* reserve space for 63 LUNs*/
+ buf = g_byte_array_sized_new(512);
+
channel = r->req.dev->channel;
id = r->req.dev->id;
- found_lun0 = false;
- n = 0;
- rcu_read_lock();
+ /* add size (will be updated later to correct value */
+ g_byte_array_append(buf, tmp, 8);
+ len += 8;
- QTAILQ_FOREACH_RCU(kid, &r->req.bus->qbus.children, sibling) {
- DeviceState *qdev = kid->child;
- SCSIDevice *dev = SCSI_DEVICE(qdev);
+ /* add LUN0 */
+ g_byte_array_append(buf, tmp, 8);
+ len += 8;
- if (dev->channel == channel && dev->id == id) {
- if (dev->lun == 0) {
- found_lun0 = true;
- }
- n += 8;
- }
- }
- if (!found_lun0) {
- n += 8;
- }
-
- scsi_target_alloc_buf(&r->req, n + 8);
-
- len = MIN(n + 8, r->req.cmd.xfer & ~7);
- memset(r->buf, 0, len);
- stl_be_p(&r->buf[0], n);
- i = found_lun0 ? 8 : 16;
+ rcu_read_lock();
QTAILQ_FOREACH_RCU(kid, &r->req.bus->qbus.children, sibling) {
DeviceState *qdev = kid->child;
SCSIDevice *dev = SCSI_DEVICE(qdev);
- if (dev->channel == channel && dev->id == id) {
- store_lun(&r->buf[i], dev->lun);
- i += 8;
+ if (dev->channel == channel && dev->id == id && dev->lun != 0) {
+ store_lun(tmp, dev->lun);
+ g_byte_array_append(buf, tmp, 8);
+ len += 8;
}
}
-
rcu_read_unlock();
- assert(i == n + 8);
- r->len = len;
+ r->buf_len = len;
+ r->buf = g_byte_array_free(buf, FALSE);
+ r->len = MIN(len, r->req.cmd.xfer & ~7);
+
+ /* store the LUN list length */
+ stl_be_p(&r->buf[0], len - 8);
+
return true;
}