Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
3d139684
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看板
提交
3d139684
编写于
8月 24, 2012
作者:
G
Gerd Hoffmann
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
xhci: iso xfer support
Add support for iso transfers. Signed-off-by:
N
Gerd Hoffmann
<
kraxel@redhat.com
>
上级
01546fa6
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
101 addition
and
16 deletion
+101
-16
hw/usb/hcd-xhci.c
hw/usb/hcd-xhci.c
+101
-16
未找到文件。
hw/usb/hcd-xhci.c
浏览文件 @
3d139684
...
...
@@ -325,9 +325,15 @@ typedef struct XHCITransfer {
unsigned
int
pkts
;
unsigned
int
pktsize
;
unsigned
int
cur_pkt
;
uint64_t
mfindex_kick
;
}
XHCITransfer
;
typedef
struct
XHCIEPContext
{
XHCIState
*
xhci
;
unsigned
int
slotid
;
unsigned
int
epid
;
XHCIRing
ring
;
unsigned
int
next_xfer
;
unsigned
int
comp_xfer
;
...
...
@@ -337,6 +343,11 @@ typedef struct XHCIEPContext {
dma_addr_t
pctx
;
unsigned
int
max_psize
;
uint32_t
state
;
/* iso xfer scheduling */
unsigned
int
interval
;
int64_t
mfindex_last
;
QEMUTimer
*
kick_timer
;
}
XHCIEPContext
;
typedef
struct
XHCISlot
{
...
...
@@ -856,6 +867,12 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
epctx
->
state
=
state
;
}
static
void
xhci_ep_kick_timer
(
void
*
opaque
)
{
XHCIEPContext
*
epctx
=
opaque
;
xhci_kick_ep
(
epctx
->
xhci
,
epctx
->
slotid
,
epctx
->
epid
);
}
static
TRBCCode
xhci_enable_ep
(
XHCIState
*
xhci
,
unsigned
int
slotid
,
unsigned
int
epid
,
dma_addr_t
pctx
,
uint32_t
*
ctx
)
...
...
@@ -877,6 +894,9 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
epctx
=
g_malloc
(
sizeof
(
XHCIEPContext
));
memset
(
epctx
,
0
,
sizeof
(
XHCIEPContext
));
epctx
->
xhci
=
xhci
;
epctx
->
slotid
=
slotid
;
epctx
->
epid
=
epid
;
slot
->
eps
[
epid
-
1
]
=
epctx
;
...
...
@@ -895,6 +915,10 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
usb_packet_init
(
&
epctx
->
transfers
[
i
].
packet
);
}
epctx
->
interval
=
1
<<
(
ctx
[
0
]
>>
16
)
&
0xff
;
epctx
->
mfindex_last
=
0
;
epctx
->
kick_timer
=
qemu_new_timer_ns
(
vm_clock
,
xhci_ep_kick_timer
,
epctx
);
epctx
->
state
=
EP_RUNNING
;
ctx
[
0
]
&=
~
EP_STATE_MASK
;
ctx
[
0
]
|=
EP_RUNNING
;
...
...
@@ -934,6 +958,7 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
if
(
t
->
running_retry
)
{
t
->
running_retry
=
0
;
epctx
->
retry
=
NULL
;
qemu_del_timer
(
epctx
->
kick_timer
);
}
if
(
t
->
trbs
)
{
g_free
(
t
->
trbs
);
...
...
@@ -969,6 +994,7 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
xhci_set_ep_state
(
xhci
,
epctx
,
EP_DISABLED
);
qemu_free_timer
(
epctx
->
kick_timer
);
g_free
(
epctx
);
slot
->
eps
[
epid
-
1
]
=
NULL
;
...
...
@@ -1376,29 +1402,70 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
return
0
;
}
static
void
xhci_calc_iso_kick
(
XHCIState
*
xhci
,
XHCITransfer
*
xfer
,
XHCIEPContext
*
epctx
,
uint64_t
mfindex
)
{
if
(
xfer
->
trbs
[
0
].
control
&
TRB_TR_SIA
)
{
uint64_t
asap
=
((
mfindex
+
epctx
->
interval
-
1
)
&
~
(
epctx
->
interval
-
1
));
if
(
asap
>=
epctx
->
mfindex_last
&&
asap
<=
epctx
->
mfindex_last
+
epctx
->
interval
*
4
)
{
xfer
->
mfindex_kick
=
epctx
->
mfindex_last
+
epctx
->
interval
;
}
else
{
xfer
->
mfindex_kick
=
asap
;
}
}
else
{
xfer
->
mfindex_kick
=
(
xfer
->
trbs
[
0
].
control
>>
TRB_TR_FRAMEID_SHIFT
)
&
TRB_TR_FRAMEID_MASK
;
xfer
->
mfindex_kick
|=
mfindex
&
~
0x3fff
;
if
(
xfer
->
mfindex_kick
<
mfindex
)
{
xfer
->
mfindex_kick
+=
0x4000
;
}
}
}
static
void
xhci_check_iso_kick
(
XHCIState
*
xhci
,
XHCITransfer
*
xfer
,
XHCIEPContext
*
epctx
,
uint64_t
mfindex
)
{
if
(
xfer
->
mfindex_kick
>
mfindex
)
{
qemu_mod_timer
(
epctx
->
kick_timer
,
qemu_get_clock_ns
(
vm_clock
)
+
(
xfer
->
mfindex_kick
-
mfindex
)
*
125000
);
xfer
->
running_retry
=
1
;
}
else
{
epctx
->
mfindex_last
=
xfer
->
mfindex_kick
;
qemu_del_timer
(
epctx
->
kick_timer
);
xfer
->
running_retry
=
0
;
}
}
static
int
xhci_submit
(
XHCIState
*
xhci
,
XHCITransfer
*
xfer
,
XHCIEPContext
*
epctx
)
{
uint64_t
mfindex
;
int
ret
;
DPRINTF
(
"xhci_submit(slotid=%d,epid=%d)
\n
"
,
xfer
->
slotid
,
xfer
->
epid
);
xfer
->
in_xfer
=
epctx
->
type
>>
2
;
if
(
epctx
->
type
==
ET_ISO_IN
||
epctx
->
type
==
ET_ISO_OUT
)
{
xfer
->
pkts
=
1
;
}
else
{
xfer
->
pkts
=
0
;
}
switch
(
epctx
->
type
)
{
case
ET_INTR_OUT
:
case
ET_INTR_IN
:
case
ET_BULK_OUT
:
case
ET_BULK_IN
:
xfer
->
pkts
=
0
;
xfer
->
iso_xfer
=
false
;
break
;
case
ET_ISO_OUT
:
case
ET_ISO_IN
:
FIXME
();
xfer
->
pkts
=
1
;
xfer
->
iso_xfer
=
true
;
mfindex
=
xhci_mfindex_get
(
xhci
);
xhci_calc_iso_kick
(
xhci
,
xfer
,
epctx
,
mfindex
);
xhci_check_iso_kick
(
xhci
,
xfer
,
epctx
,
mfindex
);
if
(
xfer
->
running_retry
)
{
return
-
1
;
}
break
;
default:
fprintf
(
stderr
,
"xhci: unknown or unhandled EP "
...
...
@@ -1428,6 +1495,7 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext
static
void
xhci_kick_ep
(
XHCIState
*
xhci
,
unsigned
int
slotid
,
unsigned
int
epid
)
{
XHCIEPContext
*
epctx
;
uint64_t
mfindex
;
int
length
;
int
i
;
...
...
@@ -1447,20 +1515,35 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
}
if
(
epctx
->
retry
)
{
/* retry nak'ed transfer */
XHCITransfer
*
xfer
=
epctx
->
retry
;
int
result
;
trace_usb_xhci_xfer_retry
(
xfer
);
assert
(
xfer
->
running_retry
);
if
(
xhci_setup_packet
(
xfer
)
<
0
)
{
return
;
}
result
=
usb_handle_packet
(
xfer
->
packet
.
ep
->
dev
,
&
xfer
->
packet
);
if
(
result
==
USB_RET_NAK
)
{
return
;
if
(
xfer
->
iso_xfer
)
{
/* retry delayed iso transfer */
mfindex
=
xhci_mfindex_get
(
xhci
);
xhci_check_iso_kick
(
xhci
,
xfer
,
epctx
,
mfindex
);
if
(
xfer
->
running_retry
)
{
return
;
}
if
(
xhci_setup_packet
(
xfer
)
<
0
)
{
return
;
}
result
=
usb_handle_packet
(
xfer
->
packet
.
ep
->
dev
,
&
xfer
->
packet
);
assert
(
result
!=
USB_RET_NAK
);
xhci_complete_packet
(
xfer
,
result
);
}
else
{
/* retry nak'ed transfer */
if
(
xhci_setup_packet
(
xfer
)
<
0
)
{
return
;
}
result
=
usb_handle_packet
(
xfer
->
packet
.
ep
->
dev
,
&
xfer
->
packet
);
if
(
result
==
USB_RET_NAK
)
{
return
;
}
xhci_complete_packet
(
xfer
,
result
);
}
xhci_complete_packet
(
xfer
,
result
);
assert
(
!
xfer
->
running_retry
);
epctx
->
retry
=
NULL
;
}
...
...
@@ -1512,7 +1595,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
if
(
xhci_fire_transfer
(
xhci
,
xfer
,
epctx
)
>=
0
)
{
epctx
->
next_xfer
=
(
epctx
->
next_xfer
+
1
)
%
TD_QUEUE
;
}
else
{
fprintf
(
stderr
,
"xhci: error firing data transfer
\n
"
);
if
(
!
xfer
->
iso_xfer
)
{
fprintf
(
stderr
,
"xhci: error firing data transfer
\n
"
);
}
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录