ReactOS 0.4.15-dev-7918-g2a2556c
ParaNdis-VirtIO.c
Go to the documentation of this file.
1/*
2 * This file contains NDIS driver VirtIO callbacks
3 *
4 * Copyright (c) 2008-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#include "ndis56common.h"
30
32//
33// ReadVirtIODeviceRegister\WriteVirtIODeviceRegister
34// NDIS specific implementation of the IO and memory space read\write
35//
36// The lower 64k of memory is never mapped so we can use the same routines
37// for both port I/O and memory access and use the address alone to decide
38// which space to use.
40
41#define PORT_MASK 0xFFFF
42
44{
45 ULONG ulValue;
46
47 if (ulRegister & ~PORT_MASK) {
48 NdisReadRegisterUlong(ulRegister, &ulValue);
49 } else {
50 NdisRawReadPortUlong(ulRegister, &ulValue);
51 }
52
53 DPrintf(6, ("[%s]R[%x]=%x", __FUNCTION__, (ULONG)ulRegister, ulValue));
54 return ulValue;
55}
56
57static void WriteVirtIODeviceRegister(ULONG_PTR ulRegister, u32 ulValue)
58{
59 DPrintf(6, ("[%s]R[%x]=%x", __FUNCTION__, (ULONG)ulRegister, ulValue));
60
61 if (ulRegister & ~PORT_MASK) {
62 NdisWriteRegisterUlong((PULONG)ulRegister, ulValue);
63 } else {
64 NdisRawWritePortUlong(ulRegister, ulValue);
65 }
66}
67
69{
70 u8 bValue;
71
72 if (ulRegister & ~PORT_MASK) {
73 NdisReadRegisterUchar(ulRegister, &bValue);
74 } else {
75 NdisRawReadPortUchar(ulRegister, &bValue);
76 }
77
78 DPrintf(6, ("[%s]R[%x]=%x", __FUNCTION__, (ULONG)ulRegister, bValue));
79 return bValue;
80}
81
82static void WriteVirtIODeviceByte(ULONG_PTR ulRegister, u8 bValue)
83{
84 DPrintf(6, ("[%s]R[%x]=%x", __FUNCTION__, (ULONG)ulRegister, bValue));
85
86 if (ulRegister & ~PORT_MASK) {
87 NdisWriteRegisterUchar((PUCHAR)ulRegister, bValue);
88 } else {
89 NdisRawWritePortUchar(ulRegister, bValue);
90 }
91}
92
94{
95 u16 wValue;
96
97 if (ulRegister & ~PORT_MASK) {
98 NdisReadRegisterUshort(ulRegister, &wValue);
99 } else {
100 NdisRawReadPortUshort(ulRegister, &wValue);
101 }
102
103 DPrintf(6, ("[%s]R[%x]=%x\n", __FUNCTION__, (ULONG)ulRegister, wValue));
104 return wValue;
105}
106
107static void WriteVirtIODeviceWord(ULONG_PTR ulRegister, u16 wValue)
108{
109#if 1
110 if (ulRegister & ~PORT_MASK) {
111 NdisWriteRegisterUshort((PUSHORT)ulRegister, wValue);
112 } else {
113 NdisRawWritePortUshort(ulRegister, wValue);
114 }
115#else
116 // test only to cause long TX waiting queue of NDIS packets
117 // to recognize it and request for reset via Hang handler
118 static int nCounterToFail = 0;
119 static const int StartFail = 200, StopFail = 600;
120 BOOLEAN bFail = FALSE;
121 DPrintf(6, ("%s> R[%x] = %x\n", __FUNCTION__, (ULONG)ulRegister, wValue));
122 if ((ulRegister & 0x1F) == 0x10)
123 {
124 nCounterToFail++;
125 bFail = nCounterToFail >= StartFail && nCounterToFail < StopFail;
126 }
127 if (!bFail) NdisRawWritePortUshort(ulRegister, wValue);
128 else
129 {
130 DPrintf(0, ("%s> FAILING R[%x] = %x\n", __FUNCTION__, (ULONG)ulRegister, wValue));
131 }
132#endif
133}
134
135static void *mem_alloc_contiguous_pages(void *context, size_t size)
136{
138 PVOID retVal = NULL;
139 ULONG i;
140
141 /* find the first unused memory range of the requested size */
142 for (i = 0; i < MAX_NUM_OF_QUEUES; i++) {
143 if (pContext->SharedMemoryRanges[i].pBase != NULL &&
144 pContext->SharedMemoryRanges[i].bUsed == FALSE &&
145 pContext->SharedMemoryRanges[i].uLength == (ULONG)size) {
146 retVal = pContext->SharedMemoryRanges[i].pBase;
147 pContext->SharedMemoryRanges[i].bUsed = TRUE;
148 break;
149 }
150 }
151
152 if (!retVal) {
153 /* find the first null memory range descriptor and allocate */
154 for (i = 0; i < MAX_NUM_OF_QUEUES; i++) {
155 if (pContext->SharedMemoryRanges[i].pBase == NULL) {
156 break;
157 }
158 }
159 if (i < MAX_NUM_OF_QUEUES) {
161 pContext->MiniportHandle,
162 (ULONG)size,
163 TRUE /* Cached */,
164 &pContext->SharedMemoryRanges[i].pBase,
165 &pContext->SharedMemoryRanges[i].BasePA);
166 retVal = pContext->SharedMemoryRanges[i].pBase;
167 if (retVal) {
168 NdisZeroMemory(retVal, size);
169 pContext->SharedMemoryRanges[i].uLength = (ULONG)size;
170 pContext->SharedMemoryRanges[i].bUsed = TRUE;
171 }
172 }
173 }
174
175 if (retVal) {
176 DPrintf(6, ("[%s] returning %p, size %x\n", __FUNCTION__, retVal, (ULONG)size));
177 } else {
178 DPrintf(0, ("[%s] failed to allocate size %x\n", __FUNCTION__, (ULONG)size));
179 }
180 return retVal;
181}
182
183static void mem_free_contiguous_pages(void *context, void *virt)
184{
186 ULONG i;
187
188 for (i = 0; i < MAX_NUM_OF_QUEUES; i++) {
189 if (pContext->SharedMemoryRanges[i].pBase == virt) {
190 pContext->SharedMemoryRanges[i].bUsed = FALSE;
191 break;
192 }
193 }
194
195 if (i < MAX_NUM_OF_QUEUES) {
196 DPrintf(6, ("[%s] freed %p at index %d\n", __FUNCTION__, virt, i));
197 } else {
198 DPrintf(0, ("[%s] failed to free %p\n", __FUNCTION__, virt));
199 }
200}
201
203{
205 ULONG_PTR uAddr = (ULONG_PTR)virt;
206 ULONG i;
207
208 for (i = 0; i < MAX_NUM_OF_QUEUES; i++) {
209 ULONG_PTR uBase = (ULONG_PTR)pContext->SharedMemoryRanges[i].pBase;
210 if (uAddr >= uBase && uAddr < (uBase + pContext->SharedMemoryRanges[i].uLength)) {
211 ULONGLONG retVal = pContext->SharedMemoryRanges[i].BasePA.QuadPart + (uAddr - uBase);
212
213 DPrintf(6, ("[%s] translated %p to %I64X\n", __FUNCTION__, virt, retVal));
214 return retVal;
215 }
216 }
217
218 DPrintf(0, ("[%s] failed to translate %p\n", __FUNCTION__, virt));
219 return 0;
220}
221
222static void *mem_alloc_nonpaged_block(void *context, size_t size)
223{
224 PVOID retVal;
225
227 &retVal,
228 (UINT)size,
230 retVal = NULL;
231 }
232
233 if (retVal) {
234 NdisZeroMemory(retVal, size);
235 DPrintf(6, ("[%s] returning %p, len %x\n", __FUNCTION__, retVal, (ULONG)size));
236 } else {
237 DPrintf(0, ("[%s] failed to allocate size %x\n", __FUNCTION__, (ULONG)size));
238 }
239 return retVal;
240}
241
242static void mem_free_nonpaged_block(void *context, void *addr)
243{
245
246 NdisFreeMemory(addr, 0, 0);
247 DPrintf(6, ("[%s] freed %p\n", __FUNCTION__, addr));
248}
249
251 int where,
252 void *buffer,
253 size_t length)
254{
255 ULONG read;
256
258 pContext->MiniportHandle,
259 0 /* SlotNumber */,
260 where,
261 buffer,
262 (ULONG)length);
263
264 if (read == length) {
265 DPrintf(6, ("[%s] read %d bytes at %d\n", __FUNCTION__, read, where));
266 return 0;
267 } else {
268 DPrintf(0, ("[%s] failed to read %d bytes at %d\n", __FUNCTION__, read, where));
269 return -1;
270 }
271}
272
273static int pci_read_config_byte(void *context, int where, u8 *bVal)
274{
275 return PCIReadConfig((PPARANDIS_ADAPTER)context, where, bVal, sizeof(*bVal));
276}
277
278static int pci_read_config_word(void *context, int where, u16 *wVal)
279{
280 return PCIReadConfig((PPARANDIS_ADAPTER)context, where, wVal, sizeof(*wVal));
281}
282
283static int pci_read_config_dword(void *context, int where, u32 *dwVal)
284{
285 return PCIReadConfig((PPARANDIS_ADAPTER)context, where, dwVal, sizeof(*dwVal));
286}
287
288static size_t pci_get_resource_len(void *context, int bar)
289{
291
292 if (bar < PCI_TYPE0_ADDRESSES) {
293 return pContext->AdapterResources.PciBars[bar].uLength;
294 }
295
296 DPrintf(0, ("[%s] queried invalid BAR %d\n", __FUNCTION__, bar));
297 return 0;
298}
299
300static void *pci_map_address_range(void *context, int bar, size_t offset, size_t maxlen)
301{
303
304 if (bar < PCI_TYPE0_ADDRESSES) {
305 tBusResource *pRes = &pContext->AdapterResources.PciBars[bar];
306 if (pRes->pBase == NULL) {
307 /* BAR not mapped yet */
308 if (pRes->bPortSpace) {
310 &pRes->pBase,
311 pContext->MiniportHandle,
312 pRes->BasePA.LowPart,
313 pRes->uLength)) {
314 DPrintf(6, ("[%s] mapped port BAR at %x\n", __FUNCTION__, pRes->BasePA.LowPart));
315 } else {
316 pRes->pBase = NULL;
317 DPrintf(0, ("[%s] failed to map port BAR at %x\n", __FUNCTION__, pRes->BasePA.LowPart));
318 }
319 } else {
321 &pRes->pBase,
322 pContext->MiniportHandle,
323 pRes->BasePA,
324 pRes->uLength)) {
325 DPrintf(6, ("[%s] mapped memory BAR at %I64x\n", __FUNCTION__, pRes->BasePA.QuadPart));
326 } else {
327 pRes->pBase = NULL;
328 DPrintf(0, ("[%s] failed to map memory BAR at %I64x\n", __FUNCTION__, pRes->BasePA.QuadPart));
329 }
330 }
331 }
332 if (pRes->pBase != NULL && offset < pRes->uLength) {
333 if (pRes->bPortSpace) {
334 /* use physical address for port I/O */
335 return (PUCHAR)(ULONG_PTR)pRes->BasePA.LowPart + offset;
336 } else {
337 /* use virtual address for memory I/O */
338 return (PUCHAR)pRes->pBase + offset;
339 }
340 } else {
341 DPrintf(0, ("[%s] failed to get map BAR %d, offset %x\n", __FUNCTION__, bar, offset));
342 }
343 } else {
344 DPrintf(0, ("[%s] queried invalid BAR %d\n", __FUNCTION__, bar));
345 }
346
347 return NULL;
348}
349
351{
354
355 /* we don't run on MSI support so this will never be true */
356 if (pContext->bUsingMSIX && queue >= 0) {
357 vector = (u16)pContext->AdapterResources.Vector;
358 }
359
360 return vector;
361}
362
363static void vdev_sleep(void *context, unsigned int msecs)
364{
366
367 NdisMSleep(1000 * msecs);
368}
369
371 /* .vdev_read_byte = */ ReadVirtIODeviceByte,
372 /* .vdev_read_word = */ ReadVirtIODeviceWord,
373 /* .vdev_read_dword = */ ReadVirtIODeviceRegister,
374 /* .vdev_write_byte = */ WriteVirtIODeviceByte,
375 /* .vdev_write_word = */ WriteVirtIODeviceWord,
376 /* .vdev_write_dword = */ WriteVirtIODeviceRegister,
377 /* .mem_alloc_contiguous_pages = */ mem_alloc_contiguous_pages,
378 /* .mem_free_contiguous_pages = */ mem_free_contiguous_pages,
379 /* .mem_get_physical_address = */ mem_get_physical_address,
380 /* .mem_alloc_nonpaged_block = */ mem_alloc_nonpaged_block,
381 /* .mem_free_nonpaged_block = */ mem_free_nonpaged_block,
382 /* .pci_read_config_byte = */ pci_read_config_byte,
383 /* .pci_read_config_word = */ pci_read_config_word,
384 /* .pci_read_config_dword = */ pci_read_config_dword,
385 /* .pci_get_resource_len = */ pci_get_resource_len,
386 /* .pci_map_address_range = */ pci_map_address_range,
387 /* .vdev_get_msix_vector = */ vdev_get_msix_vector,
388 /*.vdev_sleep = */ vdev_sleep,
389};
static void WriteVirtIODeviceByte(ULONG_PTR ulRegister, u8 bValue)
static u16 ReadVirtIODeviceWord(ULONG_PTR ulRegister)
static void WriteVirtIODeviceRegister(ULONG_PTR ulRegister, u32 ulValue)
static int PCIReadConfig(PPARANDIS_ADAPTER pContext, int where, void *buffer, size_t length)
static u32 ReadVirtIODeviceRegister(ULONG_PTR ulRegister)
#define PORT_MASK
VirtIOSystemOps ParaNdisSystemOps
static void WriteVirtIODeviceWord(ULONG_PTR ulRegister, u16 wValue)
static u8 ReadVirtIODeviceByte(ULONG_PTR ulRegister)
unsigned char BOOLEAN
#define read
Definition: acwin.h:96
ULONG32 u32
Definition: btrfs.h:14
UCHAR u8
Definition: btrfs.h:12
USHORT u16
Definition: btrfs.h:13
Definition: _queue.h:67
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define __FUNCTION__
Definition: types.h:116
#define DPrintf(Level, Fmt)
Definition: kdebugprint.h:61
ULONG EXPORT NdisReadPciSlotInformation(IN NDIS_HANDLE NdisAdapterHandle, IN ULONG SlotNumber, IN ULONG Offset, IN PVOID Buffer, IN ULONG Length)
Definition: hardware.c:180
NDIS_STATUS EXPORT NdisMMapIoSpace(OUT PVOID *VirtualAddress, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, IN UINT Length)
Definition: io.c:774
NDIS_STATUS EXPORT NdisMRegisterIoPortRange(OUT PVOID *PortOffset, IN NDIS_HANDLE MiniportAdapterHandle, IN UINT InitialPort, IN UINT NumberOfPorts)
Definition: io.c:1018
VOID EXPORT NdisFreeMemory(IN PVOID VirtualAddress, IN UINT Length, IN UINT MemoryFlags)
Definition: memory.c:110
NDIS_STATUS EXPORT NdisAllocateMemoryWithTag(OUT PVOID *VirtualAddress, IN UINT Length, IN ULONG Tag)
Definition: memory.c:21
VOID EXPORT NdisMAllocateSharedMemory(IN NDIS_HANDLE MiniportAdapterHandle, IN ULONG Length, IN BOOLEAN Cached, OUT PVOID *VirtualAddress, OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
Definition: memory.c:148
#define ULONG_PTR
Definition: config.h:101
void bar()
Definition: ehthrow.cxx:142
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum const GLvoid * addr
Definition: glext.h:9621
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
if(dx< 0)
Definition: linetemp.h:194
#define PARANDIS_MEMORY_TAG
Definition: ndis56common.h:120
#define MAX_NUM_OF_QUEUES
Definition: ndis56common.h:93
#define NdisRawReadPortUlong(Port, Data)
Definition: ndis.h:4182
#define NdisWriteRegisterUchar(Register, Data)
Definition: ndis.h:4285
#define NdisRawReadPortUshort(Port, Data)
Definition: ndis.h:4191
#define NdisZeroMemory(Destination, Length)
Definition: ndis.h:3926
unsigned int UINT
Definition: ndis.h:50
#define NdisRawReadPortUchar(Port, Data)
Definition: ndis.h:4173
#define NdisReadRegisterUlong(Register, Data)
Definition: ndis.h:4267
#define NdisWriteRegisterUshort(Register, Data)
Definition: ndis.h:4303
#define NdisReadRegisterUchar(Register, Data)
Definition: ndis.h:4258
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
#define NdisRawWritePortUlong(Port, Data)
Definition: ndis.h:4239
#define NdisWriteRegisterUlong(Register, Data)
Definition: ndis.h:4294
#define NdisRawWritePortUchar(Port, Data)
Definition: ndis.h:4230
#define NdisRawWritePortUshort(Port, Data)
Definition: ndis.h:4248
#define NdisReadRegisterUshort(Register, Data)
Definition: ndis.h:4276
VOID EXPORT NdisMSleep(IN ULONG MicrosecondsToSleep)
Definition: miniport.c:2928
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define u16
Definition: types.h:8
tBusResource PciBars[PCI_TYPE0_ADDRESSES]
Definition: ndis56common.h:170
NDIS_PHYSICAL_ADDRESS BasePA
Definition: ndis56common.h:161
BOOLEAN bPortSpace
Definition: ndis56common.h:164
tAdapterResources AdapterResources
Definition: ndis56common.h:351
NDIS_HANDLE MiniportHandle
Definition: ndis56common.h:349
tBusResource SharedMemoryRanges[MAX_NUM_OF_QUEUES]
Definition: ndis56common.h:352
Definition: http.c:7252
uint32_t * PULONG
Definition: typedefs.h:59
uint16_t * PUSHORT
Definition: typedefs.h:56
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
#define VIRTIO_MSI_NO_VECTOR
Definition: virtio_pci.h:98
#define pci_read_config_byte(vdev, where, bVal)
#define mem_get_physical_address(vdev, virt)
#define mem_free_nonpaged_block(vdev, addr)
#define pci_read_config_word(vdev, where, wVal)
#define mem_alloc_nonpaged_block(vdev, size)
#define pci_map_address_range(vdev, bar, offset, maxlen)
#define mem_alloc_contiguous_pages(vdev, size)
#define mem_free_contiguous_pages(vdev, virt)
#define vdev_sleep(vdev, msecs)
#define pci_read_config_dword(vdev, where, dwVal)
#define pci_get_resource_len(vdev, bar)
#define vdev_get_msix_vector(vdev, queue)
#define PCI_TYPE0_ADDRESSES
Definition: iotypes.h:3500