Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
54dcd0b3
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
54dcd0b3
编写于
11月 18, 2011
作者:
A
Anthony Liguori
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'kwolf/block-stable' into staging
上级
7197390a
33ebad12
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
209 addition
and
44 deletion
+209
-44
hw/ide/atapi.c
hw/ide/atapi.c
+8
-12
hw/scsi-bus.c
hw/scsi-bus.c
+108
-20
hw/scsi-defs.h
hw/scsi-defs.h
+9
-1
hw/scsi-disk.c
hw/scsi-disk.c
+26
-11
hw/scsi.h
hw/scsi.h
+2
-0
qemu-doc.texi
qemu-doc.texi
+56
-0
未找到文件。
hw/ide/atapi.c
浏览文件 @
54dcd0b3
...
...
@@ -695,12 +695,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
int
action
,
code
;
int
max_len
;
if
(
buf
[
0
]
==
GPCMD_MODE_SENSE_10
)
{
max_len
=
ube16_to_cpu
(
buf
+
7
);
}
else
{
max_len
=
buf
[
4
];
}
max_len
=
ube16_to_cpu
(
buf
+
7
);
action
=
buf
[
2
]
>>
6
;
code
=
buf
[
2
]
&
0x3f
;
...
...
@@ -708,7 +703,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
case
0
:
/* current values */
switch
(
code
)
{
case
MODE_PAGE_R_W_ERROR
:
/* error recovery */
cpu_to_ube16
(
&
buf
[
0
],
16
+
6
);
cpu_to_ube16
(
&
buf
[
0
],
16
-
2
);
buf
[
2
]
=
0x70
;
buf
[
3
]
=
0
;
buf
[
4
]
=
0
;
...
...
@@ -727,7 +722,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
ide_atapi_cmd_reply
(
s
,
16
,
max_len
);
break
;
case
MODE_PAGE_AUDIO_CTL
:
cpu_to_ube16
(
&
buf
[
0
],
24
+
6
);
cpu_to_ube16
(
&
buf
[
0
],
24
-
2
);
buf
[
2
]
=
0x70
;
buf
[
3
]
=
0
;
buf
[
4
]
=
0
;
...
...
@@ -746,7 +741,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
ide_atapi_cmd_reply
(
s
,
24
,
max_len
);
break
;
case
MODE_PAGE_CAPABILITIES
:
cpu_to_ube16
(
&
buf
[
0
],
28
+
6
);
cpu_to_ube16
(
&
buf
[
0
],
30
-
2
);
buf
[
2
]
=
0x70
;
buf
[
3
]
=
0
;
buf
[
4
]
=
0
;
...
...
@@ -755,7 +750,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
buf
[
7
]
=
0
;
buf
[
8
]
=
MODE_PAGE_CAPABILITIES
;
buf
[
9
]
=
28
-
10
;
buf
[
9
]
=
30
-
10
;
buf
[
10
]
=
0x3b
;
/* read CDR/CDRW/DVDROM/DVDR/DVDRAM */
buf
[
11
]
=
0x00
;
...
...
@@ -777,7 +772,9 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
buf
[
25
]
=
0
;
buf
[
26
]
=
0
;
buf
[
27
]
=
0
;
ide_atapi_cmd_reply
(
s
,
28
,
max_len
);
buf
[
28
]
=
0
;
buf
[
29
]
=
0
;
ide_atapi_cmd_reply
(
s
,
30
,
max_len
);
break
;
default:
goto
error_cmd
;
...
...
@@ -1043,7 +1040,6 @@ static const struct {
[
0x00
]
=
{
cmd_test_unit_ready
,
CHECK_READY
},
[
0x03
]
=
{
cmd_request_sense
,
ALLOW_UA
},
[
0x12
]
=
{
cmd_inquiry
,
ALLOW_UA
},
[
0x1a
]
=
{
cmd_mode_sense
,
/* (6) */
0
},
[
0x1b
]
=
{
cmd_start_stop_unit
,
0
},
/* [1] */
[
0x1e
]
=
{
cmd_prevent_allow_medium_removal
,
0
},
[
0x25
]
=
{
cmd_read_cdvd_capacity
,
CHECK_READY
},
...
...
hw/scsi-bus.c
浏览文件 @
54dcd0b3
...
...
@@ -9,8 +9,6 @@
static
char
*
scsibus_get_fw_dev_path
(
DeviceState
*
dev
);
static
int
scsi_req_parse
(
SCSICommand
*
cmd
,
SCSIDevice
*
dev
,
uint8_t
*
buf
);
static
void
scsi_req_dequeue
(
SCSIRequest
*
req
);
static
int
scsi_build_sense
(
uint8_t
*
in_buf
,
int
in_len
,
uint8_t
*
buf
,
int
len
,
bool
fixed
);
static
struct
BusInfo
scsi_bus_info
=
{
.
name
=
"SCSI"
,
...
...
@@ -502,7 +500,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
hba_private
);
}
else
if
(
lun
!=
d
->
lun
||
buf
[
0
]
==
REPORT_LUNS
||
buf
[
0
]
==
REQUEST_SENSE
)
{
(
buf
[
0
]
==
REQUEST_SENSE
&&
(
d
->
sense_len
||
cmd
.
xfer
<
4
))
)
{
req
=
scsi_req_alloc
(
&
reqops_target_command
,
d
,
tag
,
lun
,
hba_private
);
}
else
{
...
...
@@ -649,6 +647,31 @@ static void scsi_req_dequeue(SCSIRequest *req)
}
}
static
int
scsi_get_performance_length
(
int
num_desc
,
int
type
,
int
data_type
)
{
/* MMC-6, paragraph 6.7. */
switch
(
type
)
{
case
0
:
if
((
data_type
&
3
)
==
0
)
{
/* Each descriptor is as in Table 295 - Nominal performance. */
return
16
*
num_desc
+
8
;
}
else
{
/* Each descriptor is as in Table 296 - Exceptions. */
return
6
*
num_desc
+
8
;
}
case
1
:
case
4
:
case
5
:
return
8
*
num_desc
+
8
;
case
2
:
return
2048
*
num_desc
+
8
;
case
3
:
return
16
*
num_desc
+
8
;
default:
return
8
;
}
}
static
int
scsi_req_length
(
SCSICommand
*
cmd
,
SCSIDevice
*
dev
,
uint8_t
*
buf
)
{
switch
(
buf
[
0
]
>>
5
)
{
...
...
@@ -666,11 +689,11 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
cmd
->
len
=
10
;
break
;
case
4
:
cmd
->
xfer
=
ldl_be_p
(
&
buf
[
10
]);
cmd
->
xfer
=
ldl_be_p
(
&
buf
[
10
])
&
0xffffffffULL
;
cmd
->
len
=
16
;
break
;
case
5
:
cmd
->
xfer
=
ldl_be_p
(
&
buf
[
6
]);
cmd
->
xfer
=
ldl_be_p
(
&
buf
[
6
])
&
0xffffffffULL
;
cmd
->
len
=
12
;
break
;
default:
...
...
@@ -681,8 +704,9 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case
TEST_UNIT_READY
:
case
REWIND
:
case
START_STOP
:
case
SE
EK_6
:
case
SE
T_CAPACITY
:
case
WRITE_FILEMARKS
:
case
WRITE_FILEMARKS_16
:
case
SPACE
:
case
RESERVE
:
case
RELEASE
:
...
...
@@ -691,6 +715,8 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case
VERIFY_10
:
case
SEEK_10
:
case
SYNCHRONIZE_CACHE
:
case
SYNCHRONIZE_CACHE_16
:
case
LOCATE_16
:
case
LOCK_UNLOCK_CACHE
:
case
LOAD_UNLOAD
:
case
SET_CD_SPEED
:
...
...
@@ -698,6 +724,11 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case
WRITE_LONG_10
:
case
MOVE_MEDIUM
:
case
UPDATE_BLOCK
:
case
RESERVE_TRACK
:
case
SET_READ_AHEAD
:
case
PRE_FETCH
:
case
PRE_FETCH_16
:
case
ALLOW_OVERWRITE
:
cmd
->
xfer
=
0
;
break
;
case
MODE_SENSE
:
...
...
@@ -711,14 +742,13 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case
READ_BLOCK_LIMITS
:
cmd
->
xfer
=
6
;
break
;
case
READ_POSITION
:
cmd
->
xfer
=
20
;
break
;
case
SEND_VOLUME_TAG
:
cmd
->
xfer
*=
40
;
break
;
case
MEDIUM_SCAN
:
cmd
->
xfer
*=
8
;
/* GPCMD_SET_STREAMING from multimedia commands. */
if
(
dev
->
type
==
TYPE_ROM
)
{
cmd
->
xfer
=
buf
[
10
]
|
(
buf
[
9
]
<<
8
);
}
else
{
cmd
->
xfer
=
buf
[
9
]
|
(
buf
[
8
]
<<
8
);
}
break
;
case
WRITE_10
:
case
WRITE_VERIFY_10
:
...
...
@@ -737,9 +767,39 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case
READ_16
:
cmd
->
xfer
*=
dev
->
blocksize
;
break
;
case
FORMAT_UNIT
:
/* MMC mandates the parameter list to be 12-bytes long. Parameters
* for block devices are restricted to the header right now. */
if
(
dev
->
type
==
TYPE_ROM
&&
(
buf
[
1
]
&
16
))
{
cmd
->
xfer
=
12
;
}
else
{
cmd
->
xfer
=
(
buf
[
1
]
&
16
)
==
0
?
0
:
(
buf
[
1
]
&
32
?
8
:
4
);
}
break
;
case
INQUIRY
:
case
RECEIVE_DIAGNOSTIC
:
case
SEND_DIAGNOSTIC
:
cmd
->
xfer
=
buf
[
4
]
|
(
buf
[
3
]
<<
8
);
break
;
case
READ_CD
:
case
READ_BUFFER
:
case
WRITE_BUFFER
:
case
SEND_CUE_SHEET
:
cmd
->
xfer
=
buf
[
8
]
|
(
buf
[
7
]
<<
8
)
|
(
buf
[
6
]
<<
16
);
break
;
case
PERSISTENT_RESERVE_OUT
:
cmd
->
xfer
=
ldl_be_p
(
&
buf
[
5
])
&
0xffffffffULL
;
break
;
case
ERASE_12
:
if
(
dev
->
type
==
TYPE_ROM
)
{
/* MMC command GET PERFORMANCE. */
cmd
->
xfer
=
scsi_get_performance_length
(
buf
[
9
]
|
(
buf
[
8
]
<<
8
),
buf
[
10
],
buf
[
1
]
&
0x1f
);
}
break
;
case
MECHANISM_STATUS
:
case
READ_DVD_STRUCTURE
:
case
SEND_DVD_STRUCTURE
:
case
MAINTENANCE_OUT
:
case
MAINTENANCE_IN
:
if
(
dev
->
type
==
TYPE_ROM
)
{
...
...
@@ -755,6 +815,10 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
{
switch
(
buf
[
0
])
{
/* stream commands */
case
ERASE_12
:
case
ERASE_16
:
cmd
->
xfer
=
0
;
break
;
case
READ_6
:
case
READ_REVERSE
:
case
RECOVER_BUFFERED_DATA
:
...
...
@@ -770,6 +834,15 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
cmd
->
len
=
6
;
cmd
->
xfer
=
0
;
break
;
case
SPACE_16
:
cmd
->
xfer
=
buf
[
13
]
|
(
buf
[
12
]
<<
8
);
break
;
case
READ_POSITION
:
cmd
->
xfer
=
buf
[
8
]
|
(
buf
[
7
]
<<
8
);
break
;
case
FORMAT_UNIT
:
cmd
->
xfer
=
buf
[
4
]
|
(
buf
[
3
]
<<
8
);
break
;
/* generic commands */
default:
return
scsi_req_length
(
cmd
,
dev
,
buf
);
...
...
@@ -809,6 +882,8 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
case
SEARCH_LOW_12
:
case
MEDIUM_SCAN
:
case
SEND_VOLUME_TAG
:
case
SEND_CUE_SHEET
:
case
SEND_DVD_STRUCTURE
:
case
PERSISTENT_RESERVE_OUT
:
case
MAINTENANCE_OUT
:
cmd
->
mode
=
SCSI_XFER_TO_DEV
;
...
...
@@ -835,7 +910,7 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
case
1
:
case
2
:
case
5
:
lba
=
ldl_be_p
(
&
buf
[
2
]);
lba
=
ldl_be_p
(
&
buf
[
2
])
&
0xffffffffULL
;
break
;
case
4
:
lba
=
ldq_be_p
(
&
buf
[
2
]);
...
...
@@ -1036,7 +1111,7 @@ static const char *scsi_command_name(uint8_t cmd)
[
REASSIGN_BLOCKS
]
=
"REASSIGN_BLOCKS"
,
[
READ_6
]
=
"READ_6"
,
[
WRITE_6
]
=
"WRITE_6"
,
[
SE
EK_6
]
=
"SEEK_6
"
,
[
SE
T_CAPACITY
]
=
"SET_CAPACITY
"
,
[
READ_REVERSE
]
=
"READ_REVERSE"
,
[
WRITE_FILEMARKS
]
=
"WRITE_FILEMARKS"
,
[
SPACE
]
=
"SPACE"
,
...
...
@@ -1064,7 +1139,7 @@ static const char *scsi_command_name(uint8_t cmd)
[
SEARCH_EQUAL
]
=
"SEARCH_EQUAL"
,
[
SEARCH_LOW
]
=
"SEARCH_LOW"
,
[
SET_LIMITS
]
=
"SET_LIMITS"
,
[
PRE_FETCH
]
=
"PRE_FETCH"
,
[
PRE_FETCH
]
=
"PRE_FETCH
/READ_POSITION
"
,
/* READ_POSITION and PRE_FETCH use the same operation code */
[
SYNCHRONIZE_CACHE
]
=
"SYNCHRONIZE_CACHE"
,
[
LOCK_UNLOCK_CACHE
]
=
"LOCK_UNLOCK_CACHE"
,
...
...
@@ -1101,9 +1176,11 @@ static const char *scsi_command_name(uint8_t cmd)
[
WRITE_16
]
=
"WRITE_16"
,
[
WRITE_VERIFY_16
]
=
"WRITE_VERIFY_16"
,
[
VERIFY_16
]
=
"VERIFY_16"
,
[
SYNCHRONIZE_CACHE_16
]
=
"SYNCHRONIZE_CACHE_16"
,
[
PRE_FETCH_16
]
=
"PRE_FETCH_16"
,
[
SYNCHRONIZE_CACHE_16
]
=
"SPACE_16/SYNCHRONIZE_CACHE_16"
,
/* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
[
LOCATE_16
]
=
"LOCATE_16"
,
[
WRITE_SAME_16
]
=
"WRITE_SAME_16"
,
[
WRITE_SAME_16
]
=
"
ERASE_16/
WRITE_SAME_16"
,
/* ERASE_16 and WRITE_SAME_16 use the same operation code */
[
SERVICE_ACTION_IN_16
]
=
"SERVICE_ACTION_IN_16"
,
[
WRITE_LONG_16
]
=
"WRITE_LONG_16"
,
...
...
@@ -1113,6 +1190,8 @@ static const char *scsi_command_name(uint8_t cmd)
[
LOAD_UNLOAD
]
=
"LOAD_UNLOAD"
,
[
READ_12
]
=
"READ_12"
,
[
WRITE_12
]
=
"WRITE_12"
,
[
ERASE_12
]
=
"ERASE_12/GET_PERFORMANCE"
,
/* ERASE_12 and GET_PERFORMANCE use the same operation code */
[
SERVICE_ACTION_IN_12
]
=
"SERVICE_ACTION_IN_12"
,
[
WRITE_VERIFY_12
]
=
"WRITE_VERIFY_12"
,
[
VERIFY_12
]
=
"VERIFY_12"
,
...
...
@@ -1120,9 +1199,18 @@ static const char *scsi_command_name(uint8_t cmd)
[
SEARCH_EQUAL_12
]
=
"SEARCH_EQUAL_12"
,
[
SEARCH_LOW_12
]
=
"SEARCH_LOW_12"
,
[
READ_ELEMENT_STATUS
]
=
"READ_ELEMENT_STATUS"
,
[
SEND_VOLUME_TAG
]
=
"SEND_VOLUME_TAG"
,
[
SEND_VOLUME_TAG
]
=
"SEND_VOLUME_TAG/SET_STREAMING"
,
/* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
[
READ_CD
]
=
"READ_CD"
,
[
READ_DEFECT_DATA_12
]
=
"READ_DEFECT_DATA_12"
,
[
READ_DVD_STRUCTURE
]
=
"READ_DVD_STRUCTURE"
,
[
RESERVE_TRACK
]
=
"RESERVE_TRACK"
,
[
SEND_CUE_SHEET
]
=
"SEND_CUE_SHEET"
,
[
SEND_DVD_STRUCTURE
]
=
"SEND_DVD_STRUCTURE"
,
[
SET_CD_SPEED
]
=
"SET_CD_SPEED"
,
[
SET_READ_AHEAD
]
=
"SET_READ_AHEAD"
,
[
ALLOW_OVERWRITE
]
=
"ALLOW_OVERWRITE"
,
[
MECHANISM_STATUS
]
=
"MECHANISM_STATUS"
,
};
if
(
cmd
>=
ARRAY_SIZE
(
names
)
||
names
[
cmd
]
==
NULL
)
...
...
@@ -1279,7 +1367,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
SCSIDevice
*
d
=
DO_UPCAST
(
SCSIDevice
,
qdev
,
dev
);
char
path
[
100
];
snprintf
(
path
,
sizeof
(
path
),
"%s@%d
:%d:
%d"
,
qdev_fw_name
(
dev
),
snprintf
(
path
,
sizeof
(
path
),
"%s@%d
,%d,
%d"
,
qdev_fw_name
(
dev
),
d
->
channel
,
d
->
id
,
d
->
lun
);
return
strdup
(
path
);
...
...
hw/scsi-defs.h
浏览文件 @
54dcd0b3
...
...
@@ -32,7 +32,7 @@
#define REASSIGN_BLOCKS 0x07
#define READ_6 0x08
#define WRITE_6 0x0a
#define SE
EK_6
0x0b
#define SE
T_CAPACITY
0x0b
#define READ_REVERSE 0x0f
#define WRITE_FILEMARKS 0x10
#define SPACE 0x11
...
...
@@ -81,14 +81,17 @@
#define GET_EVENT_STATUS_NOTIFICATION 0x4a
#define LOG_SELECT 0x4c
#define LOG_SENSE 0x4d
#define RESERVE_TRACK 0x53
#define MODE_SELECT_10 0x55
#define RESERVE_10 0x56
#define RELEASE_10 0x57
#define MODE_SENSE_10 0x5a
#define SEND_CUE_SHEET 0x5d
#define PERSISTENT_RESERVE_IN 0x5e
#define PERSISTENT_RESERVE_OUT 0x5f
#define VARLENGTH_CDB 0x7f
#define WRITE_FILEMARKS_16 0x80
#define ALLOW_OVERWRITE 0x82
#define EXTENDED_COPY 0x83
#define ATA_PASSTHROUGH 0x85
#define ACCESS_CONTROL_IN 0x86
...
...
@@ -98,6 +101,8 @@
#define WRITE_16 0x8a
#define WRITE_VERIFY_16 0x8e
#define VERIFY_16 0x8f
#define PRE_FETCH_16 0x90
#define SPACE_16 0x91
#define SYNCHRONIZE_CACHE_16 0x91
#define LOCATE_16 0x92
#define WRITE_SAME_16 0x93
...
...
@@ -110,9 +115,11 @@
#define MAINTENANCE_OUT 0xa4
#define MOVE_MEDIUM 0xa5
#define LOAD_UNLOAD 0xa6
#define SET_READ_AHEAD 0xa7
#define READ_12 0xa8
#define WRITE_12 0xaa
#define SERVICE_ACTION_IN_12 0xab
#define ERASE_12 0xac
#define READ_DVD_STRUCTURE 0xad
#define WRITE_VERIFY_12 0xae
#define VERIFY_12 0xaf
...
...
@@ -125,6 +132,7 @@
#define SET_CD_SPEED 0xbb
#define MECHANISM_STATUS 0xbd
#define READ_CD 0xbe
#define SEND_DVD_STRUCTURE 0xbf
/*
* SERVICE ACTION IN subcodes
...
...
hw/scsi-disk.c
浏览文件 @
54dcd0b3
...
...
@@ -797,7 +797,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
break
;
}
/* if a geometry hint is available, use it */
bdrv_g
et_geometry_hint
(
bdrv
,
&
cylinders
,
&
heads
,
&
secs
);
bdrv_g
uess_geometry
(
bdrv
,
&
cylinders
,
&
heads
,
&
secs
);
p
[
2
]
=
(
cylinders
>>
16
)
&
0xff
;
p
[
3
]
=
(
cylinders
>>
8
)
&
0xff
;
p
[
4
]
=
cylinders
&
0xff
;
...
...
@@ -831,7 +831,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
p
[
2
]
=
5000
>>
8
;
p
[
3
]
=
5000
&
0xff
;
/* if a geometry hint is available, use it */
bdrv_g
et_geometry_hint
(
bdrv
,
&
cylinders
,
&
heads
,
&
secs
);
bdrv_g
uess_geometry
(
bdrv
,
&
cylinders
,
&
heads
,
&
secs
);
p
[
4
]
=
heads
&
0xff
;
p
[
5
]
=
secs
&
0xff
;
p
[
6
]
=
s
->
qdev
.
blocksize
>>
8
;
...
...
@@ -956,8 +956,9 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
p
+=
8
;
}
/* MMC prescribes that CD/DVD drives have no block descriptors. */
bdrv_get_geometry
(
s
->
qdev
.
conf
.
bs
,
&
nb_sectors
);
if
(
!
dbd
&&
nb_sectors
)
{
if
(
!
dbd
&&
s
->
qdev
.
type
==
TYPE_DISK
&&
nb_sectors
)
{
if
(
r
->
req
.
cmd
.
buf
[
0
]
==
MODE_SENSE
)
{
outbuf
[
3
]
=
8
;
/* Block descriptor length */
}
else
{
/* MODE_SENSE_10 */
...
...
@@ -1178,6 +1179,11 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
outbuf
[
7
]
=
0
;
buflen
=
8
;
break
;
case
REQUEST_SENSE
:
/* Just return "NO SENSE". */
buflen
=
scsi_build_sense
(
NULL
,
0
,
outbuf
,
r
->
buflen
,
(
req
->
cmd
.
buf
[
1
]
&
1
)
==
0
);
break
;
case
MECHANISM_STATUS
:
buflen
=
scsi_emulate_mechanism_status
(
s
,
outbuf
);
if
(
buflen
<
0
)
{
...
...
@@ -1312,6 +1318,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
case
GET_EVENT_STATUS_NOTIFICATION
:
case
MECHANISM_STATUS
:
case
SERVICE_ACTION_IN_16
:
case
REQUEST_SENSE
:
case
VERIFY_10
:
rc
=
scsi_disk_emulate_command
(
r
);
if
(
rc
<
0
)
{
...
...
@@ -1374,10 +1381,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
goto
fail
;
}
break
;
case
SEEK_6
:
case
SEEK_10
:
DPRINTF
(
"Seek(%d) (sector %"
PRId64
")
\n
"
,
command
==
SEEK_6
?
6
:
10
,
r
->
req
.
cmd
.
lba
);
DPRINTF
(
"Seek(10) (sector %"
PRId64
")
\n
"
,
r
->
req
.
cmd
.
lba
);
if
(
r
->
req
.
cmd
.
lba
>
s
->
qdev
.
max_lba
)
{
goto
illegal_lba
;
}
...
...
@@ -1408,8 +1413,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
}
break
;
case
REQUEST_SENSE
:
abort
();
default:
DPRINTF
(
"Unknown SCSI command (%2.2x)
\n
"
,
buf
[
0
]);
scsi_check_condition
(
r
,
SENSE_CODE
(
INVALID_OPCODE
));
...
...
@@ -1553,7 +1556,7 @@ static int scsi_initfn(SCSIDevice *dev)
bdrv_set_buffer_alignment
(
s
->
qdev
.
conf
.
bs
,
s
->
qdev
.
blocksize
);
bdrv_iostatus_enable
(
s
->
qdev
.
conf
.
bs
);
add_boot_device_path
(
s
->
qdev
.
conf
.
bootindex
,
&
dev
->
qdev
,
",0"
);
add_boot_device_path
(
s
->
qdev
.
conf
.
bootindex
,
&
dev
->
qdev
,
NULL
);
return
0
;
}
...
...
@@ -1700,8 +1703,20 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
case
WRITE_VERIFY_10
:
case
WRITE_VERIFY_12
:
case
WRITE_VERIFY_16
:
return
scsi_req_alloc
(
&
scsi_disk_reqops
,
&
s
->
qdev
,
tag
,
lun
,
hba_private
);
/* MMC writing cannot be done via pread/pwrite, because it sometimes
* involves writing beyond the maximum LBA or to negative LBA (lead-in).
* And once you do these writes, reading from the block device is
* unreliable, too. It is even possible that reads deliver random data
* from the host page cache (this is probably a Linux bug).
*
* We might use scsi_disk_reqops as long as no writing commands are
* seen, but performance usually isn't paramount on optical media. So,
* just make scsi-block operate the same as scsi-generic for them.
*/
if
(
s
->
qdev
.
type
!=
TYPE_ROM
)
{
return
scsi_req_alloc
(
&
scsi_disk_reqops
,
&
s
->
qdev
,
tag
,
lun
,
hba_private
);
}
}
return
scsi_req_alloc
(
&
scsi_generic_req_ops
,
&
s
->
qdev
,
tag
,
lun
,
...
...
hw/scsi.h
浏览文件 @
54dcd0b3
...
...
@@ -179,6 +179,8 @@ extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
#define SENSE_CODE(x) sense_code_ ## x
int
scsi_sense_valid
(
SCSISense
sense
);
int
scsi_build_sense
(
uint8_t
*
in_buf
,
int
in_len
,
uint8_t
*
buf
,
int
len
,
bool
fixed
);
SCSIRequest
*
scsi_req_alloc
(
const
SCSIReqOps
*
reqops
,
SCSIDevice
*
d
,
uint32_t
tag
,
uint32_t
lun
,
void
*
hba_private
);
...
...
qemu-doc.texi
浏览文件 @
54dcd0b3
...
...
@@ -421,6 +421,7 @@ snapshots.
*
disk
_
images
_
fat
_
images:: Virtual FAT disk images
*
disk
_
images
_
nbd:: NBD access
*
disk
_
images
_
sheepdog:: Sheepdog disk images
*
disk
_
images
_
iscsi:: iSCSI LUNs
@end menu
@node disk
_
images
_
quickstart
...
...
@@ -695,6 +696,61 @@ qemu-img create sheepdog:@var{hostname}:@var{port}:@var{image} @var{size}
qemu sheepdog:@var
{
hostname
}
:@var
{
port
}
:@var
{
image
}
@end example
@node disk
_
images
_
iscsi
@subsection iSCSI LUNs
iSCSI is a popular protocol used to access SCSI devices across a computer
network.
There are two different ways iSCSI devices can be used by QEMU.
The first method is to mount the iSCSI LUN on the host, and make it appear as
any other ordinary SCSI device on the host and then to access this device as a
/
dev
/
sd device from QEMU. How to do this differs between host OSes.
The second method involves using the iSCSI initiator that is built into
QEMU. This provides a mechanism that works the same way regardless of which
host OS you are running QEMU on. This section will describe this second method
of using iSCSI together with QEMU.
In QEMU, iSCSI devices are described using special iSCSI URLs
@example
URL syntax:
iscsi:
//[
<username>
[
%<password>]@@]<host>[:<port>]/<target-iqn-name>/<lun>
@end example
Username and password are optional and only used if your target is set up
using CHAP authentication for access control.
Alternatively the username and password can also be set via environment
variables to have these not show up in the process list
@example
export LIBISCSI
_
CHAP
_
USERNAME
=
<username>
export LIBISCSI
_
CHAP
_
PASSWORD
=
<password>
iscsi:
//
<host>
/
<target
-
iqn
-
name>
/
<lun>
@end example
Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
@example
This example shows how to set up an iSCSI target with one CDROM and one DISK
using the Linux STGT software target. This target is available on Red Hat based
systems as the package 'scsi
-
target
-
utils'.
tgtd
--
iscsi portal
=
127
.
0
.
0
.
1
:
3260
tgtadm
--
lld iscsi
--
op new
--
mode target
--
tid
1
-
T iqn.qemu.test
tgtadm
--
lld iscsi
--
mode logicalunit
--
op new
--
tid
1
--
lun
1
\
-
b
/
IMAGES
/
disk.img
--
device
-
type
=
disk
tgtadm
--
lld iscsi
--
mode logicalunit
--
op new
--
tid
1
--
lun
2
\
-
b
/
IMAGES
/
cd.iso
--
device
-
type
=
cd
tgtadm
--
lld iscsi
--
op bind
--
mode target
--
tid
1
-
I ALL
qemu
-
system
-
i
386
-
boot d
-
drive file
=
iscsi:
//
127
.
0
.
0
.
1
/
iqn.qemu.test
/
1
\
-
cdrom iscsi:
//
127
.
0
.
0
.
1
/
iqn.qemu.test
/
2
@end example
@node pcsys
_
network
@section Network emulation
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录