win-pvdrivers

annotate xenvbd_common/common_xen.h @ 1058:8b6500e0ebfc

Rename to fix case issue on shutdownmon directory
author James Harper <james.harper@bendigoit.com.au>
date Mon Sep 30 19:46:16 2013 +1000 (2013-09-30)
parents 306c10cdcba1
children e86ea7c3d8a4
rev   line source
james@1005 1 /*
james@1005 2 PV Drivers for Windows Xen HVM Domains
james@1005 3 Copyright (C) 2013 James Harper
james@1005 4
james@1005 5 This program is free software; you can redistribute it and/or
james@1005 6 modify it under the terms of the GNU General Public License
james@1005 7 as published by the Free Software Foundation; either version 2
james@1005 8 of the License, or (at your option) any later version.
james@1005 9
james@1005 10 This program is distributed in the hope that it will be useful,
james@1005 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@1005 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@1005 13 GNU General Public License for more details.
james@1005 14
james@1005 15 You should have received a copy of the GNU General Public License
james@1005 16 along with this program; if not, write to the Free Software
james@1005 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@1005 18 */
james@1005 19
james@1005 20 static NTSTATUS
james@1005 21 XenVbd_Connect(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend) {
james@1005 22 BOOLEAN qemu_hide_filter = FALSE;
james@1005 23 ULONG qemu_hide_flags_value = 0;
james@1005 24 PCHAR device_type;
james@1005 25 //BOOLEAN active = FALSE;
james@1005 26 NTSTATUS status;
james@1005 27 PCHAR mode;
james@1025 28 PCHAR uuid;
james@1005 29 PFN_NUMBER pfn;
james@1005 30
james@1005 31 FUNCTION_ENTER();
james@1005 32
james@1005 33 if (xvdd->device_state != DEVICE_STATE_DISCONNECTED) {
james@1005 34 FUNCTION_MSG("state not DEVICE_STATE_DISCONNECTED, is %d instead\n", xvdd->device_state);
james@1005 35 FUNCTION_EXIT();
james@1005 36 return STATUS_SUCCESS;
james@1005 37 }
james@1005 38 if (!suspend) {
james@1025 39 xvdd->backend_state = XenbusStateUnknown;
james@1005 40 if ((xvdd->handle = XnOpenDevice(xvdd->pdo, XenVbd_DeviceCallback, xvdd)) == NULL) {
james@1005 41 FUNCTION_MSG("Failed to open\n");
james@1005 42 return STATUS_UNSUCCESSFUL;
james@1005 43 }
james@1005 44 }
james@1005 45 xvdd->sring = (blkif_sring_t *)ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENVBD_POOL_TAG);
james@1005 46 if (!xvdd->sring) {
james@1025 47 FUNCTION_MSG("Failed to allocate sring\n");
james@1005 48 return STATUS_UNSUCCESSFUL;
james@1005 49 }
james@1021 50 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(xvdd->sring).QuadPart >> PAGE_SHIFT);
james@1005 51 xvdd->sring_gref = XnGrantAccess(xvdd->handle, (ULONG)pfn, FALSE, INVALID_GRANT_REF, xvdd->grant_tag);
james@1005 52 SHARED_RING_INIT(xvdd->sring);
james@1005 53 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
james@1005 54
james@1005 55 while (xvdd->backend_state != XenbusStateInitialising &&
james@1005 56 xvdd->backend_state != XenbusStateInitWait &&
james@1005 57 xvdd->backend_state != XenbusStateInitialised) {
james@1005 58 FUNCTION_MSG("waiting for XenbusStateInitXxx, backend_state = %d\n", xvdd->backend_state);
james@1005 59 KeWaitForSingleObject(&xvdd->backend_event, Executive, KernelMode, FALSE, NULL);
james@1005 60 }
james@1005 61 XnGetValue(xvdd->handle, XN_VALUE_TYPE_QEMU_HIDE_FLAGS, &qemu_hide_flags_value);
james@1005 62 XnGetValue(xvdd->handle, XN_VALUE_TYPE_QEMU_FILTER, &qemu_hide_filter);
james@1005 63 status = XnReadString(xvdd->handle, XN_BASE_FRONTEND, "device-type", &device_type);
james@1005 64 if (strcmp(device_type, "disk") == 0) {
james@1005 65 FUNCTION_MSG("device-type = Disk\n");
james@1005 66 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
james@1005 67 } else if (strcmp(device_type, "cdrom") == 0) {
james@1005 68 FUNCTION_MSG("device-type = CDROM\n");
james@1005 69 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
james@1005 70 } else {
james@1005 71 FUNCTION_MSG("device-type = %s (This probably won't work!)\n", device_type);
james@1005 72 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
james@1005 73 }
james@1005 74 XnFreeMem(xvdd->handle, device_type);
james@1005 75 if (!(((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) && xvdd->device_type != XENVBD_DEVICETYPE_CDROM) || qemu_hide_filter)) {
james@1005 76 /* we never set backend state active if we are inactive */
james@1005 77 FUNCTION_MSG("Inactive\n");
james@1018 78 XnCloseDevice(xvdd->handle);
james@1005 79 xvdd->device_state = DEVICE_STATE_INACTIVE;
james@1005 80 return STATUS_SUCCESS;
james@1005 81 }
james@1005 82 status = XnBindEvent(xvdd->handle, &xvdd->event_channel, XenVbd_HandleEventDIRQL, xvdd);
james@1005 83 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "event-channel", xvdd->event_channel);
james@1005 84 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "ring-ref", xvdd->sring_gref);
james@1005 85 status = XnWriteString(xvdd->handle, XN_BASE_FRONTEND, "protocol", ABI_PROTOCOL);
james@1005 86 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateInitialised);
james@1005 87
james@1005 88 while (xvdd->backend_state != XenbusStateConnected) {
james@1005 89 FUNCTION_MSG("waiting for XenbusStateConnected, backend_state = %d\n", xvdd->backend_state);
james@1005 90 KeWaitForSingleObject(&xvdd->backend_event, Executive, KernelMode, FALSE, NULL);
james@1005 91 }
james@1005 92
james@1005 93 // TODO: some of this stuff should be read on first connect only, then only verified on resume
james@1032 94 xvdd->new_total_sectors = (ULONGLONG)-1L;
james@1005 95 status = XnReadInt64(xvdd->handle, XN_BASE_BACKEND, "sectors", &xvdd->total_sectors);
james@1005 96 status = XnReadInt32(xvdd->handle, XN_BASE_BACKEND, "sector-size", &xvdd->hw_bytes_per_sector);
james@1005 97 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM) {
james@1005 98 /* CD/DVD drives must have bytes_per_sector = 2048. */
james@1005 99 xvdd->bytes_per_sector = 2048;
james@1005 100 xvdd->hw_bytes_per_sector = 2048;
james@1005 101 } else {
james@1005 102 xvdd->bytes_per_sector = 512;
james@1005 103 }
james@1005 104 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
james@1005 105 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
james@1005 106 status = XnReadInt32(xvdd->handle, XN_BASE_BACKEND, "feature-barrier", &xvdd->feature_barrier);
james@1005 107 status = XnReadInt32(xvdd->handle, XN_BASE_BACKEND, "feature-discard", &xvdd->feature_discard);
james@1005 108 status = XnReadInt32(xvdd->handle, XN_BASE_BACKEND, "feature-flush-cache", &xvdd->feature_flush_cache);
james@1005 109 status = XnReadString(xvdd->handle, XN_BASE_BACKEND, "mode", &mode);
james@1005 110 if (strncmp(mode, "r", 1) == 0) {
james@1005 111 FUNCTION_MSG("mode = r\n");
james@1005 112 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
james@1005 113 } else if (strncmp(mode, "w", 1) == 0) {
james@1005 114 FUNCTION_MSG("mode = w\n");
james@1005 115 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
james@1005 116 } else {
james@1005 117 FUNCTION_MSG("mode = unknown\n");
james@1005 118 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
james@1005 119 }
james@1005 120 XnFreeMem(xvdd->handle, mode);
james@1005 121
james@1005 122 // read device-type
james@1005 123 status = XnReadString(xvdd->handle, XN_BASE_FRONTEND, "device-type", &device_type);
james@1005 124 if (strcmp(device_type, "disk") == 0) {
james@1005 125 FUNCTION_MSG("device-type = Disk\n");
james@1005 126 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
james@1005 127 } else if (strcmp(device_type, "cdrom") == 0) {
james@1005 128 FUNCTION_MSG("device-type = CDROM\n");
james@1005 129 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
james@1005 130 } else {
james@1005 131 FUNCTION_MSG("device-type = %s (This probably won't work!)\n", device_type);
james@1005 132 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
james@1005 133 }
james@1025 134
james@1025 135 status = XnReadString(xvdd->handle, XN_BASE_FRONTEND, "device-type", &uuid);
james@1025 136 if (status == STATUS_SUCCESS) {
james@1025 137 RtlStringCbCopyA(xvdd->serial_number, ARRAY_SIZE(xvdd->serial_number), uuid);
james@1025 138 XnFreeMem(xvdd->handle, uuid);
james@1025 139 } else {
james@1025 140 RtlStringCbCopyA(xvdd->serial_number, ARRAY_SIZE(xvdd->serial_number), " ");
james@1025 141 }
james@1025 142
james@1005 143 XnFreeMem(xvdd->handle, device_type);
james@1005 144 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateConnected);
james@1005 145
james@1005 146 if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
james@1005 147 || xvdd->sring == NULL
james@1005 148 || xvdd->event_channel == 0
james@1005 149 || xvdd->total_sectors == 0
james@1005 150 || xvdd->hw_bytes_per_sector == 0) {
james@1005 151 FUNCTION_MSG("Missing settings\n");
james@1005 152 // TODO: fail how?
james@1005 153 }
james@1005 154
james@1005 155 xvdd->device_state = DEVICE_STATE_ACTIVE;
james@1005 156 XenVbd_StartRing(xvdd, suspend);
james@1005 157 FUNCTION_EXIT();
james@1005 158 return STATUS_SUCCESS;
james@1005 159 }
james@1005 160
james@1005 161 static NTSTATUS
james@1005 162 XenVbd_Disconnect(PVOID DeviceExtension, BOOLEAN suspend) {
james@1005 163 NTSTATUS status;
james@1005 164 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@1005 165
james@1018 166 if (xvdd->device_state == DEVICE_STATE_INACTIVE) {
james@1018 167 /* state stays INACTIVE */
james@1018 168 return STATUS_SUCCESS;
james@1018 169 }
james@1018 170
james@1005 171 if (xvdd->device_state != DEVICE_STATE_ACTIVE) {
james@1005 172 FUNCTION_MSG("state not DEVICE_STATE_ACTIVE, is %d instead\n", xvdd->device_state);
james@1005 173 FUNCTION_EXIT();
james@1005 174 return STATUS_SUCCESS;
james@1005 175 }
james@1005 176
james@1005 177 /* StopRing must set XenbusStateClosing when ring is paused */
james@1005 178 XenVbd_StopRing(xvdd, suspend);
james@1005 179
james@1005 180 while (xvdd->backend_state != XenbusStateClosing) {
james@1005 181 FUNCTION_MSG("waiting for XenbusStateClosing, backend_state = %d\n", xvdd->backend_state);
james@1005 182 KeWaitForSingleObject(&xvdd->backend_event, Executive, KernelMode, FALSE, NULL);
james@1005 183 }
james@1005 184 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosed);
james@1005 185 while (xvdd->backend_state != XenbusStateClosed) {
james@1005 186 FUNCTION_MSG("waiting for XenbusStateClosed, backend_state = %d\n", xvdd->backend_state);
james@1005 187 KeWaitForSingleObject(&xvdd->backend_event, Executive, KernelMode, FALSE, NULL);
james@1005 188 }
james@1005 189 XnUnbindEvent(xvdd->handle, xvdd->event_channel);
james@1005 190 XnEndAccess(xvdd->handle, xvdd->sring_gref, FALSE, xvdd->grant_tag);
james@1005 191 ExFreePoolWithTag(xvdd->sring, XENVBD_POOL_TAG);
james@1005 192
james@1005 193 if (!suspend) {
james@1005 194 XnCloseDevice(xvdd->handle);
james@1005 195 }
james@1005 196 xvdd->device_state = DEVICE_STATE_DISCONNECTED;
james@1005 197 return STATUS_SUCCESS;
james@1005 198 }
james@1005 199
james@1032 200
james@1005 201 static VOID
james@1005 202 XenVbd_DeviceCallback(PVOID context, ULONG callback_type, PVOID value) {
james@1005 203 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)context;
james@1005 204 ULONG state;
james@1005 205
james@1005 206 FUNCTION_ENTER();
james@1005 207
james@1005 208 switch (callback_type) {
james@1005 209 case XN_DEVICE_CALLBACK_BACKEND_STATE:
james@1005 210 state = (ULONG)(ULONG_PTR)value;
james@1005 211 if (state == xvdd->backend_state) {
james@1005 212 FUNCTION_MSG("same state %d\n", state);
james@1032 213 /* could be rewriting same state because of size change */
james@1032 214 if (xvdd->backend_state == XenbusStateConnected) {
james@1032 215 /* just set the new value - it will be noticed sooner or later */
james@1032 216 XnReadInt64(xvdd->handle, XN_BASE_BACKEND, "sectors", &xvdd->new_total_sectors);
james@1032 217 }
james@1005 218 FUNCTION_EXIT();
james@1005 219 }
james@1005 220 FUNCTION_MSG("XenBusState = %d -> %d\n", xvdd->backend_state, state);
james@1005 221 xvdd->backend_state = state;
james@1005 222 KeMemoryBarrier();
james@1005 223 KeSetEvent(&xvdd->backend_event, 0, FALSE);
james@1005 224 break;
james@1005 225 case XN_DEVICE_CALLBACK_SUSPEND:
james@1005 226 FUNCTION_MSG("XN_DEVICE_CALLBACK_SUSPEND\n");
james@1005 227 XenVbd_Disconnect(xvdd, TRUE);
james@1005 228 break;
james@1005 229 case XN_DEVICE_CALLBACK_RESUME:
james@1005 230 FUNCTION_MSG("XN_DEVICE_CALLBACK_RESUME\n");
james@1005 231 XenVbd_Connect(xvdd, TRUE);
james@1005 232 break;
james@1005 233 }
james@1005 234 FUNCTION_EXIT();
james@1005 235 }