win-pvdrivers

annotate xennet/xennet_oid.c @ 1099:27bd2a5a4704

License change from GPL to BSD
author James Harper <james.harper@bendigoit.com.au>
date Thu Mar 13 13:38:31 2014 +1100 (2014-03-13)
parents c21a4feb4a27
children
rev   line source
james@1007 1 /*
james@1099 2 PV Drivers for Windows Xen HVM Domains
james@1007 3
james@1099 4 Copyright (c) 2014, James Harper
james@1099 5 All rights reserved.
james@1007 6
james@1099 7 Redistribution and use in source and binary forms, with or without
james@1099 8 modification, are permitted provided that the following conditions are met:
james@1099 9 * Redistributions of source code must retain the above copyright
james@1099 10 notice, this list of conditions and the following disclaimer.
james@1099 11 * Redistributions in binary form must reproduce the above copyright
james@1099 12 notice, this list of conditions and the following disclaimer in the
james@1099 13 documentation and/or other materials provided with the distribution.
james@1099 14 * Neither the name of James Harper nor the
james@1099 15 names of its contributors may be used to endorse or promote products
james@1099 16 derived from this software without specific prior written permission.
james@1007 17
james@1099 18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
james@1099 19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
james@1099 20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
james@1099 21 DISCLAIMED. IN NO EVENT SHALL JAMES HARPER BE LIABLE FOR ANY
james@1099 22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
james@1099 23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
james@1099 24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
james@1099 25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
james@1099 26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
james@1099 27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
james@1007 28 */
james@1007 29
james@1007 30 #include "xennet.h"
james@1007 31
james@1007 32 #define DEF_OID_QUERY(oid, min_length) {oid, #oid, min_length, XenNet_Query##oid, NULL}
james@1007 33 #define DEF_OID_QUERYSET(oid, min_length) {oid, #oid, min_length, XenNet_Query##oid, XenNet_Set##oid}
james@1007 34 #define DEF_OID_SET(oid, min_length) {oid, #oid, min_length, NULL, XenNet_Set##oid}
james@1007 35 #define DEF_OID_NONE(oid) {oid, #oid, 0, NULL, NULL} /* define this for a silent but unsupported oid */
james@1007 36
james@1007 37 #define DEF_OID_QUERY_STAT(oid) DEF_OID_QUERY(##oid, 0) /* has to be 0 so the 4/8 size works */
james@1007 38 #define DEF_OID_QUERY_ULONG(oid) DEF_OID_QUERY(##oid, sizeof(ULONG))
james@1007 39 #define DEF_OID_QUERYSET_ULONG(oid) DEF_OID_QUERYSET(##oid, sizeof(ULONG))
james@1007 40 #define DEF_OID_SET_ULONG(oid) DEF_OID_SET(##oid, sizeof(ULONG))
james@1007 41
james@1007 42 #define DEF_OID_QUERY_ROUTINE(oid, value, length) \
james@1007 43 NDIS_STATUS \
james@1007 44 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
james@1007 45 struct xennet_info *xi = context; \
james@1007 46 UNREFERENCED_PARAMETER(xi); \
james@1007 47 if (information_buffer_length < length) \
james@1007 48 { \
james@1007 49 *bytes_needed = length; \
james@1007 50 return NDIS_STATUS_BUFFER_TOO_SHORT; \
james@1007 51 } \
james@1007 52 *bytes_written = length; \
james@1007 53 NdisMoveMemory(information_buffer, value, length); \
james@1007 54 return STATUS_SUCCESS; \
james@1007 55 }
james@1007 56
james@1007 57 #define DEF_OID_QUERY_ULONG_ROUTINE(oid, value) \
james@1007 58 NDIS_STATUS \
james@1007 59 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
james@1007 60 struct xennet_info *xi = context; \
james@1007 61 UNREFERENCED_PARAMETER(xi); \
james@1007 62 UNREFERENCED_PARAMETER(information_buffer_length); \
james@1007 63 UNREFERENCED_PARAMETER(bytes_needed); \
james@1007 64 *bytes_written = sizeof(ULONG); \
james@1007 65 *(ULONG *)information_buffer = value; \
james@1007 66 return STATUS_SUCCESS; \
james@1007 67 }
james@1007 68
james@1007 69 #define DEF_OID_QUERY_STAT_ROUTINE(oid, value) \
james@1007 70 NDIS_STATUS \
james@1007 71 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
james@1007 72 struct xennet_info *xi = context; \
james@1007 73 UNREFERENCED_PARAMETER(xi); \
james@1007 74 if (information_buffer_length >= sizeof(ULONG64)) \
james@1007 75 { \
james@1007 76 *bytes_written = sizeof(ULONG64); \
james@1007 77 *(ULONG64 *)information_buffer = (value); \
james@1007 78 } \
james@1007 79 else if (information_buffer_length >= sizeof(ULONG)) \
james@1007 80 { \
james@1007 81 *bytes_written = sizeof(ULONG); \
james@1007 82 *bytes_needed = sizeof(ULONG64); \
james@1007 83 *(ULONG *)information_buffer = (ULONG)(value); \
james@1007 84 } \
james@1007 85 else \
james@1007 86 { \
james@1007 87 *bytes_needed = sizeof(ULONG64); \
james@1007 88 return NDIS_STATUS_BUFFER_TOO_SHORT; \
james@1007 89 } \
james@1007 90 return STATUS_SUCCESS; \
james@1007 91 }
james@1007 92
james@1007 93 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_TOTAL_SIZE, xi->current_mtu_value + XN_HDR_SIZE)
james@1007 94 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_CURRENT_PACKET_FILTER, xi->packet_filter)
james@1007 95 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_CURRENT_LOOKAHEAD, xi->current_lookahead)
james@1007 96 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_TRANSMIT_BUFFER_SPACE, PAGE_SIZE * NET_TX_RING_SIZE * 4)
james@1007 97 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_RECEIVE_BUFFER_SPACE, PAGE_SIZE * NET_RX_RING_SIZE * 2)
james@1007 98 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_TRANSMIT_BLOCK_SIZE, PAGE_SIZE)
james@1007 99 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_RECEIVE_BLOCK_SIZE, PAGE_SIZE)
james@1007 100 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_SEND_PACKETS, 0)
james@1007 101 DEF_OID_QUERY_ULONG_ROUTINE(OID_802_3_MAXIMUM_LIST_SIZE, MULTICAST_LIST_MAX_SIZE)
james@1007 102 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_HARDWARE_STATUS, (xi->device_state == DEVICE_STATE_INACTIVE || xi->device_state == DEVICE_STATE_ACTIVE)?NdisHardwareStatusReady:NdisHardwareStatusInitializing)
james@1007 103 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_VENDOR_ID, 0xFFFFFF) // Not guaranteed to be XENSOURCE_MAC_HDR;
james@1007 104 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_VENDOR_DRIVER_VERSION, VENDOR_DRIVER_VERSION)
james@1007 105 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_SUPPORTED, NdisMedium802_3)
james@1007 106 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_IN_USE, NdisMedium802_3)
james@1007 107 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_LOOKAHEAD, MAX_LOOKAHEAD_LENGTH)
james@1007 108
james@1007 109 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 110 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_FRAME_SIZE, xi->current_mtu_value);
james@1007 111 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAC_OPTIONS, NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_NO_LOOPBACK);
james@1007 112 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_CONNECT_STATUS, (xi->device_state == DEVICE_STATE_ACTIVE)?NdisMediaStateConnected:NdisMediaStateDisconnected);
james@1007 113 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_LINK_SPEED, (ULONG)(MAX_LINK_SPEED / 100));
james@1007 114
james@1007 115 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_OK, xi->stat_tx_ok)
james@1007 116 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_ERROR, xi->stat_tx_error)
james@1007 117 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_OK, xi->stat_rx_ok)
james@1007 118 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_ERROR, xi->stat_rx_error)
james@1007 119 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_NO_BUFFER, xi->stat_rx_no_buffer)
james@914 120 #else
james@1007 121 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_OK, xi->stats.ifHCOutUcastPkts + xi->stats.ifHCOutMulticastPkts + xi->stats.ifHCOutBroadcastPkts)
james@1007 122 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_ERROR, xi->stats.ifOutErrors)
james@1007 123 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_OK, xi->stats.ifHCInUcastPkts + xi->stats.ifHCInMulticastPkts + xi->stats.ifHCInBroadcastPkts)
james@1007 124 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_ERROR, xi->stats.ifInErrors)
james@1007 125 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_NO_BUFFER, xi->stats.ifInDiscards)
james@914 126 #endif
james@1007 127 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_RCV_ERROR_ALIGNMENT, 0)
james@1007 128 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_XMIT_ONE_COLLISION, 0)
james@1007 129 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_XMIT_MORE_COLLISIONS, 0)
james@1007 130
james@1007 131 DEF_OID_QUERY_ROUTINE(OID_GEN_VENDOR_DESCRIPTION, XN_VENDOR_DESC, sizeof(XN_VENDOR_DESC))
james@1007 132
james@1007 133 DEF_OID_QUERY_ROUTINE(OID_802_3_PERMANENT_ADDRESS, xi->perm_mac_addr, ETH_ALEN)
james@1007 134 DEF_OID_QUERY_ROUTINE(OID_802_3_CURRENT_ADDRESS, xi->curr_mac_addr, ETH_ALEN)
james@1007 135
james@1007 136 DEF_OID_QUERY_ROUTINE(OID_802_3_MULTICAST_LIST, xi->multicast_list, xi->multicast_list_size * 6)
james@1007 137
james@1007 138 NDIS_STATUS
james@1007 139 XenNet_SetOID_802_3_MULTICAST_LIST(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 140 struct xennet_info *xi = context;
james@1007 141 UCHAR *multicast_list;
james@1007 142 int i;
james@1007 143 UNREFERENCED_PARAMETER(bytes_read);
james@1007 144 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 145
james@1007 146 if (information_buffer_length > MULTICAST_LIST_MAX_SIZE * 6) {
james@1007 147 return NDIS_STATUS_MULTICAST_FULL;
james@1007 148 }
james@1007 149
james@1007 150 if (information_buffer_length % 6 != 0) {
james@1007 151 return NDIS_STATUS_MULTICAST_FULL;
james@1007 152 }
james@1007 153 multicast_list = information_buffer;
james@1007 154 for (i = 0; i < (int)information_buffer_length / 6; i++) {
james@1007 155 if (!(multicast_list[i * 6 + 0] & 0x01)) {
james@1007 156 FUNCTION_MSG("Address %d (%02x:%02x:%02x:%02x:%02x:%02x) is not a multicast address\n", i,
james@1007 157 (ULONG)multicast_list[i * 6 + 0], (ULONG)multicast_list[i * 6 + 1],
james@1007 158 (ULONG)multicast_list[i * 6 + 2], (ULONG)multicast_list[i * 6 + 3],
james@1007 159 (ULONG)multicast_list[i * 6 + 4], (ULONG)multicast_list[i * 6 + 5]);
james@1007 160 /* the docs say that we should return NDIS_STATUS_MULTICAST_FULL if we get an invalid multicast address but I'm not sure if that's the case... */
james@1007 161 }
james@1007 162 }
james@1007 163 memcpy(xi->multicast_list, multicast_list, information_buffer_length);
james@1007 164 xi->multicast_list_size = information_buffer_length / 6;
james@1007 165 return NDIS_STATUS_SUCCESS;
james@1007 166 }
james@1007 167
james@1007 168 NDIS_STATUS
james@1007 169 XenNet_SetOID_GEN_CURRENT_PACKET_FILTER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 170 struct xennet_info *xi = context;
james@1007 171 PULONG data = information_buffer;
james@1007 172
james@1007 173 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 174 *bytes_needed = sizeof(ULONG64);
james@1007 175 if (*data & NDIS_PACKET_TYPE_DIRECTED)
james@1007 176 FUNCTION_MSG("NDIS_PACKET_TYPE_DIRECTED\n");
james@1007 177 if (*data & NDIS_PACKET_TYPE_MULTICAST)
james@1007 178 FUNCTION_MSG("NDIS_PACKET_TYPE_MULTICAST\n");
james@1007 179 if (*data & NDIS_PACKET_TYPE_ALL_MULTICAST)
james@1007 180 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_MULTICAST\n");
james@1007 181 if (*data & NDIS_PACKET_TYPE_BROADCAST)
james@1007 182 FUNCTION_MSG("NDIS_PACKET_TYPE_BROADCAST\n");
james@1007 183 if (*data & NDIS_PACKET_TYPE_PROMISCUOUS)
james@1007 184 FUNCTION_MSG("NDIS_PACKET_TYPE_PROMISCUOUS\n");
james@1007 185 if (*data & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
james@1007 186 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_FUNCTIONAL (not supported)\n");
james@1007 187 if (*data & NDIS_PACKET_TYPE_ALL_LOCAL)
james@1007 188 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_LOCAL (not supported)\n");
james@1007 189 if (*data & NDIS_PACKET_TYPE_FUNCTIONAL)
james@1007 190 FUNCTION_MSG("NDIS_PACKET_TYPE_FUNCTIONAL (not supported)\n");
james@1007 191 if (*data & NDIS_PACKET_TYPE_GROUP)
james@1007 192 FUNCTION_MSG("NDIS_PACKET_TYPE_GROUP (not supported)\n");
james@1007 193 if (*data & ~SUPPORTED_PACKET_FILTERS) {
james@1007 194 FUNCTION_MSG("returning NDIS_STATUS_NOT_SUPPORTED\n");
james@1007 195 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 196 }
james@1007 197 xi->packet_filter = *(ULONG *)data;
james@1007 198 *bytes_read = sizeof(ULONG);
james@1007 199 return NDIS_STATUS_SUCCESS;
james@1007 200 }
james@1007 201
james@1007 202 NDIS_STATUS
james@1007 203 XenNet_SetOID_GEN_CURRENT_LOOKAHEAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 204 struct xennet_info *xi = context;
james@1007 205 PULONG data = information_buffer;
james@1007 206 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 207 UNREFERENCED_PARAMETER(bytes_read);
james@1007 208 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 209 xi->current_lookahead = *(ULONG *)data;
james@1007 210 FUNCTION_MSG("Set OID_GEN_CURRENT_LOOKAHEAD %d (%p)\n", xi->current_lookahead, xi);
james@1007 211 return NDIS_STATUS_SUCCESS;
james@1007 212 }
james@1007 213
james@1007 214 NDIS_STATUS
james@1007 215 XenNet_SetOID_GEN_LINK_PARAMETERS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 216 UNREFERENCED_PARAMETER(context);
james@1007 217 UNREFERENCED_PARAMETER(information_buffer);
james@1007 218 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 219 UNREFERENCED_PARAMETER(bytes_read);
james@1007 220 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 221 return STATUS_NOT_SUPPORTED;
james@1007 222 }
james@1007 223
james@1007 224 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 225 NDIS_STATUS
james@1007 226 XenNet_QueryOID_GEN_SUPPORTED_LIST(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
james@1007 227 PNDIS_OID supported_oids;
james@1007 228 int i;
james@1007 229
james@1007 230 UNREFERENCED_PARAMETER(context);
james@1007 231 UNREFERENCED_PARAMETER(information_buffer);
james@1007 232 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 233 UNREFERENCED_PARAMETER(bytes_written);
james@1007 234 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 235
james@1007 236 for (i = 0; xennet_oids[i].oid; i++);
james@1007 237
james@1007 238 if (information_buffer_length < sizeof(NDIS_OID) * i) {
james@1007 239 *bytes_needed = sizeof(NDIS_OID) * i;
james@1007 240 return NDIS_STATUS_BUFFER_TOO_SHORT;
james@1007 241 }
james@1007 242
james@1007 243 supported_oids = information_buffer;
james@1007 244 for (i = 0; xennet_oids[i].oid; i++) {
james@1007 245 supported_oids[i] = xennet_oids[i].oid;
james@1007 246 FUNCTION_MSG("Supporting %08x (%s) %s %d bytes\n", xennet_oids[i].oid, xennet_oids[i].oid_name, (xennet_oids[i].query_routine?(xennet_oids[i].set_routine?"get/set":"get only"):(xennet_oids[i].set_routine?"set only":"none")), xennet_oids[i].min_length);
james@1007 247 }
james@1007 248 return STATUS_SUCCESS;
james@1007 249 }
james@1007 250
james@1007 251 NDIS_STATUS
james@1007 252 XenNet_QueryOID_GEN_DRIVER_VERSION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
james@1007 253 UNREFERENCED_PARAMETER(context);
james@1007 254 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 255 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 256 *(PUSHORT)information_buffer = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
james@1007 257 *bytes_written = sizeof(USHORT);
james@1007 258 return STATUS_SUCCESS;
james@1007 259 }
james@1007 260
james@1007 261 NDIS_STATUS
james@1007 262 XenNet_QueryOID_PNP_CAPABILITIES(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
james@1007 263 PNDIS_PNP_CAPABILITIES npc = (PNDIS_PNP_CAPABILITIES)information_buffer;
james@1007 264 UNREFERENCED_PARAMETER(context);
james@1007 265 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 266 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 267 npc->Flags = 0;
james@1007 268 npc->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
james@1007 269 npc->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
james@1007 270 npc->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
james@1007 271 *bytes_written = sizeof(NDIS_PNP_CAPABILITIES);
james@1007 272 return STATUS_SUCCESS;
james@1007 273 }
james@1007 274
james@1007 275 NDIS_STATUS
james@1007 276 XenNet_QueryOID_PNP_QUERY_POWER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
james@1007 277 UNREFERENCED_PARAMETER(context);
james@1007 278 UNREFERENCED_PARAMETER(information_buffer);
james@1007 279 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 280 UNREFERENCED_PARAMETER(bytes_written);
james@1007 281 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 282 /* all we need to do here is return STATUS_SUCCESS to acknowledge - SET_POWER will happen later */
james@1007 283 return STATUS_SUCCESS;
james@1007 284 }
james@1007 285
james@1007 286 NDIS_STATUS
james@1007 287 XenNet_SetOID_GEN_PROTOCOL_OPTIONS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 288 UNREFERENCED_PARAMETER(context);
james@1007 289 UNREFERENCED_PARAMETER(information_buffer);
james@1007 290 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 291 UNREFERENCED_PARAMETER(bytes_read);
james@1007 292 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 293 /* nothing useful here */
james@1007 294 return STATUS_SUCCESS;
james@1007 295 }
james@1007 296
james@1007 297 NDIS_STATUS
james@1007 298 XenNet_QueryOID_TCP_TASK_OFFLOAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
james@1007 299 struct xennet_info *xi = context;
james@1007 300 PNDIS_TASK_OFFLOAD_HEADER ntoh;
james@1007 301 PNDIS_TASK_OFFLOAD nto;
james@1007 302 PNDIS_TASK_TCP_IP_CHECKSUM nttic;
james@1007 303 PNDIS_TASK_TCP_LARGE_SEND nttls;
james@1007 304
james@1007 305 *bytes_needed = sizeof(NDIS_TASK_OFFLOAD_HEADER);
james@1007 306
james@1007 307 if (xi->backend_csum_supported)
james@1007 308 *bytes_needed += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
james@1007 309
james@1007 310 if (xi->backend_gso_value)
james@1007 311 *bytes_needed += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + sizeof(NDIS_TASK_TCP_LARGE_SEND);
james@1007 312
james@1007 313 if (*bytes_needed > information_buffer_length)
james@1007 314 return NDIS_STATUS_BUFFER_TOO_SHORT;
james@1007 315
james@1007 316 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)information_buffer;
james@1007 317 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
james@1007 318 || ntoh->Size != sizeof(*ntoh)
james@1007 319 || !(ntoh->EncapsulationFormat.Encapsulation == IEEE_802_3_Encapsulation
james@1007 320 || (ntoh->EncapsulationFormat.Encapsulation == UNSPECIFIED_Encapsulation
james@1007 321 && ntoh->EncapsulationFormat.EncapsulationHeaderSize == XN_HDR_SIZE))) {
james@1007 322 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 323 }
james@1007 324
james@1007 325 ntoh->OffsetFirstTask = 0;
james@1007 326 nto = NULL;
james@1007 327
james@1007 328 if (xi->backend_csum_supported) {
james@1007 329 if (ntoh->OffsetFirstTask == 0) {
james@1007 330 ntoh->OffsetFirstTask = ntoh->Size;
james@1007 331 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
james@1007 332 } else {
james@1007 333 nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
james@1007 334 + nto->TaskBufferLength;
james@1007 335 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
james@1007 336 }
james@1007 337 /* fill in first nto */
james@1007 338 nto->Version = NDIS_TASK_OFFLOAD_VERSION;
james@1007 339 nto->Size = sizeof(NDIS_TASK_OFFLOAD);
james@1007 340 nto->Task = TcpIpChecksumNdisTask;
james@1007 341 nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
james@1007 342
james@1007 343 FUNCTION_MSG("config_csum enabled\n");
james@1007 344 FUNCTION_MSG("nto = %p\n", nto);
james@1007 345 FUNCTION_MSG("nto->Size = %d\n", nto->Size);
james@1007 346 FUNCTION_MSG("nto->TaskBufferLength = %d\n", nto->TaskBufferLength);
james@1007 347
james@1007 348 /* fill in checksum offload struct */
james@1007 349 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
james@1007 350 nttic->V4Transmit.IpChecksum = 0;
james@1007 351 nttic->V4Transmit.IpOptionsSupported = 0;
james@1007 352 nttic->V4Transmit.TcpChecksum = 1;
james@1007 353 nttic->V4Transmit.TcpOptionsSupported = 1;
james@1007 354 nttic->V4Transmit.UdpChecksum = 1;
james@1007 355 nttic->V4Receive.IpChecksum = 1;
james@1007 356 nttic->V4Receive.IpOptionsSupported = 1;
james@1007 357 nttic->V4Receive.TcpChecksum = 1;
james@1007 358 nttic->V4Receive.TcpOptionsSupported = 1;
james@1007 359 nttic->V4Receive.UdpChecksum = 1;
james@1007 360 nttic->V6Transmit.IpOptionsSupported = 0;
james@1007 361 nttic->V6Transmit.TcpOptionsSupported = 0;
james@1007 362 nttic->V6Transmit.TcpChecksum = 0;
james@1007 363 nttic->V6Transmit.UdpChecksum = 0;
james@1007 364 nttic->V6Receive.IpOptionsSupported = 0;
james@1007 365 nttic->V6Receive.TcpOptionsSupported = 0;
james@1007 366 nttic->V6Receive.TcpChecksum = 0;
james@1007 367 nttic->V6Receive.UdpChecksum = 0;
james@1007 368 }
james@1007 369 if (xi->backend_gso_value) {
james@1007 370 if (ntoh->OffsetFirstTask == 0) {
james@1007 371 ntoh->OffsetFirstTask = ntoh->Size;
james@1007 372 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
james@1007 373 } else {
james@1007 374 nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
james@1007 375 + nto->TaskBufferLength;
james@1007 376 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
james@1007 377 }
james@1007 378
james@1007 379 /* fill in second nto */
james@1007 380 nto->Version = NDIS_TASK_OFFLOAD_VERSION;
james@1007 381 nto->Size = sizeof(NDIS_TASK_OFFLOAD);
james@1007 382 nto->Task = TcpLargeSendNdisTask;
james@1007 383 nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
james@1007 384
james@1007 385 FUNCTION_MSG("config_gso enabled\n");
james@1007 386 FUNCTION_MSG("nto = %p\n", nto);
james@1007 387 FUNCTION_MSG("nto->Size = %d\n", nto->Size);
james@1007 388 FUNCTION_MSG("nto->TaskBufferLength = %d\n", nto->TaskBufferLength);
james@1007 389
james@1007 390 /* fill in large send struct */
james@1007 391 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
james@1007 392 nttls->Version = 0;
james@1007 393 nttls->MaxOffLoadSize = xi->backend_gso_value;
james@1007 394 nttls->MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
james@1007 395 nttls->TcpOptions = FALSE; /* linux can't handle this */
james@1007 396 nttls->IpOptions = FALSE; /* linux can't handle this */
james@1007 397 FUNCTION_MSG("&(nttls->IpOptions) = %p\n", &(nttls->IpOptions));
james@1007 398 }
james@1007 399
james@1007 400 if (nto)
james@1007 401 nto->OffsetNextTask = 0; /* last one */
james@1007 402
james@1007 403 *bytes_written = *bytes_needed;
james@1007 404 return STATUS_SUCCESS;
james@1007 405 }
james@1007 406
james@1007 407 NDIS_STATUS
james@1007 408 XenNet_SetOID_TCP_TASK_OFFLOAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 409 struct xennet_info *xi = context;
james@1007 410 PNDIS_TASK_OFFLOAD_HEADER ntoh;
james@1007 411 PNDIS_TASK_OFFLOAD nto;
james@1007 412 PNDIS_TASK_TCP_IP_CHECKSUM nttic = NULL;
james@1007 413 PNDIS_TASK_TCP_LARGE_SEND nttls = NULL;
james@1007 414 ULONG offset;
james@1007 415
james@1007 416 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 417 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 418
james@1007 419 // we should disable everything here, then enable what has been set
james@1007 420 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)information_buffer;
james@1007 421 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION) {
james@1007 422 FUNCTION_MSG("Invalid version (%d passed but must be %d)\n", ntoh->Version, NDIS_TASK_OFFLOAD_VERSION);
james@1007 423 return NDIS_STATUS_INVALID_DATA;
james@1007 424 }
james@1007 425 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION || ntoh->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER)) {
james@1007 426 FUNCTION_MSG("Invalid size (%d passed but must be %d)\n", ntoh->Size, sizeof(NDIS_TASK_OFFLOAD_HEADER));
james@1007 427 return NDIS_STATUS_INVALID_DATA;
james@1007 428 }
james@1007 429 *bytes_read = sizeof(NDIS_TASK_OFFLOAD_HEADER);
james@1007 430 offset = ntoh->OffsetFirstTask;
james@1007 431 nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
james@1007 432 while (offset != 0) {
james@1007 433 *bytes_read += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
james@1007 434 nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
james@1007 435 switch (nto->Task) {
james@1007 436 case TcpIpChecksumNdisTask:
james@1007 437 *bytes_read += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
james@1007 438 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
james@1007 439 FUNCTION_MSG("TcpIpChecksumNdisTask\n");
james@1007 440 FUNCTION_MSG(" V4Transmit.IpOptionsSupported = %d\n", nttic->V4Transmit.IpOptionsSupported);
james@1007 441 FUNCTION_MSG(" V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported);
james@1007 442 FUNCTION_MSG(" V4Transmit.TcpChecksum = %d\n", nttic->V4Transmit.TcpChecksum);
james@1007 443 FUNCTION_MSG(" V4Transmit.UdpChecksum = %d\n", nttic->V4Transmit.UdpChecksum);
james@1007 444 FUNCTION_MSG(" V4Transmit.IpChecksum = %d\n", nttic->V4Transmit.IpChecksum);
james@1007 445 FUNCTION_MSG(" V4Receive.IpOptionsSupported = %d\n", nttic->V4Receive.IpOptionsSupported);
james@1007 446 FUNCTION_MSG(" V4Receive.TcpOptionsSupported = %d\n", nttic->V4Receive.TcpOptionsSupported);
james@1007 447 FUNCTION_MSG(" V4Receive.TcpChecksum = %d\n", nttic->V4Receive.TcpChecksum);
james@1007 448 FUNCTION_MSG(" V4Receive.UdpChecksum = %d\n", nttic->V4Receive.UdpChecksum);
james@1007 449 FUNCTION_MSG(" V4Receive.IpChecksum = %d\n", nttic->V4Receive.IpChecksum);
james@1007 450 FUNCTION_MSG(" V6Transmit.IpOptionsSupported = %d\n", nttic->V6Transmit.IpOptionsSupported);
james@1007 451 FUNCTION_MSG(" V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported);
james@1007 452 FUNCTION_MSG(" V6Transmit.TcpChecksum = %d\n", nttic->V6Transmit.TcpChecksum);
james@1007 453 FUNCTION_MSG(" V6Transmit.UdpChecksum = %d\n", nttic->V6Transmit.UdpChecksum);
james@1007 454 FUNCTION_MSG(" V6Receive.IpOptionsSupported = %d\n", nttic->V6Receive.IpOptionsSupported);
james@1007 455 FUNCTION_MSG(" V6Receive.TcpOptionsSupported = %d\n", nttic->V6Receive.TcpOptionsSupported);
james@1007 456 FUNCTION_MSG(" V6Receive.TcpChecksum = %d\n", nttic->V6Receive.TcpChecksum);
james@1007 457 FUNCTION_MSG(" V6Receive.UdpChecksum = %d\n", nttic->V6Receive.UdpChecksum);
james@1007 458 /* check for stuff we outright don't support */
james@1007 459 if (nttic->V6Transmit.IpOptionsSupported ||
james@1007 460 nttic->V6Transmit.TcpOptionsSupported ||
james@1007 461 nttic->V6Transmit.TcpChecksum ||
james@1007 462 nttic->V6Transmit.UdpChecksum ||
james@1007 463 nttic->V6Receive.IpOptionsSupported ||
james@1007 464 nttic->V6Receive.TcpOptionsSupported ||
james@1007 465 nttic->V6Receive.TcpChecksum ||
james@1007 466 nttic->V6Receive.UdpChecksum) {
james@1007 467 FUNCTION_MSG("IPv6 offload not supported\n");
james@1007 468 return NDIS_STATUS_INVALID_DATA;
james@1007 469 }
james@1007 470 if (nttic->V4Transmit.IpOptionsSupported || nttic->V4Transmit.IpChecksum) {
james@1007 471 FUNCTION_MSG("IPv4 IP Transmit offload not supported\n");
james@1007 472 return NDIS_STATUS_INVALID_DATA;
james@1007 473 }
james@1007 474 if (nttic->V4Receive.IpOptionsSupported && !nttic->V4Receive.IpChecksum) {
james@1007 475 FUNCTION_MSG("Invalid combination\n");
james@1007 476 return NDIS_STATUS_INVALID_DATA;
james@1007 477 }
james@1007 478 if (nttic->V4Transmit.TcpOptionsSupported && !nttic->V4Transmit.TcpChecksum) {
james@1007 479 FUNCTION_MSG("Invalid combination\n");
james@1007 480 return NDIS_STATUS_INVALID_DATA;
james@1007 481 }
james@1007 482 if (nttic->V4Receive.TcpOptionsSupported && !nttic->V4Receive.TcpChecksum) {
james@1007 483 FUNCTION_MSG("Invalid combination\n");
james@1007 484 return NDIS_STATUS_INVALID_DATA;
james@1007 485 }
james@1007 486 break;
james@1007 487 case TcpLargeSendNdisTask:
james@1007 488 *bytes_read += sizeof(NDIS_TASK_TCP_LARGE_SEND);
james@1007 489 FUNCTION_MSG("TcpLargeSendNdisTask\n");
james@1007 490 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
james@1007 491 FUNCTION_MSG(" MaxOffLoadSize = %d\n", nttls->MaxOffLoadSize);
james@1007 492 FUNCTION_MSG(" MinSegmentCount = %d\n", nttls->MinSegmentCount);
james@1007 493 FUNCTION_MSG(" TcpOptions = %d\n", nttls->TcpOptions);
james@1007 494 FUNCTION_MSG(" IpOptions = %d\n", nttls->IpOptions);
james@1007 495 if (nttls->MinSegmentCount != MIN_LARGE_SEND_SEGMENTS) {
james@1007 496 FUNCTION_MSG("MinSegmentCount should be %d\n", MIN_LARGE_SEND_SEGMENTS);
james@1007 497 return NDIS_STATUS_INVALID_DATA;
james@1007 498 }
james@1007 499 if (nttls->IpOptions) {
james@1007 500 FUNCTION_MSG("IpOptions not supported\n");
james@1007 501 return NDIS_STATUS_INVALID_DATA;
james@1007 502 }
james@1007 503 if (nttls->TcpOptions) {
james@1007 504 FUNCTION_MSG("TcpOptions not supported\n");
james@1007 505 return NDIS_STATUS_INVALID_DATA;
james@1007 506 }
james@1007 507 break;
james@1007 508 default:
james@1007 509 FUNCTION_MSG("Unknown Task %d\n", nto->Task);
james@1007 510 }
james@1007 511 offset = nto->OffsetNextTask;
james@1007 512 }
james@1007 513 if (nttic != NULL) {
james@1007 514 xi->current_csum_supported = TRUE;
james@1007 515 xi->setting_csum = *nttic;
james@1007 516 } else {
james@1007 517 RtlZeroMemory(&xi->setting_csum, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
james@1007 518 FUNCTION_MSG("csum offload disabled\n", nto->Task);
james@1007 519 }
james@1007 520 if (nttls != NULL)
james@1007 521 xi->current_gso_value = nttls->MaxOffLoadSize;
james@1007 522 else {
james@1007 523 xi->current_gso_value = 0;
james@1007 524 FUNCTION_MSG("LSO disabled\n", nto->Task);
james@1007 525 }
james@1007 526 return STATUS_SUCCESS;
james@1007 527 }
james@1007 528 #else
james@1007 529 NDIS_STATUS
james@1007 530 XenNet_QueryOID_GEN_INTERRUPT_MODERATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
james@1007 531 PNDIS_INTERRUPT_MODERATION_PARAMETERS nimp;
james@1007 532 UNREFERENCED_PARAMETER(context);
james@1011 533 UNREFERENCED_PARAMETER(bytes_needed);
james@1011 534 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 535 nimp = (PNDIS_INTERRUPT_MODERATION_PARAMETERS)information_buffer;
james@1007 536 nimp->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
james@1007 537 nimp->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
james@1007 538 nimp->Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
james@1007 539 nimp->Flags = 0;
james@1007 540 nimp->InterruptModeration = NdisInterruptModerationNotSupported;
james@1011 541 *bytes_written = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
james@1007 542 return STATUS_SUCCESS;
james@1007 543 }
james@1007 544
james@1007 545 NDIS_STATUS
james@1007 546 XenNet_SetOID_GEN_INTERRUPT_MODERATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 547 UNREFERENCED_PARAMETER(context);
james@1007 548 UNREFERENCED_PARAMETER(information_buffer);
james@1007 549 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 550 UNREFERENCED_PARAMETER(bytes_read);
james@1007 551 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 552 return STATUS_NOT_SUPPORTED;
james@1007 553 }
james@1007 554
james@1007 555 NDIS_STATUS
james@1007 556 XenNet_QueryOID_GEN_STATISTICS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
james@1007 557 struct xennet_info *xi = context;
james@1011 558 UNREFERENCED_PARAMETER(bytes_needed);
james@1011 559 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 560
james@1007 561 NdisMoveMemory(information_buffer, &xi->stats, sizeof(NDIS_STATISTICS_INFO));
james@1011 562 *bytes_written = sizeof(NDIS_STATISTICS_INFO);
james@1007 563 return STATUS_SUCCESS;
james@1007 564 }
james@1007 565
james@1007 566 NDIS_STATUS
james@1007 567 XenNet_SetOID_OFFLOAD_ENCAPSULATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 568 struct xennet_info *xi = context;
james@1011 569 PNDIS_OFFLOAD_ENCAPSULATION noe = (PNDIS_OFFLOAD_ENCAPSULATION)information_buffer;
james@1011 570 UNREFERENCED_PARAMETER(bytes_needed);
james@1011 571 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 572 /* mostly assume that NDIS vets the settings for us */
james@1007 573 if (noe->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3) {
james@1007 574 FUNCTION_MSG("Unknown Encapsulation Type %d\n", noe->IPv4.EncapsulationType);
james@1007 575 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 576 }
james@1007 577
james@1007 578 switch(noe->IPv4.Enabled) {
james@1007 579 case NDIS_OFFLOAD_SET_ON:
james@1007 580 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_ON\n");
james@1007 581 xi->current_csum_supported = xi->backend_csum_supported && xi->frontend_csum_supported;
james@1007 582 xi->current_gso_value = min(xi->backend_csum_supported, xi->frontend_csum_supported);
james@1007 583 break;
james@1007 584 case NDIS_OFFLOAD_SET_OFF:
james@1007 585 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_OFF\n");
james@1007 586 xi->current_csum_supported = FALSE;
james@1007 587 xi->current_gso_value = 0;
james@1007 588 break;
james@1007 589 case NDIS_OFFLOAD_SET_NO_CHANGE:
james@1007 590 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
james@1007 591 break;
james@1007 592 }
james@1007 593 FUNCTION_MSG(" IPv4.HeaderSize = %d\n", noe->IPv4.HeaderSize);
james@1007 594 FUNCTION_MSG(" IPv6.EncapsulationType = %d\n", noe->IPv6.EncapsulationType);
james@1007 595 switch(noe->IPv6.Enabled) {
james@1007 596 case NDIS_OFFLOAD_SET_ON:
james@1007 597 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_ON (this is an error)\n");
james@1007 598 break;
james@1007 599 case NDIS_OFFLOAD_SET_OFF:
james@1007 600 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_OFF\n");
james@1007 601 break;
james@1007 602 case NDIS_OFFLOAD_SET_NO_CHANGE:
james@1007 603 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
james@1007 604 break;
james@1007 605 }
james@1011 606 *bytes_read = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
james@1007 607 FUNCTION_MSG(" IPv6.HeaderSize = %d\n", noe->IPv6.HeaderSize);
james@1007 608 return NDIS_STATUS_SUCCESS;
james@1007 609 }
james@1007 610 #endif
james@1007 611
james@1007 612 NDIS_STATUS
james@1007 613 XenNet_SetOID_PNP_SET_POWER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 614 UNREFERENCED_PARAMETER(context);
james@1007 615 UNREFERENCED_PARAMETER(information_buffer);
james@1007 616 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 617 UNREFERENCED_PARAMETER(bytes_read);
james@1007 618 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 619 return STATUS_NOT_SUPPORTED;
james@1007 620 }
james@1007 621
james@1007 622 NDIS_STATUS
james@1007 623 XenNet_SetOID_GEN_NETWORK_LAYER_ADDRESSES(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 624 PNETWORK_ADDRESS_LIST nal = information_buffer;
james@1007 625 PNETWORK_ADDRESS na;
james@1007 626 PNETWORK_ADDRESS_IP ip;
james@1007 627 int i;
james@1007 628
james@1007 629 UNREFERENCED_PARAMETER(context);
james@1007 630 UNREFERENCED_PARAMETER(bytes_read);
james@1007 631 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 632 FUNCTION_MSG("AddressType = %d\n", nal->AddressType);
james@1007 633 FUNCTION_MSG("AddressCount = %d\n", nal->AddressCount);
james@1007 634 if (nal->AddressCount == 0) {
james@1007 635 // remove addresses of AddressType type
james@1007 636 } else {
james@1007 637 na = nal->Address;
james@1007 638 for (i = 0; i < nal->AddressCount; i++) {
james@1007 639 if ((ULONG_PTR)na - (ULONG_PTR)nal + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength > information_buffer_length) {
james@1007 640 FUNCTION_MSG("Out of bounds\n");
james@1007 641 return NDIS_STATUS_INVALID_DATA;
james@1007 642 }
james@1007 643 switch(na->AddressType) {
james@1007 644 case NDIS_PROTOCOL_ID_TCP_IP:
james@1007 645 FUNCTION_MSG("Address[%d].Type = NDIS_PROTOCOL_ID_TCP_IP\n", i);
james@1007 646 FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength);
james@1007 647 if (na->AddressLength != NETWORK_ADDRESS_LENGTH_IP) {
james@1007 648 FUNCTION_MSG("Length is invalid\n");
james@1007 649 break;
james@1007 650 }
james@1007 651 ip = (PNETWORK_ADDRESS_IP)na->Address;
james@1007 652 FUNCTION_MSG("Address[%d].in_addr = %d.%d.%d.%d\n", i, ip->in_addr & 0xff, (ip->in_addr >> 8) & 0xff, (ip->in_addr >> 16) & 0xff, (ip->in_addr >> 24) & 0xff);
james@1007 653 break;
james@1007 654 default:
james@1007 655 FUNCTION_MSG("Address[%d].Type = %d\n", i, na->AddressType);
james@1007 656 FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength);
james@1007 657 break;
james@1007 658 }
james@1007 659 na = (PNETWORK_ADDRESS)((PUCHAR)na + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength);
james@1007 660 }
james@1007 661 }
james@1007 662
james@1007 663 return NDIS_STATUS_SUCCESS;
james@1007 664 }
james@1007 665
james@1007 666 NDIS_STATUS
james@1007 667 XenNet_SetOID_GEN_MACHINE_NAME(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
james@1007 668 UNICODE_STRING name;
james@1007 669 UNREFERENCED_PARAMETER(context);
james@1007 670 UNREFERENCED_PARAMETER(bytes_read);
james@1007 671 UNREFERENCED_PARAMETER(bytes_needed);
james@1007 672
james@1007 673 name.Length = (USHORT)information_buffer_length;
james@1007 674 name.MaximumLength = (USHORT)information_buffer_length;
james@1007 675 name.Buffer = information_buffer;
james@1007 676 FUNCTION_MSG("name = %wZ\n", &name);
james@1007 677 return NDIS_STATUS_SUCCESS;
james@1007 678 }
james@1007 679
james@1007 680 struct xennet_oids_t xennet_oids[] = {
james@1007 681 DEF_OID_QUERY_ULONG(OID_GEN_HARDWARE_STATUS),
james@1007 682
james@1007 683 DEF_OID_QUERY_ULONG(OID_GEN_TRANSMIT_BUFFER_SPACE),
james@1007 684 DEF_OID_QUERY_ULONG(OID_GEN_RECEIVE_BUFFER_SPACE),
james@1007 685 DEF_OID_QUERY_ULONG(OID_GEN_TRANSMIT_BLOCK_SIZE),
james@1007 686 DEF_OID_QUERY_ULONG(OID_GEN_RECEIVE_BLOCK_SIZE),
james@1007 687
james@1007 688 DEF_OID_QUERY_ULONG(OID_GEN_VENDOR_ID),
james@1007 689 DEF_OID_QUERY(OID_GEN_VENDOR_DESCRIPTION, sizeof(XN_VENDOR_DESC)),
james@1007 690 DEF_OID_QUERY_ULONG(OID_GEN_VENDOR_DRIVER_VERSION),
james@1007 691
james@1007 692 DEF_OID_QUERYSET_ULONG(OID_GEN_CURRENT_PACKET_FILTER),
james@1007 693 DEF_OID_QUERYSET_ULONG(OID_GEN_CURRENT_LOOKAHEAD),
james@1007 694 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_TOTAL_SIZE),
james@1007 695
james@1007 696 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_SEND_PACKETS),
james@1007 697 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_SUPPORTED),
james@1007 698 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_IN_USE),
james@1007 699 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_LOOKAHEAD),
james@1007 700
james@1007 701 /* general optional */
james@1007 702 DEF_OID_SET(OID_GEN_NETWORK_LAYER_ADDRESSES, FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)),
james@1007 703 DEF_OID_SET(OID_GEN_MACHINE_NAME, 0),
james@1007 704
james@1007 705 /* power */
james@1007 706 DEF_OID_SET_ULONG(OID_PNP_SET_POWER),
james@1007 707
james@1007 708 /* stats */
james@1007 709 DEF_OID_QUERY_STAT(OID_GEN_XMIT_OK),
james@1007 710 DEF_OID_QUERY_STAT(OID_GEN_RCV_OK),
james@1007 711 DEF_OID_QUERY_STAT(OID_GEN_XMIT_ERROR),
james@1007 712 DEF_OID_QUERY_STAT(OID_GEN_RCV_ERROR),
james@1007 713 DEF_OID_QUERY_STAT(OID_GEN_RCV_NO_BUFFER),
james@1007 714 DEF_OID_QUERY_STAT(OID_802_3_RCV_ERROR_ALIGNMENT),
james@1007 715 DEF_OID_QUERY_STAT(OID_802_3_XMIT_ONE_COLLISION),
james@1007 716 DEF_OID_QUERY_STAT(OID_802_3_XMIT_MORE_COLLISIONS),
james@1007 717 DEF_OID_NONE(OID_IP4_OFFLOAD_STATS),
james@1007 718 DEF_OID_NONE(OID_IP6_OFFLOAD_STATS),
james@1007 719
james@1007 720 /* media-specific */
james@1007 721 DEF_OID_QUERY(OID_802_3_PERMANENT_ADDRESS, 6),
james@1007 722 DEF_OID_QUERY(OID_802_3_CURRENT_ADDRESS, 6),
james@1007 723 DEF_OID_QUERYSET(OID_802_3_MULTICAST_LIST, 0),
james@1007 724 DEF_OID_QUERY_ULONG(OID_802_3_MAXIMUM_LIST_SIZE),
james@1007 725
james@1007 726 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 727 DEF_OID_QUERY(OID_GEN_SUPPORTED_LIST, 0),
james@1007 728 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_FRAME_SIZE),
james@1007 729 DEF_OID_QUERY_ULONG(OID_GEN_LINK_SPEED),
james@1007 730 DEF_OID_QUERY(OID_GEN_DRIVER_VERSION, sizeof(USHORT)),
james@1007 731 DEF_OID_QUERY_ULONG(OID_GEN_MAC_OPTIONS),
james@1007 732 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_CONNECT_STATUS),
james@1007 733 DEF_OID_QUERYSET(OID_TCP_TASK_OFFLOAD, 0),
james@1007 734 DEF_OID_QUERY(OID_PNP_CAPABILITIES, sizeof(NDIS_PNP_CAPABILITIES)),
james@1007 735 DEF_OID_QUERY(OID_PNP_QUERY_POWER, 0),
james@1007 736 DEF_OID_SET(OID_GEN_PROTOCOL_OPTIONS, 0),
james@1007 737 #else
james@1007 738 DEF_OID_SET(OID_GEN_LINK_PARAMETERS, sizeof(NDIS_LINK_PARAMETERS)),
james@1007 739 DEF_OID_QUERYSET(OID_GEN_INTERRUPT_MODERATION, sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS)),
james@1007 740 DEF_OID_SET(OID_OFFLOAD_ENCAPSULATION, sizeof(NDIS_OFFLOAD_ENCAPSULATION)),
james@1007 741 DEF_OID_QUERY(OID_GEN_STATISTICS, sizeof(NDIS_STATISTICS_INFO)),
james@1007 742 #endif
james@1007 743 {0, "", 0, NULL, NULL}
james@1007 744 };
james@1007 745
james@1007 746 //static NDIS_OID supported_oids[ARRAY_SIZE(xennet_oids)];
james@1007 747 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 748 NDIS_STATUS
james@1007 749 XenNet_SetInformation(
james@1007 750 NDIS_HANDLE adapter_context,
james@1007 751 NDIS_OID oid,
james@1007 752 PVOID information_buffer,
james@1007 753 ULONG information_buffer_length,
james@1007 754 PULONG bytes_read,
james@1007 755 PULONG bytes_needed) {
james@1007 756 NTSTATUS status;
james@1007 757 int i;
james@1007 758
james@1007 759 FUNCTION_ENTER();
james@1007 760 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
james@1007 761
james@1007 762 if (!xennet_oids[i].oid) {
james@1007 763 FUNCTION_MSG("Unsupported OID %08x\n", oid);
james@1007 764 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 765 }
james@1007 766 if (information_buffer_length < xennet_oids[i].min_length) {
james@1007 767 FUNCTION_MSG("%s Set InformationBufferLength %d < min_length %d\n", xennet_oids[i].oid_name, information_buffer_length, xennet_oids[i].min_length);
james@1007 768 *bytes_needed = xennet_oids[i].min_length;
james@1007 769 return NDIS_STATUS_BUFFER_TOO_SHORT;
james@1007 770 }
james@1007 771 if (!xennet_oids[i].set_routine) {
james@1007 772 FUNCTION_MSG("%s Set not supported\n", xennet_oids[i].oid_name);
james@1007 773 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 774 }
james@1007 775 FUNCTION_MSG("%s\n", xennet_oids[i].oid_name);
james@1007 776 status = xennet_oids[i].set_routine(adapter_context, information_buffer, information_buffer_length, bytes_read, bytes_needed);
james@1007 777 FUNCTION_EXIT();
james@1007 778 return status;
james@1007 779 }
james@1007 780
james@1007 781 NDIS_STATUS
james@1007 782 XenNet_QueryInformation(
james@1007 783 IN NDIS_HANDLE adapter_context,
james@1007 784 IN NDIS_OID oid,
james@1007 785 IN PVOID information_buffer,
james@1007 786 IN ULONG information_buffer_length,
james@1007 787 OUT PULONG bytes_written,
james@1007 788 OUT PULONG bytes_needed) {
james@1007 789 NTSTATUS status;
james@1007 790 int i;
james@1007 791
james@1007 792 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
james@1007 793
james@1007 794 if (!xennet_oids[i].oid) {
james@1007 795 FUNCTION_MSG("Unsupported OID %08x\n", oid);
james@1007 796 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 797 }
james@1007 798 if (information_buffer_length < xennet_oids[i].min_length) {
james@1007 799 FUNCTION_MSG("%s Query InformationBufferLength %d < min_length %d\n", xennet_oids[i].oid_name, information_buffer_length, xennet_oids[i].min_length);
james@1007 800 *bytes_needed = xennet_oids[i].min_length;
james@1007 801 return NDIS_STATUS_BUFFER_TOO_SHORT;
james@1007 802 }
james@1007 803 if (!xennet_oids[i].query_routine) {
james@1007 804 FUNCTION_MSG("%s Query not supported\n", xennet_oids[i].oid_name);
james@1007 805 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 806 }
james@1007 807 //FUNCTION_MSG("%s\n", xennet_oids[i].oid_name);
james@1007 808 status = xennet_oids[i].query_routine(adapter_context, information_buffer, information_buffer_length, bytes_written, bytes_needed);
james@1007 809 return status;
james@1007 810 }
james@1007 811
james@1007 812 #else
james@1007 813 NDIS_STATUS
james@1007 814 XenNet_OidRequest(NDIS_HANDLE adapter_context, PNDIS_OID_REQUEST oid_request)
james@1007 815 {
james@1007 816 NTSTATUS status;
james@1007 817 int i;
james@1007 818 NDIS_OID oid;
james@1007 819
james@1007 820 //FUNCTION_ENTER();
james@1007 821 switch(oid_request->RequestType)
james@1007 822 {
james@1007 823 case NdisRequestQueryInformation:
james@1007 824 //FUNCTION_MSG("RequestType = NdisRequestQueryInformation\n");
james@1007 825 oid = oid_request->DATA.QUERY_INFORMATION.Oid;
james@1007 826 break;
james@1007 827 case NdisRequestSetInformation:
james@1007 828 //FUNCTION_MSG("RequestType = NdisRequestSetInformation\n");
james@1007 829 oid = oid_request->DATA.SET_INFORMATION.Oid;
james@1007 830 break;
james@1007 831 case NdisRequestQueryStatistics:
james@1007 832 //FUNCTION_MSG("RequestType = NdisRequestQueryStatistics\n");
james@1007 833 oid = oid_request->DATA.QUERY_INFORMATION.Oid;
james@1007 834 break;
james@1007 835 default:
james@1007 836 //FUNCTION_MSG("RequestType = NdisRequestQuery%d\n", oid_request->RequestType);
james@1007 837 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 838 }
james@1007 839 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
james@1007 840
james@1007 841 if (!xennet_oids[i].oid) {
james@1007 842 FUNCTION_MSG("Unsupported OID %08x\n", oid);
james@1007 843 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 844 }
james@1007 845 //FUNCTION_MSG("Oid = %s\n", xennet_oids[i].oid_name);
james@1007 846 switch(oid_request->RequestType)
james@1007 847 {
james@1007 848 case NdisRequestQueryInformation:
james@1007 849 case NdisRequestQueryStatistics:
james@1007 850 if (oid_request->DATA.QUERY_INFORMATION.InformationBufferLength < xennet_oids[i].min_length) {
james@1007 851 FUNCTION_MSG("InformationBufferLength %d < min_length %d\n", oid_request->DATA.QUERY_INFORMATION.InformationBufferLength, xennet_oids[i].min_length);
james@1007 852 oid_request->DATA.QUERY_INFORMATION.BytesNeeded = xennet_oids[i].min_length;
james@1007 853 return NDIS_STATUS_BUFFER_TOO_SHORT;
james@1007 854 }
james@1011 855 if (!xennet_oids[i].query_routine) {
james@1007 856 //FUNCTION_MSG("Operation not supported\n");
james@1007 857 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 858 }
james@1011 859 status = xennet_oids[i].query_routine(adapter_context, oid_request->DATA.QUERY_INFORMATION.InformationBuffer, oid_request->DATA.QUERY_INFORMATION.InformationBufferLength, (PULONG)&oid_request->DATA.QUERY_INFORMATION.BytesWritten, (PULONG)&oid_request->DATA.QUERY_INFORMATION.BytesNeeded);
james@1007 860 break;
james@1007 861 case NdisRequestSetInformation:
james@1007 862 if (oid_request->DATA.SET_INFORMATION.InformationBufferLength < xennet_oids[i].min_length) {
james@1007 863 FUNCTION_MSG("InformationBufferLength %d < min_length %d\n", oid_request->DATA.SET_INFORMATION.InformationBufferLength, xennet_oids[i].min_length);
james@1007 864 oid_request->DATA.SET_INFORMATION.BytesNeeded = xennet_oids[i].min_length;
james@1007 865 return NDIS_STATUS_BUFFER_TOO_SHORT;
james@1007 866 }
james@1011 867 if (!xennet_oids[i].set_routine) {
james@1007 868 //FUNCTION_MSG("Operation not supported\n");
james@1007 869 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 870 }
james@1011 871 status = xennet_oids[i].set_routine(adapter_context, oid_request->DATA.SET_INFORMATION.InformationBuffer, oid_request->DATA.SET_INFORMATION.InformationBufferLength, (PULONG)&oid_request->DATA.SET_INFORMATION.BytesRead, (PULONG)&oid_request->DATA.SET_INFORMATION.BytesNeeded);
james@1007 872 break;
james@1011 873 default:
james@1007 874 return NDIS_STATUS_NOT_SUPPORTED;
james@1007 875 }
james@1007 876 //FUNCTION_EXIT();
james@1007 877 return status;
james@1007 878 }
james@1007 879
james@1007 880 VOID
james@1007 881 XenNet_CancelOidRequest(NDIS_HANDLE adapter_context, PVOID request_id)
james@1007 882 {
james@1007 883 UNREFERENCED_PARAMETER(adapter_context);
james@1007 884 UNREFERENCED_PARAMETER(request_id);
james@1007 885 FUNCTION_ENTER();
james@1007 886 FUNCTION_EXIT();
james@1007 887 }
james@1007 888 #endif