kvm-guest-drivers-windows

Форк
0
179 строк · 5.7 Кб
1
/*
2
 * Interrupt related functions
3
 *
4
 * Copyright (c) 2016-2017 Red Hat, Inc.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met :
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and / or other materials provided with the distribution.
14
 * 3. Neither the names of the copyright holders nor the names of their contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29

30
#include "precomp.h"
31
#include "vioinput.h"
32

33
#if defined(EVENT_TRACING)
34
#include "IsrDpc.tmh"
35
#endif
36

37
static
38
VOID
39
VIOInputEnableInterrupt(PINPUT_DEVICE pContext)
40
{
41
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "--> %s enable\n", __FUNCTION__);
42

43
    if (!pContext)
44
        return;
45

46
    if (pContext->EventQ)
47
    {
48
        virtqueue_enable_cb(pContext->EventQ);
49
        virtqueue_kick(pContext->EventQ);
50
    }
51
    if (pContext->StatusQ)
52
    {
53
        virtqueue_enable_cb(pContext->StatusQ);
54
        virtqueue_kick(pContext->StatusQ);
55
    }
56

57
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "<-- %s enable\n", __FUNCTION__);
58
}
59

60
static
61
VOID
62
VIOInputDisableInterrupt(PINPUT_DEVICE pContext)
63
{
64
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "--> %s disable\n", __FUNCTION__);
65

66
    if (!pContext)
67
        return;
68

69
    if (pContext->EventQ)
70
    {
71
        virtqueue_disable_cb(pContext->EventQ);
72
    }
73
    if (pContext->StatusQ)
74
    {
75
        virtqueue_disable_cb(pContext->StatusQ);
76
    }
77

78
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "<-- %s disable\n", __FUNCTION__);
79
}
80

81
NTSTATUS
82
VIOInputInterruptEnable(
83
    IN WDFINTERRUPT Interrupt,
84
    IN WDFDEVICE AssociatedDevice)
85
{
86
    UNREFERENCED_PARAMETER(AssociatedDevice);
87

88
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "--> %s\n", __FUNCTION__);
89
    VIOInputEnableInterrupt(GetDeviceContext(WdfInterruptGetDevice(Interrupt)));
90
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "<-- %s\n", __FUNCTION__);
91
    return STATUS_SUCCESS;
92
}
93

94
NTSTATUS
95
VIOInputInterruptDisable(
96
    IN WDFINTERRUPT Interrupt,
97
    IN WDFDEVICE AssociatedDevice)
98
{
99
    UNREFERENCED_PARAMETER(AssociatedDevice);
100

101
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "--> %s\n", __FUNCTION__);
102
    VIOInputDisableInterrupt(GetDeviceContext(WdfInterruptGetDevice(Interrupt)));
103
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "<-- %s\n", __FUNCTION__);
104
    return STATUS_SUCCESS;
105
}
106

107
BOOLEAN
108
VIOInputInterruptIsr(
109
    IN WDFINTERRUPT Interrupt,
110
    IN ULONG MessageID)
111
{
112
    PINPUT_DEVICE pContext = GetDeviceContext(WdfInterruptGetDevice(Interrupt));
113
    WDF_INTERRUPT_INFO info;
114
    BOOLEAN serviced;
115

116
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "--> %s\n", __FUNCTION__);
117

118
    WDF_INTERRUPT_INFO_INIT(&info);
119
    WdfInterruptGetInfo(Interrupt, &info);
120

121
    // Schedule a DPC if the device is using message-signaled interrupts, or
122
    // if the device ISR status is enabled.
123
    if (info.MessageSignaled || VirtIOWdfGetISRStatus(&pContext->VDevice))
124
    {
125
        WdfInterruptQueueDpcForIsr(Interrupt);
126
        serviced = TRUE;
127
    }
128
    else
129
    {
130
        serviced = FALSE;
131
    }
132

133
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "<-- %s\n", __FUNCTION__);
134
    return serviced;
135
}
136

137
VOID
138
VIOInputQueuesInterruptDpc(
139
    IN WDFINTERRUPT Interrupt,
140
    IN WDFOBJECT AssociatedObject)
141
{
142
    WDFDEVICE Device = WdfInterruptGetDevice(Interrupt);
143
    PINPUT_DEVICE pContext = GetDeviceContext(Device);
144
    PVIRTIO_INPUT_EVENT pEvent;
145
    PVIRTIO_INPUT_EVENT_WITH_REQUEST pEventReq;
146
    UINT len;
147

148
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "--> %s\n", __FUNCTION__);
149

150
    WdfSpinLockAcquire(pContext->EventQLock);
151
    while ((pEvent = virtqueue_get_buf(pContext->EventQ, &len)) != NULL)
152
    {
153
        // translate event to a HID report and complete a pending HID request
154
        ProcessInputEvent(pContext, pEvent);
155

156
        // add the buffer back to the queue
157
        VIOInputAddInBuf(
158
            pContext->EventQ,
159
            pEvent,
160
            VirtIOWdfDeviceGetPhysicalAddress(&pContext->VDevice.VIODevice, pEvent));
161
    }
162
    WdfSpinLockRelease(pContext->EventQLock);
163

164
    WdfSpinLockAcquire(pContext->StatusQLock);
165
    while ((pEventReq = virtqueue_get_buf(pContext->StatusQ, &len)) != NULL)
166
    {
167
        // complete the pending request
168
        if (pEventReq->Request != NULL)
169
        {
170
            WdfRequestComplete(pEventReq->Request, STATUS_SUCCESS);
171
        }
172

173
        // free the buffer
174
        pContext->StatusQMemBlock->return_slice(pContext->StatusQMemBlock, pEventReq);
175
    }
176
    WdfSpinLockRelease(pContext->StatusQLock);
177

178
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "<-- %s\n", __FUNCTION__);
179
}
180

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.