win-pvdrivers

view xennet/xennet.h @ 783:644e5ddb1b47

Handle SCSI INQUIRY command better in xenvbd
author James Harper <james.harper@bendigoit.com.au>
date Mon Feb 15 20:53:57 2010 +1100 (2010-02-15)
parents 3da023729e6b
children bf1b18b4728b
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
4 Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
21 #pragma warning(disable: 4201)
22 #pragma warning(disable: 4214)
24 #define DDKAPI
25 #include <ntddk.h>
26 #include <wdm.h>
27 #define NDIS_MINIPORT_DRIVER
28 #if NTDDI_VERSION < NTDDI_WINXP
29 # define NDIS50_MINIPORT 1
30 #else
31 # define NDIS51_MINIPORT 1
32 #endif
33 #include <ndis.h>
34 #define NTSTRSAFE_LIB
35 #include <ntstrsafe.h>
37 #define VENDOR_DRIVER_VERSION_MAJOR 0
38 #define VENDOR_DRIVER_VERSION_MINOR 10
40 #define VENDOR_DRIVER_VERSION (((VENDOR_DRIVER_VERSION_MAJOR) << 16) | (VENDOR_DRIVER_VERSION_MINOR))
42 #define __DRIVER_NAME "XenNet"
44 #include <xen_windows.h>
45 #include <memory.h>
46 #include <grant_table.h>
47 #include <event_channel.h>
48 #include <hvm/params.h>
49 #include <hvm/hvm_op.h>
50 #include <xen_public.h>
51 #include <io/ring.h>
52 #include <io/netif.h>
53 #include <io/xenbus.h>
54 #include <stdlib.h>
55 #define XENNET_POOL_TAG (ULONG) 'XenN'
58 /* Xen macros use these, so they need to be redefined to Win equivs */
59 #define wmb() KeMemoryBarrier()
60 #define mb() KeMemoryBarrier()
62 #define GRANT_INVALID_REF 0
64 #define NAME_SIZE 64
66 #define ETH_ALEN 6
68 /*
69 #define __NET_USHORT_BYTE_0(x) ((USHORT)(x & 0xFF))
70 #define __NET_USHORT_BYTE_1(x) ((USHORT)((PUCHAR)&x)[1] & 0xFF)
72 #define GET_NET_USHORT(x) ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
73 #define SET_NET_USHORT(y, x) *((USHORT *)&(y)) = ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
74 */
76 static FORCEINLINE USHORT
77 GET_NET_USHORT(USHORT data)
78 {
79 return (data << 8) | (data >> 8);
80 }
82 static FORCEINLINE USHORT
83 GET_NET_PUSHORT(PVOID pdata)
84 {
85 return (*((PUSHORT)pdata) << 8) | (*((PUSHORT)pdata) >> 8);
86 }
88 static FORCEINLINE VOID
89 SET_NET_USHORT(PVOID ptr, USHORT data)
90 {
91 *((PUSHORT)ptr) = GET_NET_USHORT(data);
92 }
94 static FORCEINLINE ULONG
95 GET_NET_ULONG(ULONG data)
96 {
97 ULONG tmp;
99 tmp = ((data & 0x00ff00ff) << 8) | ((data & 0xff00ff00) >> 8);
100 return (tmp << 16) | (tmp >> 16);
101 }
103 static FORCEINLINE ULONG
104 GET_NET_PULONG(PVOID pdata)
105 {
106 ULONG tmp;
108 tmp = ((*((PULONG)pdata) & 0x00ff00ff) << 8) | ((*((PULONG)pdata) & 0xff00ff00) >> 8);
109 return (tmp << 16) | (tmp >> 16);
110 }
112 static FORCEINLINE VOID
113 SET_NET_ULONG(PVOID ptr, ULONG data)
114 {
115 *((PULONG)ptr) = GET_NET_ULONG(data);
116 }
117 /*
118 #define GET_NET_ULONG(x) ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
119 #define SET_NET_ULONG(y, x) *((ULONG *)&(y)) = ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
120 */
122 #define SUPPORTED_PACKET_FILTERS (\
123 NDIS_PACKET_TYPE_DIRECTED | \
124 NDIS_PACKET_TYPE_MULTICAST | \
125 NDIS_PACKET_TYPE_BROADCAST | \
126 NDIS_PACKET_TYPE_PROMISCUOUS | \
127 NDIS_PACKET_TYPE_ALL_MULTICAST)
129 /* couldn't get regular xen ring macros to work...*/
130 #define __NET_RING_SIZE(type, _sz) \
131 (__RD32( \
132 (_sz - sizeof(struct type##_sring) + sizeof(union type##_sring_entry)) \
133 / sizeof(union type##_sring_entry)))
135 #define NET_TX_RING_SIZE __NET_RING_SIZE(netif_tx, PAGE_SIZE)
136 #define NET_RX_RING_SIZE __NET_RING_SIZE(netif_rx, PAGE_SIZE)
138 #pragma warning(disable: 4127) // conditional expression is constant
140 #define MIN_LARGE_SEND_SEGMENTS 4
142 /* TODO: crank this up if we support higher mtus? */
143 #define XN_HDR_SIZE 14
144 #define XN_MAX_DATA_SIZE 1500
145 #define XN_MIN_FRAME_SIZE 60
146 #define XN_MAX_FRAME_SIZE (XN_HDR_SIZE + XN_DATA_SIZE)
147 /*
148 #if !defined(OFFLOAD_LARGE_SEND)
149 #define XN_MAX_PKT_SIZE (XN_HDR_SIZE + XN_DATA_SIZE)
150 #else
151 #define XN_MAX_PKT_SIZE MAX_LARGE_SEND_OFFLOAD
152 #endif
153 */
155 #define XN_MAX_SEND_PKTS 16
157 #define XENSOURCE_MAC_HDR 0x00163E
158 #define XN_VENDOR_DESC "Xensource"
159 #define MAX_XENBUS_STR_LEN 128
161 #define RX_MIN_TARGET 8
162 #define RX_DFL_MIN_TARGET 256
163 #define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
165 //#define MAX_BUFFERS_PER_PACKET NET_RX_RING_SIZE
167 #define MIN_ETH_HEADER_LENGTH 14
168 #define MAX_ETH_HEADER_LENGTH 14
169 #define MIN_IP4_HEADER_LENGTH 20
170 #define MAX_IP4_HEADER_LENGTH (15 * 4)
171 #define MIN_TCP_HEADER_LENGTH 20
172 #define MAX_TCP_HEADER_LENGTH (15 * 4)
173 #define MAX_PKT_HEADER_LENGTH (MAX_ETH_HEADER_LENGTH + MAX_IP4_HEADER_LENGTH + MAX_TCP_HEADER_LENGTH)
175 #define MIN_LOOKAHEAD_LENGTH (MAX_IP4_HEADER_LENGTH + MAX_TCP_HEADER_LENGTH)
176 #define MAX_LOOKAHEAD_LENGTH 256
178 #define LINUX_MAX_SG_ELEMENTS 19
180 typedef struct
181 {
182 PVOID next;
183 grant_ref_t gref;
184 USHORT offset;
185 PVOID virtual;
186 PNDIS_BUFFER buffer;
187 USHORT id;
188 USHORT ref_count;
189 } shared_buffer_t;
191 typedef struct
192 {
193 PNDIS_PACKET packet; /* only set on the last packet */
194 PVOID *cb;
195 grant_ref_t gref;
196 } tx_shadow_t;
198 typedef struct {
199 PNDIS_BUFFER first_buffer;
200 PNDIS_BUFFER curr_buffer;
201 shared_buffer_t *first_pb;
202 shared_buffer_t *curr_pb;
203 PUCHAR first_buffer_virtual;
204 ULONG mdl_count;
205 ULONG curr_mdl_offset;
206 USHORT mss;
207 NDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
208 BOOLEAN csum_blank;
209 BOOLEAN data_validated;
210 BOOLEAN split_required;
211 UCHAR ip_version;
212 PUCHAR header;
213 ULONG first_buffer_length;
214 ULONG header_length;
215 UCHAR ip_proto;
216 ULONG total_length;
217 USHORT ip4_header_length;
218 USHORT ip4_length;
219 USHORT tcp_header_length;
220 BOOLEAN tcp_has_options;
221 USHORT tcp_length;
222 USHORT tcp_remaining;
223 ULONG tcp_seq;
224 BOOLEAN extra_info;
225 BOOLEAN more_frags;
226 /* anything past here doesn't get cleared automatically by the ClearPacketInfo */
227 UCHAR header_data[MAX_LOOKAHEAD_LENGTH + MAX_ETH_HEADER_LENGTH];
228 } packet_info_t;
230 #define PAGE_LIST_SIZE (max(NET_RX_RING_SIZE, NET_TX_RING_SIZE) * 4)
231 #define MULTICAST_LIST_MAX_SIZE 32
233 struct xennet_info
234 {
235 BOOLEAN inactive;
237 /* Base device vars */
238 PDEVICE_OBJECT pdo;
239 PDEVICE_OBJECT fdo;
240 PDEVICE_OBJECT lower_do;
241 //WDFDEVICE wdf_device;
242 WCHAR dev_desc[NAME_SIZE];
244 /* NDIS-related vars */
245 NDIS_HANDLE adapter_handle;
246 NDIS_MINIPORT_INTERRUPT interrupt;
247 ULONG packet_filter;
248 BOOLEAN connected;
249 BOOLEAN shutting_down;
250 BOOLEAN tx_shutting_down;
251 BOOLEAN rx_shutting_down;
252 uint8_t perm_mac_addr[ETH_ALEN];
253 uint8_t curr_mac_addr[ETH_ALEN];
254 ULONG current_lookahead;
256 /* Misc. Xen vars */
257 XENPCI_VECTORS vectors;
258 PXENPCI_DEVICE_STATE device_state;
259 evtchn_port_t event_channel;
260 ULONG state;
261 char backend_path[MAX_XENBUS_STR_LEN];
262 ULONG backend_state;
263 PVOID config_page;
264 UCHAR multicast_list[MULTICAST_LIST_MAX_SIZE][6];
265 ULONG multicast_list_size;
266 KDPC suspend_dpc;
267 PIO_WORKITEM resume_work_item;
269 /* tx related - protected by tx_lock */
270 KSPIN_LOCK tx_lock;
271 LIST_ENTRY tx_waiting_pkt_list;
272 struct netif_tx_front_ring tx;
273 ULONG tx_ring_free;
274 tx_shadow_t tx_shadows[NET_TX_RING_SIZE];
275 NDIS_HANDLE tx_buffer_pool;
276 #define TX_HEADER_BUFFER_SIZE 512
277 //#define TX_COALESCE_BUFFERS (NET_TX_RING_SIZE >> 2)
278 #define TX_COALESCE_BUFFERS (NET_TX_RING_SIZE)
279 KEVENT tx_idle_event;
280 ULONG tx_outstanding;
281 ULONG tx_id_free;
282 USHORT tx_id_list[NET_TX_RING_SIZE];
283 //ULONG tx_cb_free;
284 //ULONG tx_cb_list[TX_COALESCE_BUFFERS];
285 //ULONG tx_cb_size;
286 //shared_buffer_t tx_cbs[TX_COALESCE_BUFFERS];
287 KDPC tx_dpc;
288 NPAGED_LOOKASIDE_LIST tx_lookaside_list;
290 /* rx_related - protected by rx_lock */
291 KSPIN_LOCK rx_lock;
292 struct netif_rx_front_ring rx;
293 ULONG rx_id_free;
294 packet_info_t rxpi;
295 PNDIS_PACKET rx_packet_list[NET_RX_RING_SIZE * 2];
296 ULONG rx_packet_free;
297 KEVENT packet_returned_event;
298 //NDIS_MINIPORT_TIMER rx_timer;
299 KDPC rx_dpc;
300 KTIMER rx_timer;
301 KDPC rx_timer_dpc;
302 NDIS_HANDLE rx_packet_pool;
303 NDIS_HANDLE rx_buffer_pool;
304 ULONG rx_pb_free;
305 #define RX_PAGE_BUFFERS (NET_RX_RING_SIZE * 2)
306 ULONG rx_pb_list[RX_PAGE_BUFFERS];
307 shared_buffer_t rx_pbs[RX_PAGE_BUFFERS];
308 USHORT rx_ring_pbs[NET_RX_RING_SIZE];
309 NPAGED_LOOKASIDE_LIST rx_lookaside_list;
310 /* Receive-ring batched refills. */
311 ULONG rx_target;
312 ULONG rx_max_target;
313 ULONG rx_min_target;
315 /* how many packets are in the net stack atm */
316 ULONG rx_outstanding;
318 /* config vars from registry */
319 ULONG config_sg;
320 ULONG config_csum;
321 ULONG config_csum_rx_check;
322 ULONG config_gso;
323 ULONG config_mtu;
324 ULONG config_rx_interrupt_moderation;
326 NDIS_TASK_TCP_IP_CHECKSUM setting_csum;
327 ULONG setting_max_offload;
329 /* config stuff calculated from the above */
330 ULONG config_max_pkt_size;
332 /* stats */
333 ULONG64 stat_tx_ok;
334 ULONG64 stat_rx_ok;
335 ULONG64 stat_tx_error;
336 ULONG64 stat_rx_error;
337 ULONG64 stat_rx_no_buffer;
339 } typedef xennet_info_t;
341 VOID DDKAPI
342 XenNet_ReturnPacket(
343 IN NDIS_HANDLE MiniportAdapterContext,
344 IN PNDIS_PACKET Packet
345 );
347 BOOLEAN
348 XenNet_RxInit(xennet_info_t *xi);
350 BOOLEAN
351 XenNet_RxShutdown(xennet_info_t *xi);
353 VOID
354 XenNet_RxResumeStart(xennet_info_t *xi);
356 VOID
357 XenNet_RxResumeEnd(xennet_info_t *xi);
359 VOID
360 XenNet_TxResumeStart(xennet_info_t *xi);
362 VOID
363 XenNet_TxResumeEnd(xennet_info_t *xi);
365 VOID DDKAPI
366 XenNet_SendPackets(
367 IN NDIS_HANDLE MiniportAdapterContext,
368 IN PPNDIS_PACKET PacketArray,
369 IN UINT NumberOfPackets
370 );
372 VOID
373 XenNet_CancelSendPackets(
374 NDIS_HANDLE MiniportAdapterContext,
375 PVOID CancelId);
377 BOOLEAN
378 XenNet_TxInit(xennet_info_t *xi);
380 BOOLEAN
381 XenNet_TxShutdown(xennet_info_t *xi);
383 NDIS_STATUS DDKAPI
384 XenNet_QueryInformation(
385 IN NDIS_HANDLE MiniportAdapterContext,
386 IN NDIS_OID Oid,
387 IN PVOID InformationBuffer,
388 IN ULONG InformationBufferLength,
389 OUT PULONG BytesWritten,
390 OUT PULONG BytesNeeded);
392 NDIS_STATUS DDKAPI
393 XenNet_SetInformation(
394 IN NDIS_HANDLE MiniportAdapterContext,
395 IN NDIS_OID Oid,
396 IN PVOID InformationBuffer,
397 IN ULONG InformationBufferLength,
398 OUT PULONG BytesRead,
399 OUT PULONG BytesNeeded
400 );
402 /* return values */
403 #define PARSE_OK 0
404 #define PARSE_TOO_SMALL 1 /* first buffer is too small */
405 #define PARSE_UNKNOWN_TYPE 2
407 BOOLEAN
408 XenNet_BuildHeader(packet_info_t *pi, PVOID header, ULONG new_header_size);
409 ULONG
410 XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR buffer, ULONG min_header_size);
411 BOOLEAN
412 XenNet_FilterAcceptPacket(struct xennet_info *xi,packet_info_t *pi);
414 VOID
415 XenNet_SumIpHeader(
416 PUCHAR header,
417 USHORT ip4_header_length
418 );
420 static __forceinline VOID
421 XenNet_ClearPacketInfo(packet_info_t *pi)
422 {
423 #if 1
424 RtlZeroMemory(pi, sizeof(packet_info_t) - FIELD_OFFSET(packet_info_t, header_data));
425 #else
426 pi->mdl_count = 0;
427 pi->mss = 0;
428 pi->ip4_header_length = 0;
429 pi->tcp_header_length = 0;
430 pi->curr_mdl_index = pi->curr_mdl_offset = 0;
431 pi->extra_info = pi->more_frags = pi->csum_blank =
432 pi->data_validated = pi->split_required = 0;
433 #endif
434 }
436 /* Get some data from the current packet, but don't cross a page boundry. */
437 static __forceinline ULONG
438 XenNet_QueryData(packet_info_t *pi, ULONG length)
439 {
440 ULONG offset_in_page;
442 if (length > MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset)
443 length = MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset;
445 offset_in_page = (MmGetMdlByteOffset(pi->curr_buffer) + pi->curr_mdl_offset) & (PAGE_SIZE - 1);
446 if (offset_in_page + length > PAGE_SIZE)
447 length = PAGE_SIZE - offset_in_page;
449 return length;
450 }
452 /* Move the pointers forward by the given amount. No error checking is done. */
453 static __forceinline VOID
454 XenNet_EatData(packet_info_t *pi, ULONG length)
455 {
456 pi->curr_mdl_offset += length;
457 if (pi->curr_mdl_offset >= MmGetMdlByteCount(pi->curr_buffer))
458 {
459 pi->curr_mdl_offset -= MmGetMdlByteCount(pi->curr_buffer);
460 NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
461 }
462 }