win-pvdrivers

changeset 0:435e5753300f

Initial upload of files
author James Harper <james.harper@bendigoit.com.au>
date Sat Nov 10 14:40:56 2007 +1100 (2007-11-10)
parents
children b16f2f5eb611
files common/include/evtchn_public.h common/include/gnttbl_public.h common/include/hypercall.h common/include/xen_public.h common/include/xen_windows.h common/include/xenbus_public.h xenpci/evtchn.c xenpci/gnttbl.c xenpci/makefile xenpci/memory.c xenpci/target/xenpci.inf xenpci/xenbus.c xenpci/xenbus.h xenpci/xenpci.c xenpci/xenpci.h xenvbd/makefile xenvbd/sources xenvbd/target/xenvbd.inf xenvbd/xenvbd.c xenvbd/xenvbd.h
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/common/include/evtchn_public.h	Sat Nov 10 14:40:56 2007 +1100
     1.3 @@ -0,0 +1,51 @@
     1.4 +/*
     1.5 +PV Drivers for Windows Xen HVM Domains
     1.6 +Copyright (C) 2007 James Harper
     1.7 +
     1.8 +This program is free software; you can redistribute it and/or
     1.9 +modify it under the terms of the GNU General Public License
    1.10 +as published by the Free Software Foundation; either version 2
    1.11 +of the License, or (at your option) any later version.
    1.12 +
    1.13 +This program is distributed in the hope that it will be useful,
    1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 +GNU General Public License for more details.
    1.17 +
    1.18 +You should have received a copy of the GNU General Public License
    1.19 +along with this program; if not, write to the Free Software
    1.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    1.21 +*/
    1.22 +
    1.23 +DEFINE_GUID( GUID_XEN_IFACE_EVTCHN, 0xD2D20756, 0xDE69, 0x4447, 0x8A, 0x7D, 0x98, 0x37, 0x19, 0x7D, 0x61, 0x66);
    1.24 +//{D2D20756-DE69-4447-8A7D-9837197D6166}
    1.25 +
    1.26 +typedef evtchn_port_t
    1.27 +(*PXEN_EVTCHN_ALLOCUNBOUND)(domid_t Domain);
    1.28 +
    1.29 +typedef NTSTATUS
    1.30 +(*PXEN_EVTCHN_BIND)(evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext);
    1.31 +
    1.32 +typedef NTSTATUS
    1.33 +(*PXEN_EVTCHN_UNBIND)(evtchn_port_t Port);
    1.34 +
    1.35 +typedef NTSTATUS
    1.36 +(*PXEN_EVTCHN_MASK)(evtchn_port_t Port);
    1.37 +
    1.38 +typedef NTSTATUS
    1.39 +(*PXEN_EVTCHN_UNMASK)(evtchn_port_t Port);
    1.40 +
    1.41 +typedef NTSTATUS
    1.42 +(*PXEN_EVTCHN_NOTIFY)(evtchn_port_t Port);
    1.43 +
    1.44 +typedef struct _XENBUS_IFACE_EVTCHN {
    1.45 +  INTERFACE InterfaceHeader;
    1.46 +
    1.47 +  PXEN_EVTCHN_BIND Bind;
    1.48 +  PXEN_EVTCHN_UNBIND Unbind;
    1.49 +  PXEN_EVTCHN_MASK Mask;
    1.50 +  PXEN_EVTCHN_UNMASK Unmask;
    1.51 +  PXEN_EVTCHN_NOTIFY Notify;
    1.52 +  PXEN_EVTCHN_ALLOCUNBOUND AllocUnbound;
    1.53 +
    1.54 +} XEN_IFACE_EVTCHN, *PXEN_IFACE_EVTCHN;
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/common/include/gnttbl_public.h	Sat Nov 10 14:40:56 2007 +1100
     2.3 @@ -0,0 +1,33 @@
     2.4 +/*
     2.5 +PV Drivers for Windows Xen HVM Domains
     2.6 +Copyright (C) 2007 James Harper
     2.7 +
     2.8 +This program is free software; you can redistribute it and/or
     2.9 +modify it under the terms of the GNU General Public License
    2.10 +as published by the Free Software Foundation; either version 2
    2.11 +of the License, or (at your option) any later version.
    2.12 +
    2.13 +This program is distributed in the hope that it will be useful,
    2.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16 +GNU General Public License for more details.
    2.17 +
    2.18 +You should have received a copy of the GNU General Public License
    2.19 +along with this program; if not, write to the Free Software
    2.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    2.21 +*/
    2.22 +
    2.23 +// {6A71ACF8-0F6D-4022-BA60-19986EBEEA73}
    2.24 +DEFINE_GUID(GUID_XEN_IFACE_GNTTBL, 0x6a71acf8, 0xf6d, 0x4022, 0xba, 0x60, 0x19, 0x98, 0x6e, 0xbe, 0xea, 0x73);
    2.25 +
    2.26 +typedef grant_ref_t
    2.27 +(*PXEN_GNTTBL_GRANTACCESS)(domid_t domid, unsigned long frame, int readonly);
    2.28 +typedef BOOLEAN
    2.29 +(*PXEN_GNTTBL_ENDACCESS)(grant_ref_t ref);
    2.30 +
    2.31 +typedef struct _XEN_IFACE_GNTTBL {
    2.32 +  INTERFACE InterfaceHeader;
    2.33 +
    2.34 +  PXEN_GNTTBL_GRANTACCESS GrantAccess;
    2.35 +  PXEN_GNTTBL_ENDACCESS EndAccess;
    2.36 +} XEN_IFACE_GNTTBL, *PXEN_IFACE_GNTTBL;
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/common/include/hypercall.h	Sat Nov 10 14:40:56 2007 +1100
     3.3 @@ -0,0 +1,148 @@
     3.4 +/*
     3.5 +PV Drivers for Windows Xen HVM Domains
     3.6 +Copyright (C) 2007 James Harper
     3.7 +
     3.8 +This program is free software; you can redistribute it and/or
     3.9 +modify it under the terms of the GNU General Public License
    3.10 +as published by the Free Software Foundation; either version 2
    3.11 +of the License, or (at your option) any later version.
    3.12 +
    3.13 +This program is distributed in the hope that it will be useful,
    3.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.16 +GNU General Public License for more details.
    3.17 +
    3.18 +You should have received a copy of the GNU General Public License
    3.19 +along with this program; if not, write to the Free Software
    3.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    3.21 +*/
    3.22 +
    3.23 +#include "xenpci.h"
    3.24 +
    3.25 +char *hypercall_stubs;
    3.26 +
    3.27 +static __inline int
    3.28 +HYPERVISOR_memory_op(int cmd, void *arg)
    3.29 +{
    3.30 +  long __res;
    3.31 +  __asm {
    3.32 +    mov ebx, cmd
    3.33 +    mov ecx, arg
    3.34 +    mov eax, hypercall_stubs
    3.35 +    add eax, (__HYPERVISOR_memory_op * 32)
    3.36 +    call eax
    3.37 +    mov [__res], eax
    3.38 +  }
    3.39 +  return __res;
    3.40 +}
    3.41 +
    3.42 +static __inline int
    3.43 +HYPERVISOR_xen_version(int cmd, void *arg)
    3.44 +{
    3.45 +  long __res;
    3.46 +  __asm {
    3.47 +    mov ebx, cmd
    3.48 +    mov ecx, arg
    3.49 +    mov eax, hypercall_stubs
    3.50 +    add eax, (__HYPERVISOR_xen_version * 32)
    3.51 +    call eax
    3.52 +    mov [__res], eax
    3.53 +  }
    3.54 +  return __res;
    3.55 +}
    3.56 +
    3.57 +static __inline int
    3.58 +HYPERVISOR_grant_table_op(int cmd, void *uop, unsigned int count)
    3.59 +{
    3.60 +  long __res;
    3.61 +  __asm {
    3.62 +    mov ebx, cmd
    3.63 +    mov ecx, uop
    3.64 +    mov edx, count
    3.65 +    mov eax, hypercall_stubs
    3.66 +    add eax, (__HYPERVISOR_grant_table_op * 32)
    3.67 +    call eax
    3.68 +    mov [__res], eax
    3.69 +  }
    3.70 +  return __res;
    3.71 +}
    3.72 +
    3.73 +static __inline int
    3.74 +HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count, domid_t domid)
    3.75 +{
    3.76 +  long __res;
    3.77 +  long _domid = (long)domid;
    3.78 +  __asm {
    3.79 +    mov ebx, req
    3.80 +    mov ecx, count
    3.81 +    mov edx, success_count
    3.82 +    mov edi, _domid
    3.83 +    mov eax, hypercall_stubs
    3.84 +    add eax, (__HYPERVISOR_mmu_update * 32)
    3.85 +    call eax
    3.86 +    mov [__res], eax
    3.87 +  }
    3.88 +  return __res;
    3.89 +}
    3.90 +
    3.91 +static __inline int
    3.92 +HYPERVISOR_console_io(int cmd, int count, char *string)
    3.93 +{
    3.94 +  long __res;
    3.95 +  __asm {
    3.96 +    mov ebx, cmd
    3.97 +    mov ecx, count
    3.98 +    mov edx, string
    3.99 +    mov eax, hypercall_stubs
   3.100 +    add eax, (__HYPERVISOR_console_io * 32)
   3.101 +    call eax
   3.102 +    mov [__res], eax
   3.103 +  }
   3.104 +  return __res;
   3.105 +}
   3.106 +
   3.107 +static __inline int
   3.108 +HYPERVISOR_hvm_op(int op, struct xen_hvm_param *arg)
   3.109 +{
   3.110 +  long __res;
   3.111 +  __asm {
   3.112 +    mov ebx, op
   3.113 +    mov ecx, arg
   3.114 +    mov eax, hypercall_stubs
   3.115 +    add eax, (__HYPERVISOR_hvm_op * 32)
   3.116 +    call eax
   3.117 +    mov [__res], eax
   3.118 +  }
   3.119 +  return __res;
   3.120 +}
   3.121 +
   3.122 +static __inline int
   3.123 +HYPERVISOR_event_channel_op(int cmd, void *op)
   3.124 +{
   3.125 +  long __res;
   3.126 +  __asm {
   3.127 +    mov ebx, cmd
   3.128 +    mov ecx, op
   3.129 +    mov eax, hypercall_stubs
   3.130 +    add eax, (__HYPERVISOR_event_channel_op * 32)
   3.131 +    call eax
   3.132 +    mov [__res], eax
   3.133 +  }
   3.134 +  return __res;
   3.135 +}
   3.136 +
   3.137 +static __inline ULONGLONG
   3.138 +hvm_get_parameter(int hvm_param)
   3.139 +{
   3.140 +  struct xen_hvm_param a;
   3.141 +  int retval;
   3.142 +
   3.143 +  KdPrint((__DRIVER_NAME " --> hvm_get_parameter\n"));
   3.144 +  a.domid = DOMID_SELF;
   3.145 +  a.index = hvm_param;
   3.146 +  //a.value = via;
   3.147 +  retval = HYPERVISOR_hvm_op(HVMOP_get_param, &a);
   3.148 +  KdPrint((__DRIVER_NAME " hvm_get_parameter retval = %d\n", retval));
   3.149 +  KdPrint((__DRIVER_NAME " <-- hvm_get_parameter\n"));
   3.150 +  return a.value;
   3.151 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/common/include/xen_public.h	Sat Nov 10 14:40:56 2007 +1100
     4.3 @@ -0,0 +1,29 @@
     4.4 +#if !defined(_XEN_PUBLIC_H_)
     4.5 +#define _XEN_PUBLIC_H_
     4.6 +
     4.7 +DEFINE_GUID( GUID_XEN_IFACE_XEN, 0x5C568AC5, 0x9DDF, 0x4FA5, 0xA9, 0x4A, 0x39, 0xD6, 0x70, 0x77, 0x81, 0x9C);
     4.8 +//{5C568AC5-9DDF-4FA5-A94A-39D67077819C}
     4.9 +
    4.10 +typedef PHYSICAL_ADDRESS
    4.11 +(*PXEN_ALLOCMMIO)(ULONG Length);
    4.12 +
    4.13 +
    4.14 +typedef struct _XEN_IFACE_XEN {
    4.15 +  INTERFACE InterfaceHeader;
    4.16 +
    4.17 +  // hypervisor calls
    4.18 +  PXEN_ALLOCMMIO AllocMMIO;
    4.19 +  // allocate a page from the mmio space
    4.20 +  // release a page from the mmio space
    4.21 +
    4.22 +} XEN_IFACE_XEN, *PXEN_IFACE_XEN;
    4.23 +
    4.24 +
    4.25 +typedef struct {
    4.26 +  char BasePath[128];
    4.27 +  PXENBUS_WATCH_CALLBACK WatchHandler;
    4.28 +} XENPCI_XEN_DEVICE_DATA, *PXENPCI_XEN_DEVICE_DATA;
    4.29 +
    4.30 +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENPCI_XEN_DEVICE_DATA, GetXenDeviceData);
    4.31 +
    4.32 +#endif
    4.33 \ No newline at end of file
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/common/include/xen_windows.h	Sat Nov 10 14:40:56 2007 +1100
     5.3 @@ -0,0 +1,87 @@
     5.4 +#if !defined(_XEN_WINDOWS_H_)
     5.5 +#define _XEN_WINDOWS_H_
     5.6 +
     5.7 +#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
     5.8 +#pragma warning( disable : 4214 ) // nonstandard extension used : bit field types other than int
     5.9 +
    5.10 +#define __XEN_INTERFACE_VERSION__ 0x00030205
    5.11 +#define __i386__
    5.12 +typedef signed char int8_t;
    5.13 +typedef unsigned char uint8_t;
    5.14 +typedef SHORT int16_t;
    5.15 +typedef USHORT uint16_t;
    5.16 +typedef LONG int32_t;
    5.17 +typedef ULONG uint32_t;
    5.18 +typedef ULONGLONG uint64_t;
    5.19 +typedef unsigned long pgentry_t;
    5.20 +
    5.21 +#include <xen.h>
    5.22 +
    5.23 +#define _PAGE_PRESENT  0x001UL
    5.24 +#define _PAGE_RW       0x002UL
    5.25 +#define _PAGE_USER     0x004UL
    5.26 +#define _PAGE_PWT      0x008UL
    5.27 +#define _PAGE_PCD      0x010UL
    5.28 +#define _PAGE_ACCESSED 0x020UL
    5.29 +#define _PAGE_DIRTY    0x040UL
    5.30 +#define _PAGE_PAT      0x080UL
    5.31 +#define _PAGE_PSE      0x080UL
    5.32 +#define _PAGE_GLOBAL   0x100UL
    5.33 +
    5.34 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
    5.35 +
    5.36 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
    5.37 +
    5.38 +typedef unsigned long xenbus_transaction_t;
    5.39 +typedef uint32_t XENSTORE_RING_IDX;
    5.40 +
    5.41 +#define XBT_NIL ((xenbus_transaction_t)0)
    5.42 +
    5.43 +#define SPLITSTRING_POOL_TAG (ULONG) 'SSPT'
    5.44 +
    5.45 +static char **
    5.46 +SplitString(char *String, char Split, int MaxParts, int *Count)
    5.47 +{
    5.48 +  char **RetVal;
    5.49 +  char *first;
    5.50 +  char *last;
    5.51 +
    5.52 +  //KdPrint((__DRIVER_NAME "     a\n"));
    5.53 +
    5.54 +  *Count = 0;
    5.55 +
    5.56 +  RetVal = ExAllocatePoolWithTag(NonPagedPool, (MaxParts + 1) * sizeof(char *), SPLITSTRING_POOL_TAG);
    5.57 +  last = String;
    5.58 +  do
    5.59 +  {
    5.60 +    if (*Count == MaxParts)
    5.61 +      break;
    5.62 +    //KdPrint((__DRIVER_NAME "     b - count = %d\n", *Count));
    5.63 +    first = last;
    5.64 +    for (last = first; *last != '\0' && *last != Split; last++);
    5.65 +    RetVal[*Count] = ExAllocatePoolWithTag(NonPagedPool, last - first + 1, SPLITSTRING_POOL_TAG);
    5.66 +    //KdPrint((__DRIVER_NAME "     c - count = %d\n", *Count));
    5.67 +    strncpy(RetVal[*Count], first, last - first);
    5.68 +    RetVal[*Count][last - first] = 0;
    5.69 +    //KdPrint((__DRIVER_NAME "     d - count = %d\n", *Count));
    5.70 +    (*Count)++;
    5.71 +    //KdPrint((__DRIVER_NAME "     e - count = %d\n", *Count));
    5.72 +    if (*last == Split)
    5.73 +      last++;
    5.74 +  } while (*last != 0);
    5.75 +  //KdPrint((__DRIVER_NAME "     f - count = %d\n", *Count));
    5.76 +  RetVal[*Count] = NULL;
    5.77 +  return RetVal;
    5.78 +}
    5.79 +
    5.80 +static VOID
    5.81 +FreeSplitString(char **Bits, int Count)
    5.82 +{
    5.83 +  int i;
    5.84 +
    5.85 +  for (i = 0; i < Count; i++)
    5.86 +    ExFreePoolWithTag(Bits[i], SPLITSTRING_POOL_TAG);
    5.87 +  ExFreePoolWithTag(Bits, SPLITSTRING_POOL_TAG);
    5.88 +}
    5.89 +
    5.90 +#endif
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/common/include/xenbus_public.h	Sat Nov 10 14:40:56 2007 +1100
     6.3 @@ -0,0 +1,54 @@
     6.4 +/*
     6.5 +PV Drivers for Windows Xen HVM Domains
     6.6 +Copyright (C) 2007 James Harper
     6.7 +
     6.8 +This program is free software; you can redistribute it and/or
     6.9 +modify it under the terms of the GNU General Public License
    6.10 +as published by the Free Software Foundation; either version 2
    6.11 +of the License, or (at your option) any later version.
    6.12 +
    6.13 +This program is distributed in the hope that it will be useful,
    6.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.16 +GNU General Public License for more details.
    6.17 +
    6.18 +You should have received a copy of the GNU General Public License
    6.19 +along with this program; if not, write to the Free Software
    6.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    6.21 +*/
    6.22 +
    6.23 +DEFINE_GUID( GUID_XEN_IFACE_XENBUS, 0x9CA4D816, 0x0E5E, 0x4f9a, 0x8F, 0x59, 0x94, 0x4C, 0xED, 0x82, 0x78, 0x11);
    6.24 +//{9CA4D816-0E5E-4f9a-8F59-944CED827811}
    6.25 +
    6.26 +typedef VOID
    6.27 +(*PXENBUS_WATCH_CALLBACK)(char *Path, PVOID ServiceContext);
    6.28 +
    6.29 +typedef char *
    6.30 +(*PXEN_XENBUS_READ)(xenbus_transaction_t xbt, const char *path, char **value);
    6.31 +typedef char *
    6.32 +(*PXEN_XENBUS_WRITE)(xenbus_transaction_t xbt, const char *path, const char *value);
    6.33 +typedef char *
    6.34 +(*PXEN_XENBUS_PRINTF)(xenbus_transaction_t xbt, const char *path, const char *fmt, ...);
    6.35 +typedef char *
    6.36 +(*PXEN_XENBUS_STARTTRANSACTION)(xenbus_transaction_t *xbt);
    6.37 +typedef char *
    6.38 +(*PXEN_XENBUS_ENDTRANSACTION)(xenbus_transaction_t t, int abort, int *retry);
    6.39 +typedef char *
    6.40 +(*PXEN_XENBUS_LIST)(xenbus_transaction_t xbt, const char *prefix, char ***contents);
    6.41 +typedef char *
    6.42 +(*PXEN_XENBUS_ADDWATCH)(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext);
    6.43 +typedef char *
    6.44 +(*PXEN_XENBUS_REMWATCH)(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext);
    6.45 +
    6.46 +typedef struct _XEN_IFACE_XENBUS {
    6.47 +  INTERFACE InterfaceHeader;
    6.48 +
    6.49 +  PXEN_XENBUS_READ Read;
    6.50 +  PXEN_XENBUS_WRITE Write;
    6.51 +  PXEN_XENBUS_PRINTF Printf;
    6.52 +  PXEN_XENBUS_STARTTRANSACTION StartTransaction;
    6.53 +  PXEN_XENBUS_ENDTRANSACTION EndTransaction;
    6.54 +  PXEN_XENBUS_LIST List;
    6.55 +  PXEN_XENBUS_ADDWATCH AddWatch;
    6.56 +  PXEN_XENBUS_REMWATCH RemWatch;
    6.57 +} XEN_IFACE_XENBUS, *PXEN_IFACE_XENBUS;
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xenpci/evtchn.c	Sat Nov 10 14:40:56 2007 +1100
     7.3 @@ -0,0 +1,242 @@
     7.4 +/*
     7.5 +PV Drivers for Windows Xen HVM Domains
     7.6 +Copyright (C) 2007 James Harper
     7.7 +
     7.8 +This program is free software; you can redistribute it and/or
     7.9 +modify it under the terms of the GNU General Public License
    7.10 +as published by the Free Software Foundation; either version 2
    7.11 +of the License, or (at your option) any later version.
    7.12 +
    7.13 +This program is distributed in the hope that it will be useful,
    7.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.16 +GNU General Public License for more details.
    7.17 +
    7.18 +You should have received a copy of the GNU General Public License
    7.19 +along with this program; if not, write to the Free Software
    7.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    7.21 +*/
    7.22 +
    7.23 +#include "xenpci.h"
    7.24 +#include "hypercall.h"
    7.25 +
    7.26 +#define NR_EVENTS 1024
    7.27 +
    7.28 +typedef struct _ev_action_t {
    7.29 +  PKSERVICE_ROUTINE ServiceRoutine;
    7.30 +  PVOID ServiceContext;
    7.31 +  ULONG Count;
    7.32 +} ev_action_t;
    7.33 +
    7.34 +static ev_action_t ev_actions[NR_EVENTS];
    7.35 +
    7.36 +static unsigned long bound_ports[NR_EVENTS/(8*sizeof(unsigned long))];
    7.37 +
    7.38 +BOOLEAN
    7.39 +EvtChn_Interrupt(WDFINTERRUPT Interrupt, ULONG MessageID)
    7.40 +{
    7.41 +  int cpu = 0;
    7.42 +  vcpu_info_t *vcpu_info;
    7.43 +//  int i;
    7.44 +  unsigned long evt_words, evt_word;
    7.45 +  unsigned long evt_bit;
    7.46 +  unsigned long port;
    7.47 +  ev_action_t *ev_action;
    7.48 +
    7.49 +  UNREFERENCED_PARAMETER(Interrupt);
    7.50 +  UNREFERENCED_PARAMETER(MessageID);
    7.51 +
    7.52 +  //KdPrint((__DRIVER_NAME "     I+\n"));
    7.53 +  //KdPrint((__DRIVER_NAME " --> XenPCI_ISR\n"));
    7.54 +
    7.55 +  vcpu_info = &shared_info_area->vcpu_info[cpu];
    7.56 +
    7.57 +  vcpu_info->evtchn_upcall_pending = 0;
    7.58 +
    7.59 +  evt_words = _InterlockedExchange((volatile LONG *)&vcpu_info->evtchn_pending_sel, 0);
    7.60 +  
    7.61 +  while (_BitScanForward(&evt_word, evt_words))
    7.62 +  {
    7.63 +    evt_words &= ~(1 << evt_word);
    7.64 +    while (_BitScanForward(&evt_bit, shared_info_area->evtchn_pending[evt_word] & ~shared_info_area->evtchn_mask[evt_word]))
    7.65 +    {
    7.66 +      port = (evt_word << 5) + evt_bit;
    7.67 +      ev_action = &ev_actions[port];
    7.68 +      if (ev_action->ServiceRoutine == NULL)
    7.69 +      {
    7.70 +        KdPrint((__DRIVER_NAME "     Unhandled Event!!!\n"));
    7.71 +      }
    7.72 +      else
    7.73 +      {
    7.74 +        //KdPrint((__DRIVER_NAME "     Calling Handler for port %d\n", port));
    7.75 +        ev_action->ServiceRoutine(NULL, ev_action->ServiceContext);
    7.76 +      }
    7.77 +      _interlockedbittestandreset((volatile LONG *)&shared_info_area->evtchn_pending[0], port);
    7.78 +    }
    7.79 +  }
    7.80 +
    7.81 +  //KdPrint((__DRIVER_NAME " <-- XenPCI_ISR\n"));
    7.82 +
    7.83 +  //KdPrint((__DRIVER_NAME "     I-\n"));
    7.84 +
    7.85 +  return TRUE;
    7.86 +}
    7.87 +
    7.88 +evtchn_port_t
    7.89 +EvtChn_AllocUnbound(domid_t Domain)
    7.90 +{
    7.91 +  evtchn_alloc_unbound_t op;
    7.92 +
    7.93 +  //KdPrint((__DRIVER_NAME " --> AllocUnbound\n"));
    7.94 +
    7.95 +  op.dom = DOMID_SELF;
    7.96 +  op.remote_dom = Domain;
    7.97 +  HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
    7.98 +
    7.99 +  //KdPrint((__DRIVER_NAME " <-- AllocUnbound\n"));
   7.100 +
   7.101 +  return op.port;
   7.102 +}
   7.103 +
   7.104 +
   7.105 +NTSTATUS
   7.106 +EvtChn_Bind(evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
   7.107 +{
   7.108 +  //KdPrint((__DRIVER_NAME " --> EvtChn_Bind\n"));
   7.109 +
   7.110 +  if(ev_actions[Port].ServiceRoutine != ServiceRoutine)
   7.111 +  {
   7.112 +    KdPrint((__DRIVER_NAME " Handler for port %d already registered, replacing\n", Port));
   7.113 +  }
   7.114 +
   7.115 +  ev_actions[Port].ServiceContext = ServiceContext;
   7.116 +  //_WriteBarrier();
   7.117 +  KeMemoryBarrier();
   7.118 +  ev_actions[Port].ServiceRoutine = ServiceRoutine;
   7.119 +
   7.120 +  EvtChn_Unmask(Port);
   7.121 +
   7.122 +  //KdPrint((__DRIVER_NAME " <-- EvtChn_Bind\n"));
   7.123 +
   7.124 +  return STATUS_SUCCESS;
   7.125 +}
   7.126 +
   7.127 +NTSTATUS
   7.128 +EvtChn_Unbind(evtchn_port_t Port)
   7.129 +{
   7.130 +  //KdPrint((__DRIVER_NAME " --> EvtChn_UnBind\n"));
   7.131 +
   7.132 +  EvtChn_Mask(Port);
   7.133 +  ev_actions[Port].ServiceContext = NULL;
   7.134 +  ev_actions[Port].ServiceRoutine = NULL;
   7.135 +
   7.136 +  //KdPrint((__DRIVER_NAME " <-- EvtChn_UnBind\n"));
   7.137 +
   7.138 +  return STATUS_SUCCESS;
   7.139 +}
   7.140 +
   7.141 +NTSTATUS
   7.142 +EvtChn_Mask(evtchn_port_t Port)
   7.143 +{
   7.144 +  //KdPrint((__DRIVER_NAME " --> EvtChn_Mask\n"));
   7.145 +
   7.146 +  _interlockedbittestandset((volatile LONG *)&shared_info_area->evtchn_mask[0], Port);
   7.147 +
   7.148 +  //KdPrint((__DRIVER_NAME " <-- EvtChn_Mask\n"));
   7.149 +
   7.150 +  return STATUS_SUCCESS;
   7.151 +}
   7.152 +
   7.153 +NTSTATUS
   7.154 +EvtChn_Unmask(evtchn_port_t Port)
   7.155 +{
   7.156 +  //KdPrint((__DRIVER_NAME " --> EvtChn_Unmask\n"));
   7.157 +
   7.158 +  _interlockedbittestandreset((volatile LONG *)&shared_info_area->evtchn_mask[0], Port);
   7.159 +  // should we kick off pending interrupts here too???
   7.160 +
   7.161 +  //KdPrint((__DRIVER_NAME " <-- EvtChn_Unmask\n"));
   7.162 +
   7.163 +  return STATUS_SUCCESS;
   7.164 +}
   7.165 +
   7.166 +NTSTATUS
   7.167 +EvtChn_Notify(evtchn_port_t Port)
   7.168 +{
   7.169 +  struct evtchn_send send;
   7.170 +
   7.171 +  //KdPrint((__DRIVER_NAME " --> EvtChn_Notify\n"));
   7.172 +
   7.173 +  send.port = Port;
   7.174 +
   7.175 +  (void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send);
   7.176 +
   7.177 +  //KdPrint((__DRIVER_NAME " <-- EvtChn_Notify\n"));
   7.178 +
   7.179 +  return STATUS_SUCCESS;
   7.180 +}
   7.181 +
   7.182 +
   7.183 +evtchn_port_t
   7.184 +EvtChn_GetXenStorePort()
   7.185 +{
   7.186 +  evtchn_port_t Port;  
   7.187 +
   7.188 +  //KdPrint((__DRIVER_NAME " --> EvtChn_GetStorePort\n"));
   7.189 +
   7.190 +  Port = (evtchn_port_t)hvm_get_parameter(HVM_PARAM_STORE_EVTCHN);
   7.191 +
   7.192 +  //KdPrint((__DRIVER_NAME " <-- EvtChn_GetStorePort\n"));
   7.193 +
   7.194 +  return Port;
   7.195 +}
   7.196 +
   7.197 +PVOID
   7.198 +EvtChn_GetXenStoreRingAddr()
   7.199 +{
   7.200 +  PHYSICAL_ADDRESS pa_xen_store_interface;
   7.201 +  PVOID xen_store_interface;
   7.202 +
   7.203 +  ULONG xen_store_mfn;
   7.204 +
   7.205 +  //KdPrint((__DRIVER_NAME " --> EvtChn_GetRingAddr\n"));
   7.206 +
   7.207 +  xen_store_mfn = (ULONG)hvm_get_parameter(HVM_PARAM_STORE_PFN);
   7.208 +
   7.209 +  pa_xen_store_interface.QuadPart = xen_store_mfn << PAGE_SHIFT;
   7.210 +  xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
   7.211 +
   7.212 +  //KdPrint((__DRIVER_NAME " xen_store_mfn = %08x\n", xen_store_mfn));
   7.213 +  //KdPrint((__DRIVER_NAME " xen_store_evtchn = %08x\n", xen_store_evtchn));
   7.214 +  //KdPrint((__DRIVER_NAME " xen_store_interface = %08x\n", xen_store_interface));
   7.215 +
   7.216 +  //KeInitializeEvent(&xenbus_waitevent, NotificationEvent, FALSE);
   7.217 +
   7.218 +  //KdPrint((__DRIVER_NAME " <-- EvtChn_GetRingAddr\n"));
   7.219 +
   7.220 +  return xen_store_interface;
   7.221 +}
   7.222 +
   7.223 +NTSTATUS
   7.224 +EvtChn_Init()
   7.225 +{
   7.226 +  int i;
   7.227 +
   7.228 +  for (i = 0; i < NR_EVENTS; i++)
   7.229 +  {
   7.230 +    EvtChn_Mask(i);
   7.231 +    ev_actions[i].ServiceRoutine = NULL;
   7.232 +    ev_actions[i].ServiceContext = NULL;
   7.233 +    ev_actions[i].Count = 0;
   7.234 +  }
   7.235 +
   7.236 +  for (i = 0; i < 8; i++) {
   7.237 +    shared_info_area->evtchn_pending[i] = 0;
   7.238 +  }
   7.239 +  shared_info_area->vcpu_info[0].evtchn_upcall_pending = 0;
   7.240 +  shared_info_area->vcpu_info[0].evtchn_pending_sel = 0;
   7.241 +
   7.242 +  return STATUS_SUCCESS;
   7.243 +}
   7.244 +
   7.245 +static ev_action_t ev_actions[NR_EVENTS];
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xenpci/gnttbl.c	Sat Nov 10 14:40:56 2007 +1100
     8.3 @@ -0,0 +1,137 @@
     8.4 +/*
     8.5 +PV Drivers for Windows Xen HVM Domains
     8.6 +Copyright (C) 2007 James Harper
     8.7 +
     8.8 +This program is free software; you can redistribute it and/or
     8.9 +modify it under the terms of the GNU General Public License
    8.10 +as published by the Free Software Foundation; either version 2
    8.11 +of the License, or (at your option) any later version.
    8.12 +
    8.13 +This program is distributed in the hope that it will be useful,
    8.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.16 +GNU General Public License for more details.
    8.17 +
    8.18 +You should have received a copy of the GNU General Public License
    8.19 +along with this program; if not, write to the Free Software
    8.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    8.21 +*/
    8.22 +
    8.23 +#include "xenpci.h"
    8.24 +#include <hypercall.h>
    8.25 +
    8.26 +static grant_entry_t *gnttab_table;
    8.27 +static PHYSICAL_ADDRESS gnttab_table_physical;
    8.28 +static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
    8.29 +
    8.30 +static void
    8.31 +put_free_entry(grant_ref_t ref)
    8.32 +{
    8.33 +    gnttab_list[ref] = gnttab_list[0];
    8.34 +    gnttab_list[0]  = ref;
    8.35 +
    8.36 +}
    8.37 +
    8.38 +static grant_ref_t
    8.39 +get_free_entry()
    8.40 +{
    8.41 +    unsigned int ref = gnttab_list[0];
    8.42 +    gnttab_list[0] = gnttab_list[ref];
    8.43 +    return ref;
    8.44 +}
    8.45 +
    8.46 +/*
    8.47 +struct grant_entry {
    8.48 +    uint16_t flags;
    8.49 +    domid_t  domid;
    8.50 +    uint32_t frame;
    8.51 +};
    8.52 +typedef struct grant_entry grant_entry_t;
    8.53 +*/
    8.54 +
    8.55 +static int 
    8.56 +GntTab_Map(unsigned int start_idx, unsigned int end_idx)
    8.57 +{
    8.58 +  struct xen_add_to_physmap xatp;
    8.59 +  unsigned int i = end_idx;
    8.60 +
    8.61 +  //KdPrint((__DRIVER_NAME " --> GntTbl_Init\n"));
    8.62 +  /* Loop backwards, so that the first hypercall has the largest index,
    8.63 +   * ensuring that the table will grow only once.
    8.64 +   */
    8.65 +  do {
    8.66 +    xatp.domid = DOMID_SELF;
    8.67 +    xatp.idx = i;
    8.68 +    xatp.space = XENMAPSPACE_grant_table;
    8.69 +    xatp.gpfn = (xen_pfn_t)(gnttab_table_physical.QuadPart >> PAGE_SHIFT) + i;
    8.70 +    if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
    8.71 +    {
    8.72 +      KdPrint((__DRIVER_NAME "     ***ERROR MAPPING FRAME***\n"));
    8.73 +    }
    8.74 +  } while (i-- > start_idx);
    8.75 +
    8.76 +  return 0;
    8.77 +}
    8.78 +
    8.79 +VOID
    8.80 +GntTbl_Init()
    8.81 +{
    8.82 +  int i;
    8.83 +
    8.84 +  //KdPrint((__DRIVER_NAME " --> GntTbl_Init\n"));
    8.85 +
    8.86 +  for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
    8.87 +    put_free_entry(i);
    8.88 +
    8.89 +  gnttab_table_physical = XenPCI_AllocMMIO(PAGE_SIZE * NR_GRANT_FRAMES);
    8.90 +  gnttab_table = MmMapIoSpace(gnttab_table_physical, PAGE_SIZE * NR_GRANT_FRAMES, MmNonCached);
    8.91 +  if (gnttab_table == NULL)
    8.92 +  {
    8.93 +    KdPrint((__DRIVER_NAME "     Error Mapping Grant Table Shared Memory\n"));
    8.94 +    return;
    8.95 +  }
    8.96 +  GntTab_Map(0, NR_GRANT_FRAMES - 1);
    8.97 +
    8.98 +  //KdPrint((__DRIVER_NAME " <-- GntTbl_Init table mapped at %p\n", gnttab_table));
    8.99 +}
   8.100 +
   8.101 +grant_ref_t
   8.102 +GntTbl_GrantAccess(domid_t domid, unsigned long frame, int readonly)
   8.103 +{
   8.104 +  grant_ref_t ref;
   8.105 +
   8.106 +  //KdPrint((__DRIVER_NAME " --> GntTbl_GrantAccess\n"));
   8.107 +
   8.108 +  ref = get_free_entry();
   8.109 +  gnttab_table[ref].frame = frame;
   8.110 +  gnttab_table[ref].domid = domid;
   8.111 +  //_WriteBarrier();
   8.112 +  KeMemoryBarrier();
   8.113 +  readonly *= GTF_readonly;
   8.114 +  gnttab_table[ref].flags = GTF_permit_access | (uint16_t)readonly;
   8.115 +
   8.116 +  //KdPrint((__DRIVER_NAME " <-- GntTbl_GrantAccess (ref = %d)\n", ref));
   8.117 +
   8.118 +  return ref;
   8.119 +}
   8.120 +
   8.121 +BOOLEAN
   8.122 +GntTbl_EndAccess(grant_ref_t ref)
   8.123 +{
   8.124 +  unsigned short flags, nflags;
   8.125 +
   8.126 +  //KdPrint((__DRIVER_NAME " --> GntTbl_EndAccess\n"));
   8.127 +
   8.128 +  nflags = gnttab_table[ref].flags;
   8.129 +  do {
   8.130 +    if ((flags = nflags) & (GTF_reading|GTF_writing))
   8.131 +    {
   8.132 +      KdPrint((__DRIVER_NAME "WARNING: g.e. still in use!\n"));
   8.133 +      return FALSE;
   8.134 +    }
   8.135 +  } while ((nflags = InterlockedCompareExchange16((volatile SHORT *)&gnttab_table[ref].flags, flags, 0)) != flags);
   8.136 +
   8.137 +  put_free_entry(ref);
   8.138 +  //KdPrint((__DRIVER_NAME " <-- GntTbl_EndAccess\n"));
   8.139 +  return TRUE;
   8.140 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xenpci/makefile	Sat Nov 10 14:40:56 2007 +1100
     9.3 @@ -0,0 +1,1 @@
     9.4 +!INCLUDE $(NTMAKEENV)\makefile.def
     9.5 \ No newline at end of file
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xenpci/memory.c	Sat Nov 10 14:40:56 2007 +1100
    10.3 @@ -0,0 +1,40 @@
    10.4 +#include "xenpci.h"
    10.5 +#include <hypercall.h>
    10.6 +
    10.7 +static pgentry_t *demand_map_pgt;
    10.8 +static void *demand_map_area_start;
    10.9 +
   10.10 +PVOID
   10.11 +map_frames(PULONG f, ULONG n)
   10.12 +{
   10.13 +  unsigned long x;
   10.14 +  unsigned long y = 0;
   10.15 +  mmu_update_t mmu_updates[16];
   10.16 +  int rc;
   10.17 + 
   10.18 +  for (x = 0; x <= 1024 - n; x += y + 1) {
   10.19 +    for (y = 0; y < n; y++)
   10.20 +      if (demand_map_pgt[x+y] & _PAGE_PRESENT)
   10.21 +        break;
   10.22 +    if (y == n)
   10.23 +      break;
   10.24 +  }
   10.25 +  if (y != n) {
   10.26 +      KdPrint((__DRIVER_NAME " Failed to map %ld frames!\n", n));
   10.27 +      return NULL;
   10.28 +  }
   10.29 +
   10.30 +  for (y = 0; y < n; y++) {
   10.31 +    //mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + y]);
   10.32 +    mmu_updates[y].ptr = MmGetPhysicalAddress(&demand_map_pgt[x + y]).QuadPart;
   10.33 +    mmu_updates[y].val = (f[y] << PAGE_SHIFT) | L1_PROT;
   10.34 +  }
   10.35 +
   10.36 +  rc = HYPERVISOR_mmu_update(mmu_updates, n, NULL, DOMID_SELF);
   10.37 +  if (rc < 0) {
   10.38 +    KdPrint((__DRIVER_NAME " Map %ld failed: %d.\n", n, rc));
   10.39 +    return NULL;
   10.40 +  } else {
   10.41 +    return (PVOID)(ULONG)((ULONG)demand_map_area_start + x * PAGE_SIZE);
   10.42 +  }
   10.43 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xenpci/target/xenpci.inf	Sat Nov 10 14:40:56 2007 +1100
    11.3 @@ -0,0 +1,94 @@
    11.4 +[Version]
    11.5 +Signature="$WINDOWS NT$"
    11.6 +Class=Xen
    11.7 +ClassGuid={C828ABE9-14CA-4445-BAA6-82C2376C6518}
    11.8 +Provider=%JAMESHARPER%
    11.9 +DriverVer=11/08/2007,1.0.1.2
   11.10 +
   11.11 +[DestinationDirs]
   11.12 +DefaultDestDir = 12
   11.13 +ClassInstall32_CopyFiles=11
   11.14 +CoInstaller_CopyFiles = 11
   11.15 +
   11.16 +; ================= Class section =====================
   11.17 +
   11.18 +[ClassInstall32]
   11.19 +Addreg=ClassInstall32_AddReg
   11.20 +CopyFiles=ClassInstall32_CopyFiles
   11.21 +
   11.22 +[ClassInstall32_AddReg]
   11.23 +HKR,,,0,%ClassName%
   11.24 +HKR,,Icon,,-5
   11.25 +HKR,,DeviceCharacteristics,0x10001,0x100     ;Use same security checks on relative opens
   11.26 +HKR,,Security,,"D:P(A;;GA;;;SY)(A;;GA;;;BA)" ;Allow generic all access to system and built-in Admin. 
   11.27 +
   11.28 +[ClassInstall32_CopyFiles]
   11.29 +
   11.30 +; ================= Device Install section =====================
   11.31 +
   11.32 +[ControlFlags]
   11.33 +ExcludeFromSelect=*
   11.34 +
   11.35 +
   11.36 +[Manufacturer]
   11.37 +%JAMESHARPER%=JAMESHARPER,NTx86
   11.38 +
   11.39 +; For Win2K
   11.40 +[JAMESHARPER]
   11.41 +; DisplayName            Section           DeviceId
   11.42 +; -----------       	 -------           --------
   11.43 +%XenPCI.DRVDESC%=XenPCI_Inst, PCI\VEN_5853&DEV_0001
   11.44 +
   11.45 +; For XP and later
   11.46 +[JAMESHARPER.NTx86]
   11.47 +; DisplayName            Section           DeviceId
   11.48 +; -----------       	 -------           --------
   11.49 +%XenPCI.DRVDESC%=XenPCI_Inst, PCI\VEN_5853&DEV_0001
   11.50 +
   11.51 +[XenPCI_Inst.NT]
   11.52 +CopyFiles=XenPCI.CopyFiles
   11.53 +
   11.54 +[XenPCI.CopyFiles]
   11.55 +xenpci.sys
   11.56 +
   11.57 +[SourceDisksFiles]
   11.58 +xenpci.sys=1
   11.59 +WdfCoinstaller01005.dll=1,,
   11.60 +
   11.61 +[SourceDisksNames.x86]
   11.62 +1 = %DISK_NAME%,,,\i386
   11.63 +
   11.64 +[XenPCI_Inst.NT.Services]
   11.65 +AddService=XenPCI,2,XenPCI_Service 
   11.66 +
   11.67 +[XenPCI_Service]
   11.68 +DisplayName    = %XenPCI.SVCDESC%                            
   11.69 +ServiceType    = 1
   11.70 +StartType      = 0
   11.71 +ErrorControl   = 1
   11.72 +LoadOrderGroup = WdfLoadGroup
   11.73 +ServiceBinary  = %12%\xenpci.sys                            
   11.74 +
   11.75 +[XenPCI_Inst.NT.CoInstallers]
   11.76 +AddReg=CoInstaller_AddReg
   11.77 +CopyFiles=CoInstaller_CopyFiles
   11.78 +
   11.79 +[CoInstaller_CopyFiles]
   11.80 +WdfCoinstaller01005.dll,,,2
   11.81 +
   11.82 +[CoInstaller_AddReg]
   11.83 +HKR,,CoInstallers32,0x00010000, "WdfCoinstaller01005.dll,WdfCoInstaller"
   11.84 +
   11.85 +[XenPCI_Inst.NT.Wdf]
   11.86 +KmdfService = xenpci, xenpci_wdfsect
   11.87 +
   11.88 +[xenpci_wdfsect]
   11.89 +KmdfLibraryVersion = 1.0
   11.90 +
   11.91 +[Strings]
   11.92 +JAMESHARPER = "James Harper"
   11.93 +ClassName = "System devices"
   11.94 +XenPCI.SVCDESC = "Xen PCI Device Driver"
   11.95 +XenPCI.DRVDESC = "Xen PCI Device Driver"
   11.96 +DISK_NAME = "Xen PCI Device Driver Install Disk"
   11.97 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/xenpci/xenbus.c	Sat Nov 10 14:40:56 2007 +1100
    12.3 @@ -0,0 +1,788 @@
    12.4 +/*
    12.5 +PV Drivers for Windows Xen HVM Domains
    12.6 +Copyright (C) 2007 James Harper
    12.7 +
    12.8 +This program is free software; you can redistribute it and/or
    12.9 +modify it under the terms of the GNU General Public License
   12.10 +as published by the Free Software Foundation; either version 2
   12.11 +of the License, or (at your option) any later version.
   12.12 +
   12.13 +This program is distributed in the hope that it will be useful,
   12.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.16 +GNU General Public License for more details.
   12.17 +
   12.18 +You should have received a copy of the GNU General Public License
   12.19 +along with this program; if not, write to the Free Software
   12.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   12.21 +*/
   12.22 +
   12.23 +#include "xenpci.h"
   12.24 +#include "io/xs_wire.h"
   12.25 +#include <stdlib.h>
   12.26 +
   12.27 +#pragma warning( disable : 4204 ) 
   12.28 +#pragma warning( disable : 4221 ) 
   12.29 +
   12.30 +struct xenbus_req_info
   12.31 +{
   12.32 +  int In_Use:1;
   12.33 +  KEVENT WaitEvent;
   12.34 +  void *Reply;
   12.35 +};
   12.36 +
   12.37 +typedef struct {
   12.38 +  char Path[128];
   12.39 +  PXENBUS_WATCH_CALLBACK ServiceRoutine;
   12.40 +  PVOID ServiceContext;
   12.41 +  int Count;
   12.42 +  int Active;
   12.43 +} XENBUS_WATCH_ENTRY, *PXENBUS_WATCH_ENTRY;
   12.44 +
   12.45 +typedef struct {
   12.46 +  char Path[128];
   12.47 +  char Token[10];
   12.48 +} XENBUS_WATCH_RING;
   12.49 +
   12.50 +#define WATCH_RING_SIZE 128
   12.51 +
   12.52 +static XENBUS_WATCH_RING XenBus_WatchRing[WATCH_RING_SIZE];
   12.53 +static int XenBus_WatchRingReadIndex;
   12.54 +static int XenBus_WatchRingWriteIndex;
   12.55 +
   12.56 +#define MAX_WATCH_ENTRIES 128
   12.57 +
   12.58 +static XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
   12.59 +
   12.60 +#define NR_REQS 32
   12.61 +//#define XENSTORE_RING_SIZE 1024
   12.62 +
   12.63 +//#define XENSTORE_RING_SIZE 1024
   12.64 +//typedef uint32_t XENSTORE_RING_IDX;
   12.65 +//#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
   12.66 +
   12.67 +static struct xenstore_domain_interface *xen_store_interface;
   12.68 +
   12.69 +static struct xenbus_req_info req_info[NR_REQS];
   12.70 +static int nr_live_reqs;
   12.71 +//static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
   12.72 +
   12.73 +static HANDLE XenBus_ReadThreadHandle;
   12.74 +static KEVENT XenBus_ReadThreadEvent;
   12.75 +
   12.76 +static HANDLE XenBus_WatchThreadHandle;
   12.77 +static KEVENT XenBus_WatchThreadEvent;
   12.78 +
   12.79 +static void
   12.80 +XenBus_ReadThreadProc(PVOID StartContext);
   12.81 +static void
   12.82 +XenBus_WatchThreadProc(PVOID StartContext);
   12.83 +
   12.84 +static BOOLEAN
   12.85 +XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext);
   12.86 +
   12.87 +static int allocate_xenbus_id(void)
   12.88 +{
   12.89 +  static int probe;
   12.90 +  int o_probe;
   12.91 +
   12.92 +  //KdPrint((__DRIVER_NAME " --> allocate_xenbus_id\n"));
   12.93 +
   12.94 +  for (;;)
   12.95 +  {
   12.96 +//    spin_lock(&req_lock);
   12.97 +    if (nr_live_reqs < NR_REQS)
   12.98 +      break;
   12.99 +//    spin_unlock(&req_lock);
  12.100 +//    wait_event(req_wq, (nr_live_reqs < NR_REQS));
  12.101 +  }
  12.102 +
  12.103 +  o_probe = probe;
  12.104 +
  12.105 +  for (;;)
  12.106 +  {
  12.107 +    if (!req_info[o_probe].In_Use)
  12.108 +      break;
  12.109 +    o_probe = (o_probe + 1) % NR_REQS;
  12.110 +//    BUG_ON(o_probe == probe);
  12.111 +  }
  12.112 +  nr_live_reqs++;
  12.113 +  req_info[o_probe].In_Use = 1;
  12.114 +  probe = (o_probe + 1) % NR_REQS;
  12.115 +  //spin_unlock(&req_lock);
  12.116 +  //init_waitqueue_head(&req_info[o_probe].waitq);
  12.117 +  KeInitializeEvent(&req_info[o_probe].WaitEvent, SynchronizationEvent, FALSE);
  12.118 +
  12.119 +  //KdPrint((__DRIVER_NAME " <-- allocate_xenbus_id\n"));
  12.120 +
  12.121 +  return o_probe;
  12.122 +}
  12.123 +
  12.124 +static void release_xenbus_id(int id)
  12.125 +{
  12.126 +//    BUG_ON(!req_info[id].in_use);
  12.127 +//    spin_lock(&req_lock);
  12.128 +    req_info[id].In_Use = 0;
  12.129 +    nr_live_reqs--;
  12.130 +    req_info[id].In_Use = 0;
  12.131 +//    if (nr_live_reqs == NR_REQS - 1)
  12.132 +//        wake_up(&req_wq);
  12.133 +//    spin_unlock(&req_lock);
  12.134 +}
  12.135 +
  12.136 +
  12.137 +static char *errmsg(struct xsd_sockmsg *rep)
  12.138 +{
  12.139 +  char *res;
  12.140 +  if (!rep) {
  12.141 +    char msg[] = "No reply";
  12.142 +    size_t len = strlen(msg) + 1;
  12.143 +    return memcpy(ExAllocatePoolWithTag(NonPagedPool, len, XENPCI_POOL_TAG), msg, len);
  12.144 +  }
  12.145 +  if (rep->type != XS_ERROR)
  12.146 +    return NULL;
  12.147 +  res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
  12.148 +  memcpy(res, rep + 1, rep->len);
  12.149 +  res[rep->len] = 0;
  12.150 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
  12.151 +  return res;
  12.152 +}
  12.153 +
  12.154 +static void memcpy_from_ring(const void *Ring,
  12.155 +        void *Dest,
  12.156 +        int off,
  12.157 +        int len)
  12.158 +{
  12.159 +  int c1, c2;
  12.160 +  const char *ring = Ring;
  12.161 +  char *dest = Dest;
  12.162 +  c1 = min(len, XENSTORE_RING_SIZE - off);
  12.163 +  c2 = len - c1;
  12.164 +  memcpy(dest, ring + off, c1);
  12.165 +  memcpy(dest + c1, ring, c2);
  12.166 +}
  12.167 +
  12.168 +void wait_for_watch(void)
  12.169 +{
  12.170 +//    DEFINE_WAIT(w);
  12.171 +//    add_waiter(w,watch_queue);
  12.172 +//    schedule();
  12.173 +//    remove_waiter(w);
  12.174 +//    wake(current);
  12.175 +}
  12.176 +
  12.177 +struct write_req {
  12.178 +    const void *data;
  12.179 +    unsigned len;
  12.180 +};
  12.181 +
  12.182 +static evtchn_port_t xen_store_evtchn;
  12.183 +
  12.184 +static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
  12.185 +                     const struct write_req *req, int nr_reqs)
  12.186 +{
  12.187 +  XENSTORE_RING_IDX prod;
  12.188 +  int r;
  12.189 +  size_t len = 0;
  12.190 +  const struct write_req *cur_req;
  12.191 +  size_t req_off;
  12.192 +  size_t total_off;
  12.193 +  size_t this_chunk;
  12.194 +  struct xsd_sockmsg m = {type, req_id, trans_id };
  12.195 +  struct write_req header_req = { &m, sizeof(m) };
  12.196 +
  12.197 +  //KdPrint((__DRIVER_NAME " --> xb_write\n"));
  12.198 +
  12.199 +  for (r = 0; r < nr_reqs; r++)
  12.200 +    len += req[r].len;
  12.201 +  m.len = len;
  12.202 +  len += sizeof(m);
  12.203 +
  12.204 +  cur_req = &header_req;
  12.205 +
  12.206 +//  BUG_ON(len > XENSTORE_RING_SIZE);
  12.207 +  /* Wait for the ring to drain to the point where we can send the
  12.208 +     message. */
  12.209 +  prod = xen_store_interface->req_prod;
  12.210 +
  12.211 +  //KdPrint((__DRIVER_NAME " prod = %08x\n", prod));
  12.212 +
  12.213 +  if (prod + len - xen_store_interface->req_cons > XENSTORE_RING_SIZE)
  12.214 +  {
  12.215 +    /* Wait for there to be space on the ring */
  12.216 +    //KdPrint((__DRIVER_NAME " prod %d, len %d, cons %d, size %d; waiting.\n", prod, len, xen_store_interface->req_cons, XENSTORE_RING_SIZE));
  12.217 +//    wait_event(xb_waitq, xen_store_interface->req_prod + len - xen_store_interface->req_cons <= XENSTORE_RING_SIZE);
  12.218 +    //KdPrint((__DRIVER_NAME " Back from wait.\n"));
  12.219 +    prod = xen_store_interface->req_prod;
  12.220 +  }
  12.221 +
  12.222 +  /* We're now guaranteed to be able to send the message without
  12.223 +     overflowing the ring.  Do so. */
  12.224 +
  12.225 +  total_off = 0;
  12.226 +  req_off = 0;
  12.227 +
  12.228 +  while (total_off < len)
  12.229 +  {
  12.230 +    this_chunk = min(cur_req->len - req_off,XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
  12.231 +    memcpy((char *)xen_store_interface->req + MASK_XENSTORE_IDX(prod), (char *)cur_req->data + req_off, this_chunk);
  12.232 +    prod += this_chunk;
  12.233 +    req_off += this_chunk;
  12.234 +    total_off += this_chunk;
  12.235 +    if (req_off == cur_req->len)
  12.236 +    {
  12.237 +      req_off = 0;
  12.238 +      if (cur_req == &header_req)
  12.239 +        cur_req = req;
  12.240 +      else
  12.241 +        cur_req++;
  12.242 +    }
  12.243 +  }
  12.244 +
  12.245 +  //KdPrint((__DRIVER_NAME " Complete main loop of xb_write.\n"));
  12.246 +
  12.247 +//  BUG_ON(req_off != 0);
  12.248 +//  BUG_ON(total_off != len);
  12.249 +//  BUG_ON(prod > xen_store_interface->req_cons + XENSTORE_RING_SIZE);
  12.250 +
  12.251 +  /* Remote must see entire message before updating indexes */
  12.252 +  //_WriteBarrier();
  12.253 +  KeMemoryBarrier();
  12.254 +
  12.255 +  xen_store_interface->req_prod += len;
  12.256 +
  12.257 +  //KdPrint((__DRIVER_NAME " prod = %08x\n", xen_store_interface->req_prod));
  12.258 +
  12.259 +  /* Send evtchn to notify remote */
  12.260 +  EvtChn_Notify(xen_store_evtchn);
  12.261 +
  12.262 +  //KdPrint((__DRIVER_NAME " <-- xb_write\n"));
  12.263 +}
  12.264 +
  12.265 +static struct xsd_sockmsg *
  12.266 +xenbus_msg_reply(int type,
  12.267 +                 xenbus_transaction_t trans,
  12.268 +                 struct write_req *io,
  12.269 +                 int nr_reqs)
  12.270 +{
  12.271 +  int id;
  12.272 +//  DEFINE_WAIT(w);
  12.273 +  struct xsd_sockmsg *rep;
  12.274 +
  12.275 +  //KdPrint((__DRIVER_NAME " --> xenbus_msg_reply\n"));
  12.276 +
  12.277 +  id = allocate_xenbus_id();
  12.278 +//  add_waiter(w, req_info[id].waitq);
  12.279 +
  12.280 +  xb_write(type, id, trans, io, nr_reqs);
  12.281 +//
  12.282 +//  schedule();
  12.283 +//  remove_waiter(w);
  12.284 +//  wake(current);
  12.285 +//
  12.286 +  //KdPrint((__DRIVER_NAME "     starting wait\n"));
  12.287 +
  12.288 +  KeWaitForSingleObject(&req_info[id].WaitEvent, Executive, KernelMode, FALSE, NULL);
  12.289 +
  12.290 +  //KdPrint((__DRIVER_NAME "     wait complete\n"));
  12.291 +
  12.292 +  rep = req_info[id].Reply;
  12.293 +//  BUG_ON(rep->req_id != id);
  12.294 +  release_xenbus_id(id);
  12.295 +  //KdPrint((__DRIVER_NAME " <-- xenbus_msg_reply\n"));
  12.296 +  return rep;
  12.297 +//  return NULL;
  12.298 +}
  12.299 +
  12.300 +char *
  12.301 +XenBus_Read(xenbus_transaction_t xbt, const char *path, char **value)
  12.302 +{
  12.303 +    struct write_req req[] = { {path, strlen(path) + 1} };
  12.304 +    struct xsd_sockmsg *rep;
  12.305 +    char *res;
  12.306 +    char *msg;
  12.307 +
  12.308 +    rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
  12.309 +    msg = errmsg(rep);
  12.310 +    if (msg) {
  12.311 +      *value = NULL;
  12.312 +      return msg;
  12.313 +    }
  12.314 +    res = ExAllocatePoolWithTag(NonPagedPool, rep->len + 1, XENPCI_POOL_TAG);
  12.315 +    memcpy(res, rep + 1, rep->len);
  12.316 +    res[rep->len] = 0;
  12.317 +    ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
  12.318 +    *value = res;
  12.319 +    return NULL;
  12.320 +}
  12.321 +
  12.322 +char *
  12.323 +XenBus_Write(xenbus_transaction_t xbt, const char *path, const char *value)
  12.324 +{
  12.325 +    struct write_req req[] = {
  12.326 +        {path, strlen(path) + 1},
  12.327 +        {value, strlen(value) + 1},
  12.328 +    };
  12.329 +    struct xsd_sockmsg *rep;
  12.330 +    char *msg;
  12.331 +
  12.332 +    rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
  12.333 +    msg = errmsg(rep);
  12.334 +    if (msg)
  12.335 +      return msg;
  12.336 +    ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
  12.337 +    return NULL;
  12.338 +}
  12.339 +
  12.340 +char* xenbus_wait_for_value(const char* path,const char* value)
  12.341 +{
  12.342 +  UNREFERENCED_PARAMETER(path);
  12.343 +  UNREFERENCED_PARAMETER(value);
  12.344 +//  for(;;)
  12.345 +//  {
  12.346 +//    char *res, *msg;
  12.347 +//    int r;
  12.348 +//
  12.349 +//    msg = xenbus_read(XBT_NIL, path, &res);
  12.350 +//    if(msg) return msg;
  12.351 +//
  12.352 +//    r = strcmp(value,res);
  12.353 +//    ExFreePoolWithTag(res, XENPCI_POOL_TAG);
  12.354 +//
  12.355 +//    if(r==0)
  12.356 +//      break;
  12.357 +//    else
  12.358 +//      wait_for_watch();
  12.359 +//    }
  12.360 +    return NULL;
  12.361 +}
  12.362 +
  12.363 +NTSTATUS
  12.364 +XenBus_Init()
  12.365 +{
  12.366 +  //KdPrint((__DRIVER_NAME " --> XenBus_Init\n"));
  12.367 +
  12.368 +  xen_store_evtchn = EvtChn_GetXenStorePort();
  12.369 +  xen_store_interface = EvtChn_GetXenStoreRingAddr();
  12.370 +
  12.371 +  //KdPrint((__DRIVER_NAME "     xen_store_evtchn = %08x\n", xen_store_evtchn));
  12.372 +  //KdPrint((__DRIVER_NAME "     xen_store_interface = %08x\n", xen_store_interface));
  12.373 +
  12.374 +  KeInitializeEvent(&XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
  12.375 +  KeInitializeEvent(&XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
  12.376 +
  12.377 +  //KdPrint((__DRIVER_NAME " <-- XenBus_Init\n"));
  12.378 +
  12.379 +  return STATUS_SUCCESS;
  12.380 +}
  12.381 +
  12.382 +NTSTATUS
  12.383 +XenBus_Start()
  12.384 +{
  12.385 +  OBJECT_ATTRIBUTES oa;
  12.386 +  NTSTATUS status;
  12.387 +  int i;
  12.388 +
  12.389 +  //KdPrint((__DRIVER_NAME " --> XenBus_Start\n"));
  12.390 +
  12.391 +  InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
  12.392 +  status = PsCreateSystemThread(&XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_ReadThreadProc, NULL);
  12.393 +
  12.394 +  // remove all existing watches already in Xen too...
  12.395 +
  12.396 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++)
  12.397 +    XenBus_WatchEntries[i].Active = 0;
  12.398 +
  12.399 +  InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
  12.400 +  status = PsCreateSystemThread(&XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_WatchThreadProc, NULL);
  12.401 +
  12.402 +  EvtChn_Bind(xen_store_evtchn, XenBus_Interrupt, NULL);
  12.403 +
  12.404 +  //KdPrint((__DRIVER_NAME " <-- XenBus_Start\n"));
  12.405 +
  12.406 +  return STATUS_SUCCESS;
  12.407 +}
  12.408 +
  12.409 +NTSTATUS
  12.410 +XenBus_Stop()
  12.411 +{
  12.412 +  int i;
  12.413 +
  12.414 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++)
  12.415 +  {
  12.416 +    if (!XenBus_WatchEntries[i].Active)
  12.417 +      continue;
  12.418 +    XenBus_RemWatch(XBT_NIL, XenBus_WatchEntries[i].Path, XenBus_WatchEntries[i].ServiceRoutine, XenBus_WatchEntries[i].ServiceContext);
  12.419 +  }
  12.420 +
  12.421 +  EvtChn_Unbind(xen_store_evtchn);
  12.422 +
  12.423 +  // Does this actually stop the threads???
  12.424 +  ZwClose(XenBus_WatchThreadHandle);
  12.425 +  ZwClose(XenBus_ReadThreadHandle);
  12.426 +
  12.427 +  return STATUS_SUCCESS;
  12.428 +}
  12.429 +
  12.430 +char *
  12.431 +XenBus_List(xenbus_transaction_t xbt, const char *pre, char ***contents)
  12.432 +{
  12.433 +  struct xsd_sockmsg *reply, *repmsg;
  12.434 +  struct write_req req[] = { { pre, strlen(pre)+1 } };
  12.435 +  ULONG nr_elems, x, i;
  12.436 +  char **res;
  12.437 +  char *msg;
  12.438 +
  12.439 +  //KdPrint((__DRIVER_NAME " --> xenbus_ls\n"));
  12.440 +
  12.441 +  repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
  12.442 +  msg = errmsg(repmsg);
  12.443 +  if (msg) {
  12.444 +    *contents = NULL;
  12.445 +    //KdPrint((__DRIVER_NAME " <-- xenbus_ls (error)\n"));
  12.446 +    return msg;
  12.447 +  }
  12.448 +  reply = repmsg + 1;
  12.449 +  for (x = nr_elems = 0; x < repmsg->len; x++)
  12.450 +    nr_elems += (((char *)reply)[x] == 0);
  12.451 +  res = ExAllocatePoolWithTag(NonPagedPool, sizeof(res[0]) * (nr_elems + 1), XENPCI_POOL_TAG);
  12.452 +  for (x = i = 0; i < nr_elems; i++) {
  12.453 +    int l = strlen((char *)reply + x);
  12.454 +    res[i] = ExAllocatePoolWithTag(NonPagedPool, l + 1, XENPCI_POOL_TAG);
  12.455 +    memcpy(res[i], (char *)reply + x, l + 1);
  12.456 +    x += l + 1;
  12.457 +  }
  12.458 +  res[i] = NULL;
  12.459 +  ExFreePoolWithTag(repmsg, XENPCI_POOL_TAG);
  12.460 +  *contents = res;
  12.461 +  //KdPrint((__DRIVER_NAME " <-- xenbus_ls\n"));
  12.462 +  return NULL;
  12.463 +}
  12.464 +
  12.465 +void
  12.466 +do_ls_test(const char *pre)
  12.467 +{
  12.468 +  char **dirs;
  12.469 +  int x;
  12.470 +  char *msg;
  12.471 +
  12.472 +  //KdPrint((__DRIVER_NAME " <-- do_ls_test(\"%s\")\n", pre));
  12.473 +
  12.474 +  msg = XenBus_List(XBT_NIL, pre, &dirs);
  12.475 +  if (msg)
  12.476 +  {
  12.477 +    //KdPrint((__DRIVER_NAME "     Error in xenbus ls: %s\n", msg));
  12.478 +    ExFreePoolWithTag(msg, XENPCI_POOL_TAG);
  12.479 +    return;
  12.480 +  }
  12.481 +  for (x = 0; dirs[x]; x++)
  12.482 +  {
  12.483 +    //KdPrint((__DRIVER_NAME "     ls %s[%d] -> %s\n", pre, x, dirs[x]));
  12.484 +    ExFreePoolWithTag(dirs[x], XENPCI_POOL_TAG);
  12.485 +  }
  12.486 +  ExFreePoolWithTag(dirs, XENPCI_POOL_TAG);
  12.487 +  //KdPrint((__DRIVER_NAME " --> do_ls_test\n"));
  12.488 +}
  12.489 +
  12.490 +int ReadThreadSetCount;
  12.491 +int ReadThreadWaitCount;
  12.492 +
  12.493 +static void
  12.494 +XenBus_ReadThreadProc(PVOID StartContext) {
  12.495 +  int NewWriteIndex;
  12.496 +  struct xsd_sockmsg msg;
  12.497 +  char *payload;
  12.498 +  char *path, *token;
  12.499 +
  12.500 +  UNREFERENCED_PARAMETER(StartContext);
  12.501 +
  12.502 +  for(;;)
  12.503 +  {
  12.504 +    KeWaitForSingleObject(&XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
  12.505 +    //KdPrint((__DRIVER_NAME "     ReadThread Woken (Count = %d)\n", ReadThreadWaitCount++));
  12.506 +    while (xen_store_interface->rsp_prod != xen_store_interface->rsp_cons)
  12.507 +    {
  12.508 +      //KdPrint((__DRIVER_NAME "     a - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
  12.509 +      if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg))
  12.510 +      {
  12.511 +        //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
  12.512 +        break;
  12.513 +      }
  12.514 +      //_ReadBarrier();
  12.515 +      KeMemoryBarrier();
  12.516 +      memcpy_from_ring(xen_store_interface->rsp, &msg, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), sizeof(msg));
  12.517 +      if (xen_store_interface->rsp_prod - xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
  12.518 +      {
  12.519 +        //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
  12.520 +        break;
  12.521 +      }
  12.522 +  
  12.523 +      if(msg.type == XS_WATCH_EVENT)
  12.524 +      {
  12.525 +        payload = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
  12.526 +  
  12.527 +        memcpy_from_ring(xen_store_interface->rsp, payload, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), msg.len + sizeof(msg));
  12.528 +  
  12.529 +        xen_store_interface->rsp_cons += msg.len + sizeof(msg);
  12.530 +        //KdPrint((__DRIVER_NAME "     b - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
  12.531 +  
  12.532 +        path = payload + sizeof(msg);
  12.533 +        token = path + strlen(path) + 1;
  12.534 +
  12.535 +        NewWriteIndex = (XenBus_WatchRingWriteIndex + 1) & 127;
  12.536 +        if (NewWriteIndex != XenBus_WatchRingReadIndex)
  12.537 +        {
  12.538 +          strncpy(XenBus_WatchRing[NewWriteIndex].Path, path, 128);
  12.539 +          strncpy(XenBus_WatchRing[NewWriteIndex].Token, token, 10);
  12.540 +          XenBus_WatchRingWriteIndex = NewWriteIndex;
  12.541 +        }
  12.542 +        else
  12.543 +        {
  12.544 +          KdPrint((__DRIVER_NAME " +++ Queue full Path = %s Token = %s\n", path, token));
  12.545 +          // drop the message on the floor
  12.546 +          continue;
  12.547 +        }
  12.548 +
  12.549 +        ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
  12.550 +        //KdPrint((__DRIVER_NAME " +++ Watch Path = %s Token = %s\n", path, token));
  12.551 +        KeSetEvent(&XenBus_WatchThreadEvent, 1, FALSE);
  12.552 +      }
  12.553 +      else
  12.554 +      {  
  12.555 +        req_info[msg.req_id].Reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
  12.556 +        memcpy_from_ring(xen_store_interface->rsp, req_info[msg.req_id].Reply, MASK_XENSTORE_IDX(xen_store_interface->rsp_cons), msg.len + sizeof(msg));
  12.557 +        xen_store_interface->rsp_cons += msg.len + sizeof(msg);
  12.558 +        //KdPrint((__DRIVER_NAME "     c - Rsp_cons %d, rsp_prod %d.\n", xen_store_interface->rsp_cons, xen_store_interface->rsp_prod));
  12.559 +        //KdPrint((__DRIVER_NAME " +++ Message = %s\n", ((char *)req_info[msg.req_id].Reply) + sizeof(msg)));
  12.560 +        KeSetEvent(&req_info[msg.req_id].WaitEvent, 1, FALSE);
  12.561 +      }
  12.562 +    }
  12.563 +  }
  12.564 +}
  12.565 +
  12.566 +static void
  12.567 +XenBus_WatchThreadProc(PVOID StartContext)
  12.568 +{
  12.569 +  int index;
  12.570 +  PXENBUS_WATCH_ENTRY entry;
  12.571 +
  12.572 +  UNREFERENCED_PARAMETER(StartContext);
  12.573 +
  12.574 +  for(;;)
  12.575 +  {
  12.576 +    KeWaitForSingleObject(&XenBus_WatchThreadEvent, Executive, KernelMode, FALSE, NULL);
  12.577 +    while (XenBus_WatchRingReadIndex != XenBus_WatchRingWriteIndex)
  12.578 +    {
  12.579 +      XenBus_WatchRingReadIndex = (XenBus_WatchRingReadIndex + 1) & 127;
  12.580 +      index = atoi(XenBus_WatchRing[XenBus_WatchRingReadIndex].Token);
  12.581 +      //XenBus_WatchRing[XenBus_WatchRingReadIndex].Path
  12.582 +      //XenBus_WatchRing[XenBus_WatchRingReadIndex].Token
  12.583 +
  12.584 +      entry = &XenBus_WatchEntries[index];
  12.585 +      if (!entry->Active)
  12.586 +      {
  12.587 +        KdPrint((__DRIVER_NAME " +++ Watch not active! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
  12.588 +        continue;
  12.589 +      }
  12.590 +      entry->Count++;
  12.591 +      if (!entry->ServiceRoutine)
  12.592 +      {
  12.593 +        KdPrint((__DRIVER_NAME " +++ no handler for watch! = %s Token = %s\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
  12.594 +        continue;
  12.595 +      }
  12.596 +      //KdPrint((__DRIVER_NAME " +++ Watch Triggered Path = %s Token = %d (%s)\n", XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, index, XenBus_WatchRing[XenBus_WatchRingReadIndex].Token));
  12.597 +      entry->ServiceRoutine(XenBus_WatchRing[XenBus_WatchRingReadIndex].Path, entry->ServiceContext);
  12.598 +    }
  12.599 +  }
  12.600 +}    
  12.601 +
  12.602 +char *
  12.603 +XenBus_AddWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
  12.604 +{
  12.605 +  struct xsd_sockmsg *rep;
  12.606 +  char *msg;
  12.607 +  int i;
  12.608 +  char Token[20];
  12.609 +  struct write_req req[2];
  12.610 +
  12.611 +  //KdPrint((__DRIVER_NAME " --> XenBus_AddWatch\n"));
  12.612 +
  12.613 +  // check that Path < 128 chars
  12.614 +
  12.615 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++)
  12.616 +    if (XenBus_WatchEntries[i].Active == 0)
  12.617 +      break;
  12.618 +  
  12.619 +  if (i == MAX_WATCH_ENTRIES)
  12.620 +  {
  12.621 +    KdPrint((__DRIVER_NAME " +++ No more watch slots left\n"));
  12.622 +    return NULL;
  12.623 +  }
  12.624 +
  12.625 +  req[0].data = Path;
  12.626 +  req[0].len = strlen(Path) + 1;
  12.627 +
  12.628 +  RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
  12.629 +  req[1].data = Token;
  12.630 +  req[1].len = strlen(Token) + 1;
  12.631 +
  12.632 +  rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
  12.633 +
  12.634 +  msg = errmsg(rep);
  12.635 +  if (msg)
  12.636 +    return msg;
  12.637 +
  12.638 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
  12.639 +
  12.640 +  strncpy(XenBus_WatchEntries[i].Path, Path, 128);
  12.641 +  XenBus_WatchEntries[i].ServiceRoutine = ServiceRoutine;
  12.642 +  XenBus_WatchEntries[i].ServiceContext = ServiceContext;
  12.643 +  XenBus_WatchEntries[i].Count = 0;
  12.644 +  XenBus_WatchEntries[i].Active = 1;
  12.645 +
  12.646 +  //KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
  12.647 +
  12.648 +  return NULL;
  12.649 +}
  12.650 +
  12.651 +char *
  12.652 +XenBus_RemWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
  12.653 +{
  12.654 +  struct xsd_sockmsg *rep;
  12.655 +  char *msg;
  12.656 +  int i;
  12.657 +  char Token[20];
  12.658 +  struct write_req req[2];
  12.659 +
  12.660 +  //KdPrint((__DRIVER_NAME " --> XenBus_RemWatch\n"));
  12.661 +
  12.662 +  // check that Path < 128 chars
  12.663 +
  12.664 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
  12.665 +    if (XenBus_WatchEntries[i].Active == 1 && strcmp(XenBus_WatchEntries[i].Path, Path) == 0 && XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine && XenBus_WatchEntries[i].ServiceContext == ServiceContext)
  12.666 +      break;
  12.667 +  }
  12.668 +
  12.669 +  if (i == MAX_WATCH_ENTRIES)
  12.670 +  {
  12.671 +    KdPrint((__DRIVER_NAME "     Watch not set - can't remove\n"));
  12.672 +    return NULL;
  12.673 +  }
  12.674 +
  12.675 +  req[0].data = Path;
  12.676 +  req[0].len = strlen(Path) + 1;
  12.677 +
  12.678 +  RtlStringCbPrintfA(Token, ARRAY_SIZE(Token), "%d", i);
  12.679 +  req[1].data = Token;
  12.680 +  req[1].len = strlen(Token) + 1;
  12.681 +
  12.682 +  rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
  12.683 +
  12.684 +  msg = errmsg(rep);
  12.685 +  if (msg)
  12.686 +    return msg;
  12.687 +
  12.688 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
  12.689 +
  12.690 +  XenBus_WatchEntries[i].Active = 0;
  12.691 +
  12.692 +  //KdPrint((__DRIVER_NAME " <-- XenBus_RemWatch\n"));
  12.693 +
  12.694 +  return NULL;
  12.695 +}
  12.696 +
  12.697 +
  12.698 +char *
  12.699 +XenBus_StartTransaction(xenbus_transaction_t *xbt)
  12.700 +{
  12.701 +  /* xenstored becomes angry if you send a length 0 message, so just
  12.702 +     shove a nul terminator on the end */
  12.703 +  struct write_req req = { "", 1};
  12.704 +  struct xsd_sockmsg *rep;
  12.705 +  char *err;
  12.706 +
  12.707 +  rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
  12.708 +  err = errmsg(rep);
  12.709 +  if (err)
  12.710 +    return err;
  12.711 +  *xbt = atoi((char *)(rep + 1));
  12.712 +  //sscanf((char *)(rep + 1), "%u", xbt);
  12.713 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
  12.714 +  return NULL;
  12.715 +}
  12.716 +
  12.717 +char *
  12.718 +XenBus_EndTransaction(xenbus_transaction_t t, int abort, int *retry)
  12.719 +{
  12.720 +  struct xsd_sockmsg *rep;
  12.721 +  struct write_req req;
  12.722 +  char *err;
  12.723 +
  12.724 +  *retry = 0;
  12.725 +
  12.726 +  req.data = abort ? "F" : "T";
  12.727 +  req.len = 2;
  12.728 +  rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
  12.729 +  err = errmsg(rep);
  12.730 +  if (err) {
  12.731 +    if (!strcmp(err, "EAGAIN")) {
  12.732 +      *retry = 1;
  12.733 +      ExFreePoolWithTag(err, XENPCI_POOL_TAG);
  12.734 +      return NULL;
  12.735 +    } else {
  12.736 +      return err;
  12.737 +    }
  12.738 +  }
  12.739 +  ExFreePoolWithTag(rep, XENPCI_POOL_TAG);
  12.740 +  return NULL;
  12.741 +}
  12.742 +/*
  12.743 +void
  12.744 +XenBus_ThreadProc(PVOID StartContext)
  12.745 +{
  12.746 +  char *response;
  12.747 +
  12.748 +  //KdPrint((__DRIVER_NAME " --> XenBus_ThreadProc\n"));
  12.749 +
  12.750 +  //do_ls_test("device");
  12.751 +
  12.752 +//  do_ls_test("local");
  12.753 +
  12.754 +//  do_ls_test("control");
  12.755 +
  12.756 +//  do_ls_test(".");
  12.757 +
  12.758 +  response = XenBus_AddWatch(XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, NULL);
  12.759 +
  12.760 +  //KdPrint((__DRIVER_NAME " <-- watch response = '%s'\n", response)); 
  12.761 +
  12.762 +  //KdPrint((__DRIVER_NAME " <-- XenBus_ThreadProc\n"));
  12.763 +}
  12.764 +*/
  12.765 +
  12.766 +static BOOLEAN
  12.767 +XenBus_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
  12.768 +{
  12.769 +  UNREFERENCED_PARAMETER(Interrupt);
  12.770 +  UNREFERENCED_PARAMETER(ServiceContext);
  12.771 +
  12.772 +  //KdPrint((__DRIVER_NAME " --> XenBus_Interrupt (Count = %d)\n", ReadThreadSetCount++));
  12.773 +
  12.774 +  KeSetEvent(&XenBus_ReadThreadEvent, 1, FALSE);
  12.775 +
  12.776 +  //KdPrint((__DRIVER_NAME " <-- XenBus_Interrupt\n"));
  12.777 +
  12.778 +  return TRUE;
  12.779 +}
  12.780 +
  12.781 +char *
  12.782 +XenBus_Printf(xenbus_transaction_t xbt, const char *path, const char *fmt, ...)
  12.783 +{
  12.784 +  va_list ap;
  12.785 +  char buf[1024];
  12.786 +
  12.787 +  va_start(ap, fmt);
  12.788 +  RtlStringCbVPrintfA(buf, ARRAY_SIZE(buf), fmt, ap);
  12.789 +  va_end(ap);
  12.790 +  return XenBus_Write(xbt, path, buf);
  12.791 +}
  12.792 \ No newline at end of file
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xenpci/xenbus.h	Sat Nov 10 14:40:56 2007 +1100
    13.3 @@ -0,0 +1,188 @@
    13.4 +/*
    13.5 +PV Drivers for Windows Xen HVM Domains
    13.6 +Copyright (C) 2007 James Harper
    13.7 +
    13.8 +This program is free software; you can redistribute it and/or
    13.9 +modify it under the terms of the GNU General Public License
   13.10 +as published by the Free Software Foundation; either version 2
   13.11 +of the License, or (at your option) any later version.
   13.12 +
   13.13 +This program is distributed in the hope that it will be useful,
   13.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.16 +GNU General Public License for more details.
   13.17 +
   13.18 +You should have received a copy of the GNU General Public License
   13.19 +along with this program; if not, write to the Free Software
   13.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   13.21 +*/
   13.22 +
   13.23 +#if !defined(_XENBUS_H_)
   13.24 +#define _XENBUS_H_
   13.25 +
   13.26 +#include <ntddk.h>
   13.27 +#include <wdm.h>
   13.28 +#include <wdf.h>
   13.29 +#include <initguid.h>
   13.30 +
   13.31 +#define NTSTRSAFE_LIB
   13.32 +#include <ntstrsafe.h>
   13.33 +
   13.34 +#define __XEN_INTERFACE_VERSION__ 0x00030205
   13.35 +#define __i386__
   13.36 +typedef signed char int8_t;
   13.37 +typedef unsigned char uint8_t;
   13.38 +typedef SHORT int16_t;
   13.39 +typedef USHORT uint16_t;
   13.40 +typedef LONG int32_t;
   13.41 +typedef ULONG uint32_t;
   13.42 +typedef ULONGLONG uint64_t;
   13.43 +typedef unsigned long pgentry_t;
   13.44 +
   13.45 +#define _PAGE_PRESENT  0x001UL
   13.46 +#define _PAGE_RW       0x002UL
   13.47 +#define _PAGE_USER     0x004UL
   13.48 +#define _PAGE_PWT      0x008UL
   13.49 +#define _PAGE_PCD      0x010UL
   13.50 +#define _PAGE_ACCESSED 0x020UL
   13.51 +#define _PAGE_DIRTY    0x040UL
   13.52 +#define _PAGE_PAT      0x080UL
   13.53 +#define _PAGE_PSE      0x080UL
   13.54 +#define _PAGE_GLOBAL   0x100UL
   13.55 +
   13.56 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   13.57 +
   13.58 +#include <xen.h>
   13.59 +#include <event_channel.h>
   13.60 +#include <hvm/params.h>
   13.61 +#include <hvm/hvm_op.h>
   13.62 +#include <evtchn_public.h>
   13.63 +#include <evtchn_store_public.h>
   13.64 +
   13.65 +//{C828ABE9-14CA-4445-BAA6-82C2376C6518}
   13.66 +DEFINE_GUID( GUID_XENBUS_DEVCLASS, 0xC828ABE9, 0x14CA, 0x4445, 0xBA, 0xA6, 0x82, 0xC2, 0x37, 0x6C, 0x65, 0x18);
   13.67 +
   13.68 +#define __DRIVER_NAME "XenBus"
   13.69 +#define XENBUS_POOL_TAG (ULONG) 'XenP'
   13.70 +
   13.71 +#define NR_RESERVED_ENTRIES 8
   13.72 +#define NR_GRANT_FRAMES 4
   13.73 +#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
   13.74 +
   13.75 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
   13.76 +
   13.77 +typedef struct _XENBUS_IDENTIFICATION_DESCRIPTION
   13.78 +{
   13.79 +  WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Header;
   13.80 +  UNICODE_STRING DeviceType;
   13.81 +  ULONG DeviceIndex;
   13.82 +} XENBUS_IDENTIFICATION_DESCRIPTION, *PXENBUS_IDENTIFICATION_DESCRIPTION;
   13.83 +
   13.84 +
   13.85 +typedef struct {
   13.86 +  WDFQUEUE          IoDefaultQueue;
   13.87 +  WDFINTERRUPT      Interrupt;
   13.88 +  PULONG            IoBaseAddress;
   13.89 +  ULONG             IoRange;
   13.90 +} XENBUS_DEVICE_DATA, *PXENBUS_DEVICE_DATA;
   13.91 +
   13.92 +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENBUS_DEVICE_DATA, GetDeviceData);
   13.93 +
   13.94 +
   13.95 +void
   13.96 +grant_table_init();
   13.97 +
   13.98 +typedef unsigned long xenbus_transaction_t;
   13.99 +typedef uint32_t XENSTORE_RING_IDX;
  13.100 +
  13.101 +/*
  13.102 +enum xsd_sockmsg_type
  13.103 +{
  13.104 +    XS_DEBUG,
  13.105 +    XS_DIRECTORY,
  13.106 +    XS_READ,
  13.107 +    XS_GET_PERMS,
  13.108 +    XS_WATCH,
  13.109 +    XS_UNWATCH,
  13.110 +    XS_TRANSACTION_START,
  13.111 +    XS_TRANSACTION_END,
  13.112 +    XS_INTRODUCE,
  13.113 +    XS_RELEASE,
  13.114 +    XS_GET_DOMAIN_PATH,
  13.115 +    XS_WRITE,
  13.116 +    XS_MKDIR,
  13.117 +    XS_RM,
  13.118 +    XS_SET_PERMS,
  13.119 +    XS_WATCH_EVENT,
  13.120 +    XS_ERROR,
  13.121 +    XS_IS_DOMAIN_INTRODUCED,
  13.122 +    XS_RESUME
  13.123 +};
  13.124 +
  13.125 +struct xsd_sockmsg
  13.126 +{
  13.127 +    uint32_t type;  /* XS_??? */
  13.128 +    uint32_t req_id;/* Request identifier, echoed in daemon's response.  */
  13.129 +    uint32_t tx_id; /* Transaction id (0 if not related to a transaction). */
  13.130 +    uint32_t len;   /* Length of data following this. */
  13.131 +
  13.132 +    /* Generally followed by nul-terminated string(s). */
  13.133 +};
  13.134 +*/
  13.135 +
  13.136 +#define XBT_NIL ((xenbus_transaction_t)0)
  13.137 +char *
  13.138 +XenBus_Read(xenbus_transaction_t xbt, const char *path, char **value);
  13.139 +char *
  13.140 +XenBus_Write(xenbus_transaction_t xbt, const char *path, const char *value);
  13.141 +char *
  13.142 +XenBus_StartTransaction(xenbus_transaction_t *xbt);
  13.143 +char *
  13.144 +XenBus_EndTransaction(xenbus_transaction_t t, int abort, int *retry);
  13.145 +
  13.146 +
  13.147 +char *
  13.148 +xenbus_watch_path(xenbus_transaction_t xbt, const char *path);
  13.149 +void
  13.150 +wait_for_watch(void);
  13.151 +char *
  13.152 +xenbus_wait_for_value(const char*,const char*);
  13.153 +
  13.154 +char *
  13.155 +xenbus_rm(xenbus_transaction_t xbt, const char *path);
  13.156 +char *
  13.157 +xenbus_ls(xenbus_transaction_t xbt, const char *prefix, char ***contents);
  13.158 +char *
  13.159 +xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value);
  13.160 +char *
  13.161 +xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm);
  13.162 +char *
  13.163 +xenbus_transaction_start(xenbus_transaction_t *xbt);
  13.164 +char *
  13.165 +xenbus_transaction_end(xenbus_transaction_t, int abort, int *retry);
  13.166 +int
  13.167 +xenbus_read_integer(char *path);
  13.168 +void
  13.169 +xenbus_irq();
  13.170 +
  13.171 +NTSTATUS
  13.172 +XenBus_Init();
  13.173 +NTSTATUS
  13.174 +XenBus_Close();
  13.175 +
  13.176 +PVOID
  13.177 +map_frames(PULONG f, ULONG n);
  13.178 +
  13.179 +//extern XEN_IFACE_EVTCHN EvtchnInterface;
  13.180 +//extern XEN_IFACE_EVTCHN_STORE EvtchnStoreInterface;
  13.181 +
  13.182 +
  13.183 +/*
  13.184 +void
  13.185 +do_ls_test(const char *pre);
  13.186 +*/
  13.187 +
  13.188 +void
  13.189 +XenBus_ThreadProc(PVOID StartContext);
  13.190 +
  13.191 +#endif
  13.192 \ No newline at end of file
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xenpci/xenpci.c	Sat Nov 10 14:40:56 2007 +1100
    14.3 @@ -0,0 +1,1070 @@
    14.4 +/*
    14.5 +PV Drivers for Windows Xen HVM Domains
    14.6 +Copyright (C) 2007 James Harper
    14.7 +
    14.8 +This program is free software; you can redistribute it and/or
    14.9 +modify it under the terms of the GNU General Public License
   14.10 +as published by the Free Software Foundation; either version 2
   14.11 +of the License, or (at your option) any later version.
   14.12 +
   14.13 +This program is distributed in the hope that it will be useful,
   14.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.16 +GNU General Public License for more details.
   14.17 +
   14.18 +You should have received a copy of the GNU General Public License
   14.19 +along with this program; if not, write to the Free Software
   14.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   14.21 +*/
   14.22 +
   14.23 +#include "xenpci.h"
   14.24 +#include "hypercall.h"
   14.25 +#include <stdlib.h>
   14.26 +
   14.27 +#define SHUTDOWN_PATH "control/shutdown"
   14.28 +
   14.29 +DRIVER_INITIALIZE DriverEntry;
   14.30 +static NTSTATUS
   14.31 +XenPCI_AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit);
   14.32 +static NTSTATUS
   14.33 +XenPCI_PrepareHardware(WDFDEVICE hDevice, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated);
   14.34 +static NTSTATUS
   14.35 +XenPCI_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated);
   14.36 +static NTSTATUS
   14.37 +XenPCI_D0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
   14.38 +static NTSTATUS
   14.39 +XenPCI_D0EntryPostInterruptsEnabled(WDFDEVICE  Device, WDF_POWER_DEVICE_STATE PreviousState);
   14.40 +static NTSTATUS
   14.41 +XenPCI_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
   14.42 +static NTSTATUS
   14.43 +XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE  Device, WDF_POWER_DEVICE_STATE TargetState);
   14.44 +static VOID
   14.45 +XenPCI_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
   14.46 +static NTSTATUS
   14.47 +XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
   14.48 +static NTSTATUS
   14.49 +XenPCI_InterruptDisable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
   14.50 +static NTSTATUS
   14.51 +XenPCI_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit);
   14.52 +static NTSTATUS
   14.53 +XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
   14.54 +static NTSTATUS
   14.55 +XenPCI_FilterRemoveResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
   14.56 +static NTSTATUS
   14.57 +XenPCI_FilterAddResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList);
   14.58 +static NTSTATUS
   14.59 +XenPCI_RemoveAddedResources(WDFDEVICE Device, WDFCMRESLIST ResourcesRaw, WDFCMRESLIST ResourcesTranslated);
   14.60 +
   14.61 +static VOID
   14.62 +XenBus_ShutdownHandler(char *Path, PVOID Data);
   14.63 +static VOID
   14.64 +XenPCI_XenBusWatchHandler(char *Path, PVOID Data);
   14.65 +
   14.66 +#ifdef ALLOC_PRAGMA
   14.67 +#pragma alloc_text (INIT, DriverEntry)
   14.68 +#pragma alloc_text (PAGE, XenPCI_AddDevice)
   14.69 +#endif
   14.70 +
   14.71 +shared_info_t *shared_info_area;
   14.72 +static ULONG irqNumber = 0;
   14.73 +
   14.74 +static BOOLEAN AutoEnumerate;
   14.75 +
   14.76 +static WDFDEVICE Device;
   14.77 +
   14.78 +NTSTATUS
   14.79 +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
   14.80 +{
   14.81 +  WDF_DRIVER_CONFIG config;
   14.82 +  NTSTATUS status;
   14.83 +  UNICODE_STRING RegKeyName;
   14.84 +  UNICODE_STRING RegValueName;
   14.85 +  HANDLE RegHandle;
   14.86 +  OBJECT_ATTRIBUTES RegObjectAttributes;
   14.87 +  char Buf[200];
   14.88 +  ULONG BufLen = 200;
   14.89 +  PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
   14.90 +  int State = 0;
   14.91 +  int StartPos = 0;
   14.92 +  WCHAR *SystemStartOptions;
   14.93 +  size_t SystemStartOptionsLen;
   14.94 +  size_t i;
   14.95 +
   14.96 +  //KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
   14.97 +
   14.98 +  RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
   14.99 +  InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
  14.100 +  status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
  14.101 +  if(!NT_SUCCESS(status))
  14.102 +  {
  14.103 +    KdPrint((__DRIVER_NAME "     ZwOpenKey returned %08x\n", status));
  14.104 +  }
  14.105 +
  14.106 +  RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
  14.107 +  status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
  14.108 +  if(!NT_SUCCESS(status))
  14.109 +  {
  14.110 +    KdPrint((__DRIVER_NAME "     ZwQueryKeyValue returned %08x\n", status));
  14.111 +  }
  14.112 +  //KdPrint((__DRIVER_NAME "     BufLen = %d\n", BufLen));
  14.113 +  KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
  14.114 +  KdPrint((__DRIVER_NAME "     Buf = %ws\n", KeyPartialValue->Data));
  14.115 +  SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
  14.116 +
  14.117 +  AutoEnumerate = FALSE;
  14.118 +
  14.119 +  RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
  14.120 +
  14.121 +  for (i = 0; i <= SystemStartOptionsLen/2; i++)
  14.122 +  {
  14.123 +    //KdPrint((__DRIVER_NAME "     pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
  14.124 +    
  14.125 +    switch (State)
  14.126 +    {
  14.127 +    case 0:
  14.128 +      if (SystemStartOptions[i] == L'G')
  14.129 +      {
  14.130 +        StartPos = i;
  14.131 +        State = 2;
  14.132 +      } else if (SystemStartOptions[i] != L' ')
  14.133 +      {
  14.134 +        State = 1;
  14.135 +      }
  14.136 +      break;
  14.137 +    case 1:
  14.138 +      if (SystemStartOptions[i] == L' ')
  14.139 +        State = 0;
  14.140 +      break;
  14.141 +    case 2:
  14.142 +      if (SystemStartOptions[i] == L'P')
  14.143 +        State = 3;
  14.144 +      else
  14.145 +        State = 0;
  14.146 +      break;
  14.147 +    case 3:
  14.148 +      if (SystemStartOptions[i] == L'L')
  14.149 +        State = 4;
  14.150 +      else
  14.151 +        State = 0;
  14.152 +      break;
  14.153 +    case 4:
  14.154 +      if (SystemStartOptions[i] == L'P')
  14.155 +        State = 5;
  14.156 +      else
  14.157 +        State = 0;
  14.158 +      break;
  14.159 +    case 5:
  14.160 +      if (SystemStartOptions[i] == L'V')
  14.161 +        State = 6;
  14.162 +      else
  14.163 +        State = 0;
  14.164 +      break;
  14.165 +    case 6:
  14.166 +      if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
  14.167 +        AutoEnumerate = TRUE;
  14.168 +      State = 0;
  14.169 +      break;
  14.170 +    }
  14.171 +  }
  14.172 +
  14.173 +  KdPrint((__DRIVER_NAME "     AutoEnumerate = %d\n", AutoEnumerate));
  14.174 +
  14.175 +
  14.176 +  WDF_DRIVER_CONFIG_INIT(&config, XenPCI_AddDevice);
  14.177 +  status = WdfDriverCreate(
  14.178 +                      DriverObject,
  14.179 +                      RegistryPath,
  14.180 +                      WDF_NO_OBJECT_ATTRIBUTES,
  14.181 +                      &config,
  14.182 +                      WDF_NO_HANDLE);
  14.183 +  if(!NT_SUCCESS(status))
  14.184 +  {
  14.185 +    //KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
  14.186 +  }
  14.187 +
  14.188 +  //KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
  14.189 +
  14.190 +  return status;
  14.191 +}
  14.192 +
  14.193 +static void WRMSR(unsigned int msr, ULONGLONG val)
  14.194 +{
  14.195 +  ULONG lo, hi;
  14.196 +  lo = (ULONG)val;
  14.197 +  hi = (ULONG)(val >> 32);
  14.198 +  __asm  {
  14.199 +    mov ecx, msr
  14.200 +    mov eax, lo
  14.201 +    mov edx, hi
  14.202 +    wrmsr
  14.203 +  }
  14.204 +}
  14.205 +
  14.206 +static int
  14.207 +get_hypercall_stubs()
  14.208 +{
  14.209 +  DWORD32 cpuid_output[4];
  14.210 +  char xensig[13];
  14.211 +  ULONG i;
  14.212 +  ULONG pages;
  14.213 +  ULONG msr;  
  14.214 +
  14.215 +  __cpuid(cpuid_output, 0x40000000);
  14.216 +  *(ULONG*)(xensig + 0) = cpuid_output[1];
  14.217 +  *(ULONG*)(xensig + 4) = cpuid_output[2];
  14.218 +  *(ULONG*)(xensig + 8) = cpuid_output[3];
  14.219 +  xensig[12] = '\0';
  14.220 +  KdPrint((__DRIVER_NAME " Xen Signature = %s, EAX = 0x%08x\n", xensig, cpuid_output[0]));
  14.221 +
  14.222 +  __cpuid(cpuid_output, 0x40000002);
  14.223 +  pages = cpuid_output[0];
  14.224 +  msr = cpuid_output[1];
  14.225 +  //KdPrint((__DRIVER_NAME " Hypercall area is %u pages.\n", pages));
  14.226 +
  14.227 +  hypercall_stubs = ExAllocatePoolWithTag(NonPagedPool, pages * PAGE_SIZE, XENPCI_POOL_TAG);
  14.228 +  //KdPrint((__DRIVER_NAME " Hypercall area at %08x\n", hypercall_stubs));
  14.229 +
  14.230 +  if (hypercall_stubs == NULL)
  14.231 +    return 1;
  14.232 +  for (i = 0; i < pages; i++) {
  14.233 +    ULONG pfn;
  14.234 +    //pfn = vmalloc_to_pfn((char *)hypercall_stubs + i * PAGE_SIZE);
  14.235 +    pfn = (ULONG)(MmGetPhysicalAddress(hypercall_stubs + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
  14.236 +    //KdPrint((__DRIVER_NAME " pfn = %08X\n", pfn));
  14.237 +    WRMSR(msr, ((ULONGLONG)pfn << PAGE_SHIFT) + i);
  14.238 +  }
  14.239 +  return STATUS_SUCCESS;
  14.240 +}
  14.241 +
  14.242 +static ULONG PciBusNumber;
  14.243 +static USHORT PciFunctionNumber, PciDeviceNumber;
  14.244 +static USHORT PciPinNumber;
  14.245 +
  14.246 +static WDFINTERRUPT XenInterrupt;
  14.247 +
  14.248 +static PHYSICAL_ADDRESS platform_mmio_addr;
  14.249 +static ULONG platform_mmio_orig_len;
  14.250 +static ULONG platform_mmio_len;
  14.251 +static ULONG platform_mmio_alloc;
  14.252 +
  14.253 +PHYSICAL_ADDRESS
  14.254 +XenPCI_AllocMMIO(ULONG len)
  14.255 +{
  14.256 +  PHYSICAL_ADDRESS addr;
  14.257 +
  14.258 +  addr = platform_mmio_addr;
  14.259 +  addr.QuadPart += platform_mmio_alloc;
  14.260 +  platform_mmio_alloc += len;
  14.261 +
  14.262 +  return addr;
  14.263 +}
  14.264 +
  14.265 +static int
  14.266 +init_xen_info()
  14.267 +{
  14.268 +  struct xen_add_to_physmap xatp;
  14.269 +  int ret;
  14.270 +  PHYSICAL_ADDRESS shared_info_area_unmapped;
  14.271 +
  14.272 +  //setup_xen_features();
  14.273 +  //KdPrint((__DRIVER_NAME " init_xen_info Hypercall area at %08x\n", hypercall_stubs));
  14.274 +
  14.275 +  shared_info_area_unmapped = XenPCI_AllocMMIO(PAGE_SIZE);
  14.276 +  xatp.domid = DOMID_SELF;
  14.277 +  xatp.idx = 0;
  14.278 +  xatp.space = XENMAPSPACE_shared_info;
  14.279 +  xatp.gpfn = (xen_pfn_t)(shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
  14.280 +  ret = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
  14.281 +  //KdPrint((__DRIVER_NAME " ret = %d\n", ret));
  14.282 +
  14.283 +  shared_info_area = (shared_info_t *)MmMapIoSpace(shared_info_area_unmapped, PAGE_SIZE, MmNonCached);
  14.284 +
  14.285 +  return 0;
  14.286 +}
  14.287 +
  14.288 +static PKINTERRUPT interrupt;
  14.289 +
  14.290 +static int
  14.291 +set_callback_irq(ULONGLONG irq)
  14.292 +{
  14.293 +  struct xen_hvm_param a;
  14.294 +  int retval;
  14.295 +
  14.296 +  //KdPrint((__DRIVER_NAME " --> set_callback_irq\n"));
  14.297 +  a.domid = DOMID_SELF;
  14.298 +  a.index = HVM_PARAM_CALLBACK_IRQ;
  14.299 +  a.value = irq;
  14.300 +  retval = HYPERVISOR_hvm_op(HVMOP_set_param, &a);
  14.301 +  //KdPrint((__DRIVER_NAME " HYPERVISOR_hvm_op retval = %d\n", retval));
  14.302 +  //KdPrint((__DRIVER_NAME " <-- set_callback_irq\n"));
  14.303 +  return retval;
  14.304 +}
  14.305 +
  14.306 +static NTSTATUS
  14.307 +XenPCI_AddDevice(
  14.308 +    IN WDFDRIVER Driver,
  14.309 +    IN PWDFDEVICE_INIT DeviceInit
  14.310 +    )
  14.311 +{
  14.312 +  NTSTATUS status;
  14.313 +  WDF_CHILD_LIST_CONFIG config;
  14.314 +  PXENPCI_DEVICE_DATA devData = NULL;
  14.315 +  WDF_OBJECT_ATTRIBUTES attributes;
  14.316 +  WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
  14.317 +  WDF_IO_QUEUE_CONFIG ioQConfig;
  14.318 +  WDF_INTERRUPT_CONFIG interruptConfig;
  14.319 +  PNP_BUS_INFORMATION busInfo;
  14.320 +  BUS_INTERFACE_STANDARD BusInterface;
  14.321 +  WDFDEVICE Parent;
  14.322 +
  14.323 +  //PDEVICE_OBJECT pdo;
  14.324 +  //ULONG propertyAddress, length;
  14.325 +
  14.326 +  UNREFERENCED_PARAMETER(Driver);
  14.327 +
  14.328 +  //KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
  14.329 +
  14.330 +  // get PDO
  14.331 +  // get parent (should be PCI bus) (WdfPdoGetParent)
  14.332 +  // 
  14.333 +
  14.334 +  WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
  14.335 +  WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(XENPCI_IDENTIFICATION_DESCRIPTION), XenPCI_ChildListCreateDevice);
  14.336 +  WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES);
  14.337 +
  14.338 +//  WDF_FDO_EVENT_CALLBACKS_INIT(&FdoCallbacks);
  14.339 +//  FdoCallbacks.EvtDeviceFilterRemoveResourceRequirements = XenPCI_FilterRemoveResourceRequirements;
  14.340 +//  FdoCallbacks.EvtDeviceFilterAddResourceRequirements = XenPCI_FilterAddResourceRequirements;
  14.341 +//  FdoCallbacks.EvtDeviceRemoveAddedResources = XenPCI_RemoveAddedResources;
  14.342 +//  WdfFdoInitSetEventCallbacks(DeviceInit, &FdoCallbacks);
  14.343 +
  14.344 +  /*set the callback functions that will be 
  14.345 +  executed on PNP and Power events*/
  14.346 +  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
  14.347 +  pnpPowerCallbacks.EvtDevicePrepareHardware = XenPCI_PrepareHardware;
  14.348 +  pnpPowerCallbacks.EvtDeviceReleaseHardware = XenPCI_ReleaseHardware;
  14.349 +  pnpPowerCallbacks.EvtDeviceD0Entry = XenPCI_D0Entry;
  14.350 +  pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPCI_D0EntryPostInterruptsEnabled;
  14.351 +  pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPCI_D0ExitPreInterruptsDisabled;
  14.352 +  pnpPowerCallbacks.EvtDeviceD0Exit = XenPCI_D0Exit;
  14.353 +  WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
  14.354 +
  14.355 +  WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
  14.356 +
  14.357 +  /*initialize storage for the device context*/
  14.358 +  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENPCI_DEVICE_DATA);
  14.359 +
  14.360 +  /*create a device instance.*/
  14.361 +  status = WdfDeviceCreate(&DeviceInit, 
  14.362 +           &attributes, &Device);  
  14.363 +  if(!NT_SUCCESS(status))
  14.364 +  {
  14.365 +    KdPrint((__DRIVER_NAME "     WdfDeviceCreate failed with status 0x%08x\n", status));
  14.366 +    return status;
  14.367 +  }
  14.368 +
  14.369 +  status = WdfFdoQueryForInterface(Device, &GUID_BUS_INTERFACE_STANDARD, (PINTERFACE) &BusInterface, sizeof(BUS_INTERFACE_STANDARD), 1, NULL);
  14.370 +  if(!NT_SUCCESS(status))
  14.371 +  {
  14.372 +    KdPrint((__DRIVER_NAME "     WdfFdoQueryForInterface (BusInterface) failed with status 0x%08x\n", status));
  14.373 +  }
  14.374 +
  14.375 +  //BusInterface.GetBusData(NULL, PCI_WHICHSPACE_CONFIG, buf, 
  14.376 +
  14.377 +  
  14.378 +  busInfo.BusTypeGuid = GUID_XENPCI_DEVCLASS;
  14.379 +  busInfo.LegacyBusType = PNPBus;
  14.380 +  busInfo.BusNumber = 0;
  14.381 +
  14.382 +  WdfDeviceSetBusInformationForChildren(Device, &busInfo);
  14.383 +
  14.384 +  /*create the default IO queue. this one will 
  14.385 +  be used for all requests*/
  14.386 +  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQConfig,
  14.387 +                                WdfIoQueueDispatchSequential);
  14.388 +  ioQConfig.EvtIoDefault = XenPCI_IoDefault;
  14.389 +  status = WdfIoQueueCreate(Device, &ioQConfig,
  14.390 +                            WDF_NO_OBJECT_ATTRIBUTES,
  14.391 +                            &devData->IoDefaultQueue);
  14.392 +  if(!NT_SUCCESS(status))
  14.393 +  {
  14.394 +    KdPrint((__DRIVER_NAME "     WdfIoQueueCreate failed with status 0x%08x\n", status));
  14.395 +    return status;
  14.396 +  }
  14.397 +
  14.398 +/*
  14.399 +  status = WdfDeviceCreateDeviceInterface(Device, &GUID_INTERFACE_XENPCI, NULL);
  14.400 +  if(!NT_SUCCESS(status))
  14.401 +  {
  14.402 +    KdPrint((__DRIVER_NAME "WdfDeviceCreateDeviceInterface failed with status 0x%08x\n", status));
  14.403 +    return status;
  14.404 +  }
  14.405 +*/
  14.406 +
  14.407 +  WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, EvtChn_Interrupt, NULL); //EvtChn_InterruptDpc);
  14.408 +  interruptConfig.EvtInterruptEnable = XenPCI_InterruptEnable;
  14.409 +  interruptConfig.EvtInterruptDisable = XenPCI_InterruptDisable;
  14.410 +  status = WdfInterruptCreate(Device, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &XenInterrupt);
  14.411 +  if (!NT_SUCCESS (status))
  14.412 +  {
  14.413 +    KdPrint((__DRIVER_NAME "WdfInterruptCreate failed 0x%08x\n", status));
  14.414 +    return status;
  14.415 +  }
  14.416 +
  14.417 +  //KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
  14.418 +  return status;
  14.419 +}
  14.420 +
  14.421 +static NTSTATUS
  14.422 +XenPCI_PrepareHardware(
  14.423 +  IN WDFDEVICE    Device,
  14.424 +  IN WDFCMRESLIST ResourceList,
  14.425 +  IN WDFCMRESLIST ResourceListTranslated)
  14.426 +{
  14.427 +  NTSTATUS status = STATUS_SUCCESS;
  14.428 +  PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
  14.429 +  ULONG i;  
  14.430 +
  14.431 +  UNREFERENCED_PARAMETER(Device);
  14.432 +
  14.433 +  //KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
  14.434 +
  14.435 +  for (i = 0; i < WdfCmResourceListGetCount(ResourceList); i++)
  14.436 +  {
  14.437 +    descriptor = WdfCmResourceListGetDescriptor(ResourceList, i);
  14.438 +    if(!descriptor)
  14.439 +      continue;
  14.440 +    switch (descriptor->Type)
  14.441 +    {
  14.442 +    case CmResourceTypeInterrupt:
  14.443 +      irqNumber = descriptor->u.Interrupt.Vector;
  14.444 +      break;
  14.445 +    }
  14.446 +  }
  14.447 +
  14.448 +  //KdPrint((__DRIVER_NAME " GSI = %d\n", irqNumber));
  14.449 +
  14.450 +  //KdPrint((__DRIVER_NAME " ResourceListTranslated\n"));
  14.451 +  for (i = 0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++)
  14.452 +  {
  14.453 +    descriptor = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);
  14.454 +    if(!descriptor)
  14.455 +    {
  14.456 +      KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware (No descriptor)\n"));
  14.457 +      return STATUS_DEVICE_CONFIGURATION_ERROR;
  14.458 +    }
  14.459 +    switch (descriptor->Type) {
  14.460 +    case CmResourceTypePort:
  14.461 +      //KdPrint((__DRIVER_NAME "     I/O mapped CSR: (%x) Length: (%d)\n", descriptor->u.Port.Start.LowPart, descriptor->u.Port.Length));
  14.462 +//      deviceData->IoBaseAddress = ULongToPtr(descriptor->u.Port.Start.LowPart);
  14.463 +//      deviceData->IoRange = descriptor->u.Port.Length;
  14.464 +      break;
  14.465 +    case CmResourceTypeMemory:
  14.466 +      KdPrint((__DRIVER_NAME "     Memory mapped CSR:(%x:%x) Length:(%d)\n", descriptor->u.Memory.Start.LowPart, descriptor->u.Memory.Start.HighPart, descriptor->u.Memory.Length));
  14.467 +      platform_mmio_addr = descriptor->u.Memory.Start; //(ULONG)MmMapIoSpace(descriptor->u.Memory.Start, descriptor->u.Memory.Length, MmNonCached);
  14.468 +      platform_mmio_len = descriptor->u.Memory.Length;
  14.469 +      platform_mmio_alloc = 0;
  14.470 +      break;
  14.471 +    case CmResourceTypeInterrupt:
  14.472 +      //KdPrint((__DRIVER_NAME "     Interrupt level: 0x%0x, Vector: 0x%0x\n", descriptor->u.Interrupt.Level, descriptor->u.Interrupt.Vector));
  14.473 +      break;
  14.474 +    case CmResourceTypeDevicePrivate:
  14.475 +      //KdPrint((__DRIVER_NAME "     Private Data: 0x%02x 0x%02x 0x%02x\n", descriptor->u.DevicePrivate.Data[0], descriptor->u.DevicePrivate.Data[1], descriptor->u.DevicePrivate.Data[2] ));
  14.476 +      break;
  14.477 +    default:
  14.478 +      //KdPrint((__DRIVER_NAME "     Unhandled resource type (0x%x)\n", descriptor->Type));
  14.479 +      break;
  14.480 +    }
  14.481 +  }
  14.482 +
  14.483 +  get_hypercall_stubs();
  14.484 +
  14.485 +  init_xen_info();
  14.486 +
  14.487 +  GntTbl_Init();
  14.488 +
  14.489 +  EvtChn_Init();
  14.490 +
  14.491 +  set_callback_irq(irqNumber);
  14.492 +
  14.493 +  XenBus_Init();
  14.494 +
  14.495 +  //KdPrint((__DRIVER_NAME " upcall_pending = %d\n", shared_info_area->vcpu_info[0].evtchn_upcall_pending));
  14.496 +
  14.497 +  shared_info_area->vcpu_info[0].evtchn_upcall_mask = 0;
  14.498 +
  14.499 +  //xen_reboot_init();
  14.500 +
  14.501 +  //KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
  14.502 +
  14.503 +  return status;
  14.504 +}
  14.505 +
  14.506 +static NTSTATUS
  14.507 +XenPCI_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
  14.508 +{
  14.509 +  UNREFERENCED_PARAMETER(Device);
  14.510 +  UNREFERENCED_PARAMETER(ResourcesTranslated);
  14.511 +
  14.512 +  return STATUS_SUCCESS;
  14.513 +}
  14.514 +
  14.515 +static NTSTATUS
  14.516 +XenPCI_D0Entry(
  14.517 +    IN WDFDEVICE  Device,
  14.518 +    IN WDF_POWER_DEVICE_STATE PreviousState
  14.519 +    )
  14.520 +{
  14.521 +  NTSTATUS status = STATUS_SUCCESS;
  14.522 +
  14.523 +  UNREFERENCED_PARAMETER(Device);
  14.524 +  UNREFERENCED_PARAMETER(PreviousState);
  14.525 +
  14.526 +  //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
  14.527 +
  14.528 +  //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
  14.529 +
  14.530 +  return status;
  14.531 +}
  14.532 +
  14.533 +static HANDLE  ThreadHandle;
  14.534 +
  14.535 +static NTSTATUS
  14.536 +XenPCI_D0EntryPostInterruptsEnabled(WDFDEVICE  Device, WDF_POWER_DEVICE_STATE PreviousState)
  14.537 +{
  14.538 +  NTSTATUS status = STATUS_SUCCESS;
  14.539 +  //OBJECT_ATTRIBUTES oa;
  14.540 +  char *response;
  14.541 +  char *msgTypes;
  14.542 +  char **Types;
  14.543 +  int i;
  14.544 +  char buffer[128];
  14.545 +
  14.546 +  UNREFERENCED_PARAMETER(Device);
  14.547 +  UNREFERENCED_PARAMETER(PreviousState);
  14.548 +
  14.549 +  //KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
  14.550 +
  14.551 +  XenBus_Start();
  14.552 +  
  14.553 +  //InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
  14.554 +  //status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, &oa, NULL, NULL, XenBus_ThreadProc, NULL);
  14.555 +  //KdPrint((__DRIVER_NAME "     PsCreateSystemThread returned %08X\n", status));
  14.556 +
  14.557 +  response = XenBus_AddWatch(XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, NULL);
  14.558 +  //KdPrint((__DRIVER_NAME "     shutdown watch response = '%s'\n", response)); 
  14.559 +
  14.560 +  response = XenBus_AddWatch(XBT_NIL, "device", XenPCI_XenBusWatchHandler, NULL);
  14.561 +  //KdPrint((__DRIVER_NAME "     device watch response = '%s'\n", response)); 
  14.562 +
  14.563 +  msgTypes = XenBus_List(XBT_NIL, "device", &Types);
  14.564 +  if (!msgTypes) {
  14.565 +    for (i = 0; Types[i]; i++)
  14.566 +    {
  14.567 +      RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/%s", Types[i]);
  14.568 +      //KdPrint((__DRIVER_NAME "     ls device[%d] -> %s\n", i, Types[i]));
  14.569 +      XenPCI_XenBusWatchHandler(buffer, NULL);
  14.570 +      ExFreePoolWithTag(Types[i], XENPCI_POOL_TAG);
  14.571 +    }
  14.572 +  }
  14.573 +//      msgInstances = XenBus_List(XBT_NIL, buffer, &Instances);
  14.574 +//      for (j = 0; Instances[j]; j++)
  14.575 +//      {
  14.576 +//        //KdPrint((__DRIVER_NAME "      ls %s[%d] -> %s\n", buffer, j, Instances[j]));
  14.577 +//
  14.578 +//        sprintf(buffer, "device/%s/%s", Types[i], Instances[j]);
  14.579 +//
  14.580 +//
  14.581 +//        ExFreePoolWithTag(Instances[j], XENPCI_POOL_TAG);
  14.582 +//      }
  14.583 +  
  14.584 +  //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
  14.585 +
  14.586 +  return status;
  14.587 +}
  14.588 +
  14.589 +static NTSTATUS
  14.590 +XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)
  14.591 +{
  14.592 +  NTSTATUS status = STATUS_SUCCESS;
  14.593 +
  14.594 +  UNREFERENCED_PARAMETER(Device);
  14.595 +  UNREFERENCED_PARAMETER(TargetState);
  14.596 +
  14.597 +  XenBus_Stop();
  14.598 +
  14.599 +  return status;
  14.600 +}
  14.601 +
  14.602 +static NTSTATUS
  14.603 +XenPCI_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)
  14.604 +{
  14.605 +  NTSTATUS status = STATUS_SUCCESS;
  14.606 +
  14.607 +  UNREFERENCED_PARAMETER(Device);
  14.608 +  UNREFERENCED_PARAMETER(TargetState);
  14.609 +
  14.610 +  KdPrint((__DRIVER_NAME " --> EvtDeviceD0Exit\n"));
  14.611 +
  14.612 +  KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Exit\n"));
  14.613 +
  14.614 +  return status;
  14.615 +}
  14.616 +
  14.617 +static VOID 
  14.618 +XenPCI_IoDefault(
  14.619 +    IN WDFQUEUE  Queue,
  14.620 +    IN WDFREQUEST  Request
  14.621 +    )
  14.622 +{
  14.623 +  UNREFERENCED_PARAMETER(Queue);
  14.624 +
  14.625 +  KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
  14.626 +
  14.627 +  WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
  14.628 +
  14.629 +  KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
  14.630 +}
  14.631 +
  14.632 +static NTSTATUS
  14.633 +XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
  14.634 +{
  14.635 +  UNREFERENCED_PARAMETER(Interrupt);
  14.636 +  UNREFERENCED_PARAMETER(AssociatedDevice);
  14.637 +
  14.638 +  KdPrint((__DRIVER_NAME " --> EvtInterruptEnable\n"));
  14.639 +
  14.640 +  shared_info_area->vcpu_info[0].evtchn_upcall_mask = 0;
  14.641 +
  14.642 +  KdPrint((__DRIVER_NAME " <-- EvtInterruptEnable\n"));
  14.643 +
  14.644 +  return STATUS_SUCCESS;
  14.645 +}
  14.646 +
  14.647 +static NTSTATUS
  14.648 +XenPCI_InterruptDisable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
  14.649 +{
  14.650 +  UNREFERENCED_PARAMETER(Interrupt);
  14.651 +  UNREFERENCED_PARAMETER(AssociatedDevice);
  14.652 +
  14.653 +  //KdPrint((__DRIVER_NAME " --> EvtInterruptDisable\n"));
  14.654 +
  14.655 +  shared_info_area->vcpu_info[0].evtchn_upcall_mask = 1;
  14.656 +
  14.657 +  //KdPrint((__DRIVER_NAME " <-- EvtInterruptDisable\n"));
  14.658 +
  14.659 +  return STATUS_SUCCESS;
  14.660 +}
  14.661 +
  14.662 +static NTSTATUS
  14.663 +XenPCI_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit)
  14.664 +{
  14.665 +  NTSTATUS status;
  14.666 +  WDFDEVICE ChildDevice = NULL;
  14.667 +  PXENPCI_IDENTIFICATION_DESCRIPTION XenIdentificationDesc;
  14.668 +  XEN_IFACE_EVTCHN EvtChnInterface;
  14.669 +  XEN_IFACE_XENBUS XenBusInterface;
  14.670 +  XEN_IFACE_XEN XenInterface;
  14.671 +  XEN_IFACE_GNTTBL GntTblInterface;
  14.672 +  //UNICODE_STRING DeviceId;
  14.673 +  DECLARE_UNICODE_STRING_SIZE(buffer, 20);
  14.674 +  WDF_OBJECT_ATTRIBUTES PdoAttributes;
  14.675 +  DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
  14.676 +  WDF_QUERY_INTERFACE_CONFIG  qiConfig;
  14.677 +  //WDF_PDO_EVENT_CALLBACKS PdoCallbacks;
  14.678 +  PXENPCI_XEN_DEVICE_DATA ChildDeviceData = NULL;
  14.679 +  //size_t path_len;
  14.680 +
  14.681 +  UNREFERENCED_PARAMETER(ChildList);
  14.682 +
  14.683 +  //KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
  14.684 +
  14.685 +  XenIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENPCI_IDENTIFICATION_DESCRIPTION, Header);
  14.686 +
  14.687 +  //KdPrint((__DRIVER_NAME "     Type = %wZ\n", &XenIdentificationDesc->DeviceType));
  14.688 +
  14.689 +  //DeviceInit = WdfPdoInitAllocate(Device);
  14.690 +  WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_CONTROLLER);
  14.691 +
  14.692 +  status = RtlUnicodeStringPrintf(&buffer, L"Xen\\%wZ\0", &XenIdentificationDesc->DeviceType);
  14.693 +  status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
  14.694 +  status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
  14.695 +  status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
  14.696 +
  14.697 +  status = RtlUnicodeStringPrintf(&buffer, L"%02d", 0);
  14.698 +  status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
  14.699 +
  14.700 +  status = RtlUnicodeStringPrintf( &buffer, L"%wZ", &XenIdentificationDesc->DeviceType);
  14.701 +  status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
  14.702 +
  14.703 +  WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
  14.704 +  
  14.705 +  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, XENPCI_XEN_DEVICE_DATA);
  14.706 +
  14.707 +//  WDF_PDO_EVENT_CALLBACKS_INIT(&PdoCallbacks);
  14.708 +//  PdoCallbacks.EvtDeviceResourceRequirementsQuery = XenPCI_DeviceResourceRequirementsQuery;
  14.709 +//  WdfPdoInitSetEventCallbacks(ChildInit, &PdoCallbacks);
  14.710 +
  14.711 +  status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
  14.712 +  if (!NT_SUCCESS(status))
  14.713 +  {
  14.714 +    KdPrint((__DRIVER_NAME "     WdfDeviceCreate status = %08X\n", status));
  14.715 +  }
  14.716 +
  14.717 +  ChildDeviceData = GetXenDeviceData(ChildDevice);
  14.718 +  strncpy(ChildDeviceData->BasePath, XenIdentificationDesc->Path, 128);
  14.719 +  
  14.720 +  RtlZeroMemory(&EvtChnInterface, sizeof(EvtChnInterface));
  14.721 +  EvtChnInterface.InterfaceHeader.Size = sizeof(EvtChnInterface);
  14.722 +  EvtChnInterface.InterfaceHeader.Version = 1;
  14.723 +  EvtChnInterface.InterfaceHeader.Context = NULL;
  14.724 +  EvtChnInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
  14.725 +  EvtChnInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
  14.726 +  EvtChnInterface.Bind = EvtChn_Bind;
  14.727 +  EvtChnInterface.Unbind = EvtChn_Unbind;
  14.728 +  EvtChnInterface.Mask = EvtChn_Mask;
  14.729 +  EvtChnInterface.Unmask = EvtChn_Unmask;
  14.730 +  EvtChnInterface.Notify = EvtChn_Notify;
  14.731 +  EvtChnInterface.AllocUnbound = EvtChn_AllocUnbound;
  14.732 +  WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&EvtChnInterface, &GUID_XEN_IFACE_EVTCHN, NULL);
  14.733 +  status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
  14.734 +  if (!NT_SUCCESS(status))
  14.735 +  {
  14.736 +    return status;
  14.737 +  }
  14.738 +
  14.739 +  RtlZeroMemory(&XenInterface, sizeof(XenInterface));
  14.740 +  XenInterface.InterfaceHeader.Size = sizeof(XenInterface);
  14.741 +  XenInterface.InterfaceHeader.Version = 1;
  14.742 +  XenInterface.InterfaceHeader.Context = NULL;
  14.743 +  XenInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
  14.744 +  XenInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
  14.745 +  XenInterface.AllocMMIO = XenPCI_AllocMMIO;
  14.746 +  WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&XenInterface, &GUID_XEN_IFACE_XEN, NULL);
  14.747 +  status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
  14.748 +  if (!NT_SUCCESS(status)) {
  14.749 +    return status;
  14.750 +  }
  14.751 +
  14.752 +  RtlZeroMemory(&GntTblInterface, sizeof(GntTblInterface));
  14.753 +  GntTblInterface.InterfaceHeader.Size = sizeof(GntTblInterface);
  14.754 +  GntTblInterface.InterfaceHeader.Version = 1;
  14.755 +  GntTblInterface.InterfaceHeader.Context = NULL;
  14.756 +  GntTblInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
  14.757 +  GntTblInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
  14.758 +  GntTblInterface.GrantAccess = GntTbl_GrantAccess;
  14.759 +  GntTblInterface.EndAccess = GntTbl_EndAccess;
  14.760 +  WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&GntTblInterface, &GUID_XEN_IFACE_GNTTBL, NULL);
  14.761 +  status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
  14.762 +  if (!NT_SUCCESS(status)) {
  14.763 +    return status;
  14.764 +  }
  14.765 +
  14.766 +  RtlZeroMemory(&XenBusInterface, sizeof(XenBusInterface));
  14.767 +
  14.768 +  XenBusInterface.InterfaceHeader.Size = sizeof(XenBusInterface);
  14.769 +  XenBusInterface.InterfaceHeader.Version = 1;
  14.770 +  XenBusInterface.InterfaceHeader.Context = NULL;
  14.771 +  //XenBusInterface.InterfaceHeader.Context = ExAllocatePoolWithTag(NonPagedPool, (strlen(XenIdentificationDesc->Path) + 1), XENPCI_POOL_TAG);
  14.772 +  //strcpy(XenBusInterface.InterfaceHeader.Context, XenIdentificationDesc->Path);
  14.773 +  XenBusInterface.Read = XenBus_Read;
  14.774 +  XenBusInterface.Write = XenBus_Write;
  14.775 +  XenBusInterface.Printf = XenBus_Printf;
  14.776 +  XenBusInterface.StartTransaction = XenBus_StartTransaction;
  14.777 +  XenBusInterface.EndTransaction = XenBus_EndTransaction;
  14.778 +  XenBusInterface.List = XenBus_List;
  14.779 +  XenBusInterface.AddWatch = XenBus_AddWatch;
  14.780 +  XenBusInterface.RemWatch = XenBus_RemWatch;
  14.781 +  WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&XenBusInterface, &GUID_XEN_IFACE_XENBUS, NULL);
  14.782 +  status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
  14.783 +  if (!NT_SUCCESS(status)) {
  14.784 +    return status;
  14.785 +  }
  14.786 +
  14.787 +  //KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice\n"));
  14.788 +
  14.789 +  return status;
  14.790 +}
  14.791 +
  14.792 +VOID
  14.793 +XenPCI_XenBusWatchHandler(char *Path, PVOID Data)
  14.794 +{
  14.795 +  XENPCI_IDENTIFICATION_DESCRIPTION description;
  14.796 +  NTSTATUS status;
  14.797 +  char **Bits;
  14.798 +  int Count;
  14.799 +  WDFCHILDLIST ChildList;
  14.800 +  WDF_CHILD_LIST_ITERATOR ChildIterator;
  14.801 +  WDFDEVICE ChildDevice;
  14.802 +  PXENPCI_XEN_DEVICE_DATA ChildDeviceData;
  14.803 +  
  14.804 +  ANSI_STRING AnsiBuf;
  14.805 +
  14.806 +  UNREFERENCED_PARAMETER(Data);
  14.807 +
  14.808 +  //KdPrint((__DRIVER_NAME " --> HotPlugHandler\n"));
  14.809 +
  14.810 +  //KdPrint((__DRIVER_NAME "     %s\n", Path));
  14.811 +
  14.812 +  ChildList = WdfFdoGetDefaultChildList(Device);
  14.813 +
  14.814 +  Bits = SplitString(Path, '/', 3, &Count);
  14.815 +  switch (Count)
  14.816 +  {
  14.817 +    case 0:
  14.818 +    case 1:
  14.819 +      break;
  14.820 +    case 2:
  14.821 +      // add or update the device node
  14.822 +      WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
  14.823 +      strncpy(description.Path, Path, 128);
  14.824 +      RtlInitAnsiString(&AnsiBuf, Bits[1]);
  14.825 +      //KdPrint((__DRIVER_NAME "     Name = %s\n", Bits[1]));  
  14.826 +      RtlAnsiStringToUnicodeString(&description.DeviceType, &AnsiBuf, TRUE);
  14.827 +      status = WdfChildListAddOrUpdateChildDescriptionAsPresent(ChildList, &description.Header, NULL);
  14.828 +      break;
  14.829 +    default:
  14.830 +      WDF_CHILD_LIST_ITERATOR_INIT(&ChildIterator, WdfRetrievePresentChildren);
  14.831 +      WdfChildListBeginIteration(ChildList, &ChildIterator);
  14.832 +      while(NT_SUCCESS(WdfChildListRetrieveNextDevice(ChildList, &ChildIterator, &ChildDevice, NULL)))
  14.833 +      {
  14.834 +	ChildDeviceData = GetXenDeviceData(ChildDevice);
  14.835 +        if (!ChildDeviceData)
  14.836 +          continue;
  14.837 +        if (strncmp(ChildDeviceData->BasePath, Path, strlen(ChildDeviceData->BasePath)) == 0 && Path[strlen(ChildDeviceData->BasePath)] == '/')
  14.838 +        {
  14.839 +          //KdPrint((__DRIVER_NAME "     Child Path = %s (Match - WatchHandler = %08x)\n", ChildDeviceData->BasePath, ChildDeviceData->WatchHandler));
  14.840 +          if (ChildDeviceData->WatchHandler != NULL)
  14.841 +            ChildDeviceData->WatchHandler(Path, NULL);
  14.842 +        }
  14.843 +        else
  14.844 +        {
  14.845 +          //KdPrint((__DRIVER_NAME "     Child Path = %s (No Match)\n", ChildDeviceData->BasePath));
  14.846 +        }
  14.847 +      }
  14.848 +      WdfChildListEndIteration(ChildList, &ChildIterator);
  14.849 +      break;
  14.850 +  }
  14.851 +
  14.852 +  FreeSplitString(Bits, Count);
  14.853 +  
  14.854 +  //KdPrint((__DRIVER_NAME " <-- HotPlugHandler\n"));  
  14.855 +}
  14.856 +
  14.857 +static void
  14.858 +XenBus_ShutdownHandler(char *Path, PVOID StartContext)
  14.859 +{
  14.860 +  char *value;
  14.861 +  xenbus_transaction_t xbt;
  14.862 +  int retry;
  14.863 +
  14.864 +  UNREFERENCED_PARAMETER(Path);
  14.865 +  UNREFERENCED_PARAMETER(StartContext);
  14.866 +
  14.867 +  //KdPrint((__DRIVER_NAME " --> XenBus_ShutdownHandler\n"));
  14.868 +
  14.869 +  XenBus_StartTransaction(&xbt);
  14.870 +
  14.871 +  XenBus_Read(XBT_NIL, SHUTDOWN_PATH, &value);
  14.872 +
  14.873 +  //KdPrint((__DRIVER_NAME "     Shutdown Value = %s\n", value));
  14.874 +
  14.875 +  // should check for error here... but why have we been called at all???
  14.876 +  if (value != NULL && strlen(value) != 0)
  14.877 +    XenBus_Write(XBT_NIL, SHUTDOWN_PATH, "");
  14.878 +
  14.879 +  XenBus_EndTransaction(xbt, 0, &retry);
  14.880 +  
  14.881 +  //KdPrint((__DRIVER_NAME " <-- XenBus_ShutdownHandler\n"));
  14.882 +}
  14.883 +
  14.884 +/*
  14.885 +IO_RESOURCE_DESCRIPTOR MemoryDescriptor;
  14.886 +
  14.887 +static NTSTATUS
  14.888 +XenPCI_FilterRemoveResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList)
  14.889 +{
  14.890 +  NTSTATUS status;
  14.891 +  WDFIORESLIST ResourceList;
  14.892 +  PIO_RESOURCE_DESCRIPTOR Descriptor;
  14.893 +
  14.894 +  int i, j;
  14.895 +  int offset;
  14.896 +
  14.897 +  //KdPrint((__DRIVER_NAME " --> FilterRemoveResourceRequirements\n"));
  14.898 +
  14.899 +  for (i = 0; i < WdfIoResourceRequirementsListGetCount(RequirementsList); i++)
  14.900 +  {
  14.901 +    ResourceList = WdfIoResourceRequirementsListGetIoResList(RequirementsList, i);
  14.902 +    //KdPrint((__DRIVER_NAME "     Resource List %d\n", i));
  14.903 +    //KdPrint((__DRIVER_NAME "     %d resources in list\n", WdfIoResourceListGetCount(ResourceList)));
  14.904 +    offset = 0;
  14.905 +    for (j = 0; j < WdfIoResourceListGetCount(ResourceList); j++)
  14.906 +    {
  14.907 +      //KdPrint((__DRIVER_NAME "       Resource %d\n", j));
  14.908 +      Descriptor = WdfIoResourceListGetDescriptor(ResourceList, j - offset);
  14.909 +
  14.910 +      switch (Descriptor->Type) {
  14.911 +      case CmResourceTypePort:
  14.912 +        //KdPrint((__DRIVER_NAME "         Port\n"));
  14.913 +        break;
  14.914 +      case CmResourceTypeMemory:
  14.915 +        //KdPrint((__DRIVER_NAME "         Memory %08X%08X - %08X%08X\n", Descriptor->u.Memory.MinimumAddress.HighPart, Descriptor->u.Memory.MinimumAddress.LowPart, Descriptor->u.Memory.MaximumAddress.HighPart, Descriptor->u.Memory.MaximumAddress.LowPart));
  14.916 +        //KdPrint((__DRIVER_NAME "         Length %08X\n", Descriptor->u.Memory.Length));
  14.917 +        //KdPrint((__DRIVER_NAME "         ShareDisposition %02X\n", Descriptor->ShareDisposition));
  14.918 +        //KdPrint((__DRIVER_NAME "         Option %02X\n", Descriptor->Option));
  14.919 +        if (!Descriptor->Option || Descriptor->Option == IO_RESOURCE_PREFERRED) {
  14.920 +          memcpy(&MemoryDescriptor, Descriptor, sizeof(IO_RESOURCE_DESCRIPTOR));
  14.921 +          //platform_mmio_orig_len = MemoryDescriptor.u.Memory.Length;
  14.922 +          //MemoryDescriptor.u.Memory.Length = PAGE_SIZE;
  14.923 +          MemoryDescriptor.ShareDisposition = CmResourceShareShared;
  14.924 +        }
  14.925 +        WdfIoResourceListRemove(ResourceList, j - offset);
  14.926 +        offset++;
  14.927 +        break;
  14.928 +      case CmResourceTypeInterrupt:
  14.929 +        //KdPrint((__DRIVER_NAME "         Interrupt\n"));
  14.930 +        break;
  14.931 +      case CmResourceTypeDevicePrivate:
  14.932 +        //KdPrint((__DRIVER_NAME "         Private\n"));
  14.933 +        break;
  14.934 +      default:
  14.935 +        //KdPrint((__DRIVER_NAME "         Unknown Type (0x%x)\n", Descriptor->Type));
  14.936 +        break;
  14.937 +      }
  14.938 +    }
  14.939 +  }
  14.940 +  status = STATUS_SUCCESS;
  14.941 +
  14.942 +  KdPrint((__DRIVER_NAME " <-- FilterRemoveResourceRequirements\n"));
  14.943 +
  14.944 +  return status;
  14.945 +}
  14.946 +
  14.947 +static NTSTATUS
  14.948 +XenPCI_FilterAddResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList)
  14.949 +{
  14.950 +  NTSTATUS status;
  14.951 +  WDFIORESLIST ResourceList;
  14.952 +  PIO_RESOURCE_DESCRIPTOR Descriptor;
  14.953 +
  14.954 +  int i, j;
  14.955 +
  14.956 +  KdPrint((__DRIVER_NAME " --> FilterAddResourceRequirements\n"));
  14.957 +
  14.958 +
  14.959 +  for (i = 0; i < WdfIoResourceRequirementsListGetCount(RequirementsList); i++)
  14.960 +  {
  14.961 +    ResourceList = WdfIoResourceRequirementsListGetIoResList(RequirementsList, i);
  14.962 +    //KdPrint((__DRIVER_NAME "     Resource List %d\n", i));
  14.963 +    //KdPrint((__DRIVER_NAME "     %d resources in list\n", WdfIoResourceListGetCount(ResourceList)));
  14.964 +    WdfIoResourceListAppendDescriptor(ResourceList, &MemoryDescriptor);
  14.965 +    //KdPrint((__DRIVER_NAME "         Memory %08X%08X - %08X%08X\n", MemoryDescriptor.u.Memory.MinimumAddress.HighPart, MemoryDescriptor.u.Memory.MinimumAddress.LowPart, MemoryDescriptor.u.Memory.MaximumAddress.HighPart, MemoryDescriptor.u.Memory.MaximumAddress.LowPart));
  14.966 +    //KdPrint((__DRIVER_NAME "         Length %08X\n", MemoryDescriptor.u.Memory.Length));
  14.967 +    for (j = 0; j < WdfIoResourceListGetCount(ResourceList); j++)
  14.968 +    {
  14.969 +      //KdPrint((__DRIVER_NAME "       Resource %d\n", j));
  14.970 +      Descriptor = WdfIoResourceListGetDescriptor(ResourceList, j);
  14.971 +
  14.972 +      switch (Descriptor->Type) {
  14.973 +      case CmResourceTypePort:
  14.974 +        //KdPrint((__DRIVER_NAME "         Port\n"));
  14.975 +        break;
  14.976 +      case CmResourceTypeMemory:
  14.977 +        //KdPrint((__DRIVER_NAME "         Memory %08X%08X - %08X%08X\n", Descriptor->u.Memory.MinimumAddress.HighPart, Descriptor->u.Memory.MinimumAddress.LowPart, Descriptor->u.Memory.MaximumAddress.HighPart, Descriptor->u.Memory.MaximumAddress.LowPart));
  14.978 +        //KdPrint((__DRIVER_NAME "         Length %08X\n", Descriptor->u.Memory.Length));
  14.979 +        //KdPrint((__DRIVER_NAME "         ShareDisposition %02X\n", Descriptor->ShareDisposition));
  14.980 +        //Descriptor->ShareDisposition = CmResourceShareShared;
  14.981 +        //memcpy(&MemoryDescriptor, Descriptor, sizeof(IO_RESOURCE_DESCRIPTOR));
  14.982 +        //platform_mmio_orig_len = MemoryDescriptor.u.Memory.Length;
  14.983 +        //MemoryDescriptor.u.Memory.Length = PAGE_SIZE;
  14.984 +        //WdfIoResourceListRemove(ResourceList, j);
  14.985 +        break;
  14.986 +      case CmResourceTypeInterrupt:
  14.987 +        //KdPrint((__DRIVER_NAME "         Interrupt\n"));
  14.988 +        break;
  14.989 +      case CmResourceTypeDevicePrivate:
  14.990 +        //KdPrint((__DRIVER_NAME "         Private\n"));
  14.991 +        break;
  14.992 +      default:
  14.993 +        //KdPrint((__DRIVER_NAME "         Unknown Type (0x%x)\n", Descriptor->Type));
  14.994 +        break;
  14.995 +      }
  14.996 +    }
  14.997 +  }
  14.998 +  status = STATUS_SUCCESS;
  14.999 +
 14.1000 +  //KdPrint((__DRIVER_NAME " <-- FilterAddResourceRequirements\n"));
 14.1001 +
 14.1002 +  return status;
 14.1003 +}
 14.1004 +
 14.1005 +static NTSTATUS
 14.1006 +XenPCI_RemoveAddedResources(WDFDEVICE Device, WDFCMRESLIST ResourcesRaw, WDFCMRESLIST ResourcesTranslated)
 14.1007 +{
 14.1008 +  //KdPrint((__DRIVER_NAME " --> RemoveAddedResources\n"));
 14.1009 +  //KdPrint((__DRIVER_NAME " <-- RemoveAddedResources\n"));
 14.1010 +
 14.1011 +  return STATUS_SUCCESS;
 14.1012 +}
 14.1013 +
 14.1014 +*/
 14.1015 +
 14.1016 +static NTSTATUS
 14.1017 +XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList)
 14.1018 +{
 14.1019 +  NTSTATUS  status;
 14.1020 +  WDFIORESLIST resourceList;
 14.1021 +  IO_RESOURCE_DESCRIPTOR descriptor;
 14.1022 +
 14.1023 +  UNREFERENCED_PARAMETER(Device);
 14.1024 +
 14.1025 +  //KdPrint((__DRIVER_NAME " --> DeviceResourceRequirementsQuery\n"));
 14.1026 +
 14.1027 +  status = WdfIoResourceListCreate(IoResourceRequirementsList, WDF_NO_OBJECT_ATTRIBUTES, &resourceList);
 14.1028 +  if (!NT_SUCCESS(status))
 14.1029 +    return status;
 14.1030 +
 14.1031 +/*
 14.1032 +  RtlZeroMemory(&descriptor, sizeof(descriptor));
 14.1033 +
 14.1034 +  descriptor.Option = 0;
 14.1035 +  descriptor.Type = CmResourceTypeInterrupt;
 14.1036 +  descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
 14.1037 +  descriptor.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
 14.1038 +  descriptor.u.Interrupt.MinimumVector = 1024;
 14.1039 +  descriptor.u.Interrupt.MaximumVector = 1024+255;
 14.1040 +
 14.1041 +  //KdPrint((__DRIVER_NAME "     MinimumVector = %d, MaximumVector = %d\n", descriptor.u.Interrupt.MinimumVector, descriptor.u.Interrupt.MaximumVector));
 14.1042 +
 14.1043 +  status = WdfIoResourceListAppendDescriptor(resourceList, &descriptor);
 14.1044 +  if (!NT_SUCCESS(status))
 14.1045 +    return status;
 14.1046 +*/
 14.1047 +
 14.1048 +  RtlZeroMemory(&descriptor, sizeof(descriptor));
 14.1049 +
 14.1050 +  descriptor.Option = 0;
 14.1051 +  descriptor.Type = CmResourceTypeMemory;
 14.1052 +  descriptor.ShareDisposition = CmResourceShareShared; //CmResourceShareDeviceExclusive;
 14.1053 +  descriptor.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
 14.1054 +  descriptor.u.Memory.Length = PAGE_SIZE;
 14.1055 +  descriptor.u.Memory.Alignment = PAGE_SIZE;
 14.1056 +  descriptor.u.Memory.MinimumAddress.QuadPart = platform_mmio_addr.QuadPart + PAGE_SIZE;
 14.1057 +  descriptor.u.Memory.MaximumAddress.QuadPart = platform_mmio_addr.QuadPart + platform_mmio_len - 1;
 14.1058 +
 14.1059 +  //KdPrint((__DRIVER_NAME "     MinimumAddress = %08x, MaximumAddress = %08X\n", descriptor.u.Memory.MinimumAddress.LowPart, descriptor.u.Memory.MaximumAddress.LowPart));
 14.1060 +
 14.1061 +  status = WdfIoResourceListAppendDescriptor(resourceList, &descriptor);
 14.1062 +  if (!NT_SUCCESS(status))
 14.1063 +    return status;
 14.1064 +
 14.1065 +  status = WdfIoResourceRequirementsListAppendIoResList(IoResourceRequirementsList, resourceList);
 14.1066 +  if (!NT_SUCCESS(status))
 14.1067 +    return status;
 14.1068 +
 14.1069 +  //KdPrint((__DRIVER_NAME " <-- DeviceResourceRequirementsQuery\n"));
 14.1070 +
 14.1071 +  return status;
 14.1072 +}
 14.1073 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xenpci/xenpci.h	Sat Nov 10 14:40:56 2007 +1100
    15.3 @@ -0,0 +1,213 @@
    15.4 +/*
    15.5 +PV Drivers for Windows Xen HVM Domains
    15.6 +Copyright (C) 2007 James Harper
    15.7 +
    15.8 +This program is free software; you can redistribute it and/or
    15.9 +modify it under the terms of the GNU General Public License
   15.10 +as published by the Free Software Foundation; either version 2
   15.11 +of the License, or (at your option) any later version.
   15.12 +
   15.13 +This program is distributed in the hope that it will be useful,
   15.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.16 +GNU General Public License for more details.
   15.17 +
   15.18 +You should have received a copy of the GNU General Public License
   15.19 +along with this program; if not, write to the Free Software
   15.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   15.21 +*/
   15.22 +
   15.23 +#if !defined(_XENPCI_H_)
   15.24 +#define _XENPCI_H_
   15.25 +
   15.26 +#define __attribute__(arg) /* empty */
   15.27 +#define EISCONN 127
   15.28 +
   15.29 +#include <ntddk.h>
   15.30 +#include <wdm.h>
   15.31 +#include <wdf.h>
   15.32 +#include <initguid.h>
   15.33 +#include <wdmguid.h>
   15.34 +#include <errno.h>
   15.35 +
   15.36 +#define NTSTRSAFE_LIB
   15.37 +#include <ntstrsafe.h>
   15.38 +
   15.39 +#include <xen_windows.h>
   15.40 +/*
   15.41 +#define __XEN_INTERFACE_VERSION__ 0x00030205
   15.42 +#define __i386__
   15.43 +typedef signed char int8_t;
   15.44 +typedef unsigned char uint8_t;
   15.45 +typedef SHORT int16_t;
   15.46 +typedef USHORT uint16_t;
   15.47 +typedef LONG int32_t;
   15.48 +typedef ULONG uint32_t;
   15.49 +typedef ULONGLONG uint64_t;
   15.50 +typedef unsigned long pgentry_t;
   15.51 +
   15.52 +#define _PAGE_PRESENT  0x001UL
   15.53 +#define _PAGE_RW       0x002UL
   15.54 +#define _PAGE_USER     0x004UL
   15.55 +#define _PAGE_PWT      0x008UL
   15.56 +#define _PAGE_PCD      0x010UL
   15.57 +#define _PAGE_ACCESSED 0x020UL
   15.58 +#define _PAGE_DIRTY    0x040UL
   15.59 +#define _PAGE_PAT      0x080UL
   15.60 +#define _PAGE_PSE      0x080UL
   15.61 +#define _PAGE_GLOBAL   0x100UL
   15.62 +
   15.63 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   15.64 +*/
   15.65 +
   15.66 +#include <memory.h>
   15.67 +#include <grant_table.h>
   15.68 +#include <event_channel.h>
   15.69 +#include <hvm/params.h>
   15.70 +#include <hvm/hvm_op.h>
   15.71 +
   15.72 +//{C828ABE9-14CA-4445-BAA6-82C2376C6518}
   15.73 +DEFINE_GUID( GUID_XENPCI_DEVCLASS, 0xC828ABE9, 0x14CA, 0x4445, 0xBA, 0xA6, 0x82, 0xC2, 0x37, 0x6C, 0x65, 0x18);
   15.74 +
   15.75 +#define __DRIVER_NAME "XenPCI"
   15.76 +#define XENPCI_POOL_TAG (ULONG) 'XenP'
   15.77 +//#define XENPCI_FDO_INSTANCE_SIGNATURE (ULONG) 'XENP'
   15.78 +
   15.79 +#define NR_RESERVED_ENTRIES 8
   15.80 +#define NR_GRANT_FRAMES 4
   15.81 +#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
   15.82 +
   15.83 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
   15.84 +
   15.85 +extern char *hypercall_stubs;
   15.86 +
   15.87 +typedef struct _XENPCI_IDENTIFICATION_DESCRIPTION
   15.88 +{
   15.89 +  WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Header;
   15.90 +  UNICODE_STRING DeviceType;
   15.91 +//  ULONG DeviceIndex;
   15.92 +  char Path[128];
   15.93 +} XENPCI_IDENTIFICATION_DESCRIPTION, *PXENPCI_IDENTIFICATION_DESCRIPTION;
   15.94 +
   15.95 +
   15.96 +typedef struct {
   15.97 +  WDFQUEUE          IoDefaultQueue;
   15.98 +
   15.99 +  // Resources
  15.100 +  //WDFINTERRUPT      Interrupt;
  15.101 +  //PULONG            PhysAddress;
  15.102 +
  15.103 +  //ULONG platform_mmio_addr;
  15.104 +  //ULONG platform_mmio_len;
  15.105 +  //ULONG platform_mmio_alloc;
  15.106 +
  15.107 +  //ULONG shared_info_frame;
  15.108 +  //char *hypercall_stubs;
  15.109 +
  15.110 +  //PULONG            IoBaseAddress;
  15.111 +  //ULONG             IoRange;
  15.112 +
  15.113 +  // Grant Table stuff
  15.114 +
  15.115 +  //grant_entry_t *gnttab_table;
  15.116 +  //grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
  15.117 +
  15.118 +} XENPCI_DEVICE_DATA, *PXENPCI_DEVICE_DATA;
  15.119 +
  15.120 +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENPCI_DEVICE_DATA, GetDeviceData);
  15.121 +
  15.122 +VOID
  15.123 +GntTbl_Init();
  15.124 +
  15.125 +
  15.126 +
  15.127 +typedef unsigned long xenbus_transaction_t;
  15.128 +typedef uint32_t XENSTORE_RING_IDX;
  15.129 +
  15.130 +//struct __xsd_sockmsg
  15.131 +//{
  15.132 +//    uint32_t type;  /* XS_??? */
  15.133 +//    uint32_t req_id;/* Request identifier, echoed in daemon's response.  */
  15.134 +//    uint32_t tx_id; /* Transaction id (0 if not related to a transaction). */
  15.135 +//    uint32_t len;   /* Length of data following this. */
  15.136 +//
  15.137 +//    /* Generally followed by nul-terminated string(s). */
  15.138 +//};
  15.139 +
  15.140 +#define XBT_NIL ((xenbus_transaction_t)0)
  15.141 +
  15.142 +#include <evtchn_public.h>
  15.143 +#include <xenbus_public.h>
  15.144 +#include <xen_public.h>
  15.145 +#include <gnttbl_public.h>
  15.146 +
  15.147 +char *
  15.148 +XenBus_Read(xenbus_transaction_t xbt, const char *path, char **value);
  15.149 +char *
  15.150 +XenBus_Write(xenbus_transaction_t xbt, const char *path, const char *value);
  15.151 +char *
  15.152 +XenBus_Printf(xenbus_transaction_t xbt, const char *path, const char *fmt, ...);
  15.153 +char *
  15.154 +XenBus_StartTransaction(xenbus_transaction_t *xbt);
  15.155 +char *
  15.156 +XenBus_EndTransaction(xenbus_transaction_t t, int abort, int *retry);
  15.157 +char *
  15.158 +XenBus_List(xenbus_transaction_t xbt, const char *prefix, char ***contents);
  15.159 +NTSTATUS
  15.160 +XenBus_Init();
  15.161 +NTSTATUS
  15.162 +XenBus_Start();
  15.163 +NTSTATUS
  15.164 +XenBus_Stop();
  15.165 +
  15.166 +//typedef VOID
  15.167 +//(*PXENBUS_WATCH_CALLBACK)(char *Path, PVOID ServiceContext);
  15.168 +
  15.169 +char *
  15.170 +XenBus_AddWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext);
  15.171 +char *
  15.172 +XenBus_RemWatch(xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext);
  15.173 +
  15.174 +
  15.175 +VOID
  15.176 +XenBus_ThreadProc(PVOID StartContext);
  15.177 +
  15.178 +PHYSICAL_ADDRESS
  15.179 +XenPCI_AllocMMIO(ULONG len);
  15.180 +
  15.181 +//PVOID
  15.182 +//map_frames(PULONG f, ULONG n);
  15.183 +
  15.184 +
  15.185 +extern shared_info_t *shared_info_area;
  15.186 +
  15.187 +BOOLEAN
  15.188 +EvtChn_Interrupt(WDFINTERRUPT Interrupt, ULONG MessageID);
  15.189 +BOOLEAN
  15.190 +EvtChn_InterruptDpc(WDFINTERRUPT Interrupt, WDFOBJECT AssociatedObject);
  15.191 +NTSTATUS
  15.192 +EvtChn_Mask(evtchn_port_t Port);
  15.193 +NTSTATUS
  15.194 +EvtChn_Unmask(evtchn_port_t Port);
  15.195 +NTSTATUS
  15.196 +EvtChn_Bind(evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext);
  15.197 +NTSTATUS
  15.198 +EvtChn_Unbind(evtchn_port_t Port);
  15.199 +NTSTATUS
  15.200 +EvtChn_Notify(evtchn_port_t Port);
  15.201 +evtchn_port_t
  15.202 +EvtChn_AllocUnbound(domid_t Domain);
  15.203 +NTSTATUS
  15.204 +EvtChn_Init();
  15.205 +
  15.206 +grant_ref_t
  15.207 +GntTbl_GrantAccess(domid_t domid, unsigned long frame, int readonly);
  15.208 +BOOLEAN
  15.209 +GntTbl_EndAccess(grant_ref_t ref);
  15.210 +
  15.211 +evtchn_port_t
  15.212 +EvtChn_GetXenStorePort();
  15.213 +PVOID
  15.214 +EvtChn_GetXenStoreRingAddr();
  15.215 +
  15.216 +#endif
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/xenvbd/makefile	Sat Nov 10 14:40:56 2007 +1100
    16.3 @@ -0,0 +1,1 @@
    16.4 +!INCLUDE $(NTMAKEENV)\makefile.def
    16.5 \ No newline at end of file
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/xenvbd/sources	Sat Nov 10 14:40:56 2007 +1100
    17.3 @@ -0,0 +1,13 @@
    17.4 +TARGETNAME=XENVBD
    17.5 +TARGETTYPE=DRIVER
    17.6 +TARGETPATH=Target
    17.7 +
    17.8 +MSC_WARNING_LEVEL=/W4
    17.9 +
   17.10 +INCLUDES = ..\common\include;..\common\include\public
   17.11 +
   17.12 +NO_BINPLACE=1
   17.13 +KMDF_VERSION=1
   17.14 +TARGETLIBS=$(DDK_LIB_PATH)\ntstrsafe.lib $(DDK_LIB_PATH)\scsiport.lib
   17.15 +
   17.16 +SOURCES=xenvbd.c
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/xenvbd/target/xenvbd.inf	Sat Nov 10 14:40:56 2007 +1100
    18.3 @@ -0,0 +1,94 @@
    18.4 +[Version]
    18.5 +Signature="$WINDOWS NT$"
    18.6 +Class=SCSIAdapter
    18.7 +ClassGuid={B968331F-9539-47d0-855E-66CB6AA613E2}
    18.8 +Provider=%JAMESHARPER%
    18.9 +DriverVer=11/09/2007,1.0.1.285
   18.10 +
   18.11 +[DestinationDirs]
   18.12 +DefaultDestDir = 12
   18.13 +ClassInstall32_CopyFiles=11
   18.14 +CoInstaller_CopyFiles = 11
   18.15 +
   18.16 +; ================= Class section =====================
   18.17 +
   18.18 +[ClassInstall32]
   18.19 +Addreg=ClassInstall32_AddReg
   18.20 +CopyFiles=ClassInstall32_CopyFiles
   18.21 +
   18.22 +[ClassInstall32_AddReg]
   18.23 +HKR,,,0,%ClassName%
   18.24 +HKR,,Icon,,-5
   18.25 +HKR,,DeviceCharacteristics,0x10001,0x100
   18.26 +HKR,,Security,,"D:P(A;;GA;;;SY)(A;;GA;;;BA)"
   18.27 +
   18.28 +[ClassInstall32_CopyFiles]
   18.29 +
   18.30 +[ControlFlags]
   18.31 +ExcludeFromSelect=*
   18.32 +
   18.33 +
   18.34 +[Manufacturer]
   18.35 +%JAMESHARPER%=JAMESHARPER,NTx86
   18.36 +
   18.37 +[JAMESHARPER]
   18.38 +%XenVbd.DRVDESC%=XenVbd_Inst, XEN\VBD
   18.39 +
   18.40 +[JAMESHARPER.NTx86]
   18.41 +%XenVbd.DRVDESC%=XenVbd_Inst, XEN\VBD
   18.42 +
   18.43 +[XenVbd_Inst.NT]
   18.44 +CopyFiles=XenVbd.CopyFiles
   18.45 +
   18.46 +[XenVbd.CopyFiles]
   18.47 +xenvbd.sys
   18.48 +
   18.49 +[SourceDisksFiles]
   18.50 +xenvbd.sys=1
   18.51 +WdfCoinstaller01005.dll=1,,
   18.52 +
   18.53 +[SourceDisksNames.x86]
   18.54 +1 = %DISK_NAME%,,,\i386
   18.55 +
   18.56 +[XenVbd_Inst.Services]
   18.57 +AddService=XenVbd,2,XenVbd_Service 
   18.58 +
   18.59 +[XenVbd_Inst.NT.Services]
   18.60 +AddService=XenVbd,2,XenVbd_Service 
   18.61 +
   18.62 +[XenVbd_Service]
   18.63 +DisplayName    = %XenVbd.SVCDESC%                            
   18.64 +ServiceType    = 1
   18.65 +StartType      = 0
   18.66 +ErrorControl   = 1
   18.67 +LoadOrderGroup = WdfLoadGroup
   18.68 +ServiceBinary  = %12%\xenvbd.sys                            
   18.69 +AddReg = XenVbd_Service_AddReg
   18.70 +
   18.71 +[XenVbd_Service_AddReg]
   18.72 +; 5 = PciBus, 0 = Internal, 15 = PnpBus
   18.73 +HKR,"Parameters\PnpInterface", "15", 0x00010001, 0x00000001
   18.74 +
   18.75 +
   18.76 +[XenVbd_Inst.NT.CoInstallers]
   18.77 +AddReg=CoInstaller_AddReg
   18.78 +CopyFiles=CoInstaller_CopyFiles
   18.79 +
   18.80 +[CoInstaller_CopyFiles]
   18.81 +WdfCoinstaller01005.dll,,,2
   18.82 +
   18.83 +[CoInstaller_AddReg]
   18.84 +HKR,,CoInstallers32,0x00010000, "WdfCoinstaller01005.dll,WdfCoInstaller"
   18.85 +
   18.86 +[XenVbd_Inst.NT.Wdf]
   18.87 +KmdfService = xenvbd, xenvbd_wdfsect
   18.88 +
   18.89 +[xenvbd_wdfsect]
   18.90 +KmdfLibraryVersion = 1.0
   18.91 +
   18.92 +[Strings]
   18.93 +JAMESHARPER = "James Harper"
   18.94 +ClassName = "SCSI Adapters"
   18.95 +XenVbd.SVCDESC = "Xen Block Device Driver"
   18.96 +XenVbd.DRVDESC = "Xen Block Device Driver"
   18.97 +DISK_NAME = "Xen Block Device Driver Install Disk"
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/xenvbd/xenvbd.c	Sat Nov 10 14:40:56 2007 +1100
    19.3 @@ -0,0 +1,1341 @@
    19.4 +#include "xenvbd.h"
    19.5 +#include <io/blkif.h>
    19.6 +#include <srb.h>
    19.7 +#include <scsi.h>
    19.8 +#include <ntddscsi.h>
    19.9 +#include <ntdddisk.h>
   19.10 +#include <stdlib.h>
   19.11 +#include <xen_public.h>
   19.12 +#include <gnttbl_public.h>
   19.13 +#include <io/xenbus.h>
   19.14 +
   19.15 +#define wmb() KeMemoryBarrier()
   19.16 +#define mb() KeMemoryBarrier()
   19.17 +
   19.18 +DRIVER_INITIALIZE DriverEntry;
   19.19 +
   19.20 +static NTSTATUS
   19.21 +XenVbd_AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit);
   19.22 +
   19.23 +static NTSTATUS
   19.24 +XenVbd_PrepareHardware(WDFDEVICE hDevice, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated);
   19.25 +
   19.26 +static NTSTATUS
   19.27 +XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated);
   19.28 +
   19.29 +static NTSTATUS
   19.30 +XenVbd_D0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
   19.31 +
   19.32 +static NTSTATUS
   19.33 +XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
   19.34 +
   19.35 +static NTSTATUS
   19.36 +XenVbd_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
   19.37 +
   19.38 +static VOID
   19.39 +XenVbd_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
   19.40 +static VOID
   19.41 +XenVbd_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t  Length);
   19.42 +static VOID
   19.43 +XenVbd_IoWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t  Length);
   19.44 +static VOID
   19.45 +XenVbd_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, IN size_t  OutputBufferLength, size_t  InputBufferLength, ULONG IoControlCode);
   19.46 +
   19.47 +static NTSTATUS
   19.48 +XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit);
   19.49 +//static NTSTATUS
   19.50 +//XenVbd_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
   19.51 +static NTSTATUS
   19.52 +XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp);
   19.53 +static VOID 
   19.54 +XenVbd_Child_IoDefault(WDFQUEUE  Queue, WDFREQUEST  Request);
   19.55 +static VOID 
   19.56 +XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode);
   19.57 +
   19.58 +static VOID
   19.59 +XenVbd_HotPlugHandler(char *Path, PVOID Data);
   19.60 +
   19.61 +#ifdef ALLOC_PRAGMA
   19.62 +#pragma alloc_text (INIT, DriverEntry)
   19.63 +#pragma alloc_text (PAGE, XenVbd_AddDevice)
   19.64 +#endif
   19.65 +
   19.66 +LIST_ENTRY DeviceListHead;
   19.67 +XEN_IFACE_EVTCHN EvtChnInterface;
   19.68 +XEN_IFACE_XENBUS XenBusInterface;
   19.69 +XEN_IFACE_XEN XenInterface;
   19.70 +XEN_IFACE_GNTTBL GntTblInterface;
   19.71 +
   19.72 +static BOOLEAN AutoEnumerate;
   19.73 +
   19.74 +NTSTATUS
   19.75 +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
   19.76 +{
   19.77 +  WDF_DRIVER_CONFIG config;
   19.78 +  ULONG status;
   19.79 +  UNICODE_STRING RegKeyName;
   19.80 +  UNICODE_STRING RegValueName;
   19.81 +  HANDLE RegHandle;
   19.82 +  OBJECT_ATTRIBUTES RegObjectAttributes;
   19.83 +  char Buf[200];
   19.84 +  ULONG BufLen = 200;
   19.85 +  PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
   19.86 +  int State = 0;
   19.87 +  int StartPos = 0;
   19.88 +  WCHAR *SystemStartOptions;
   19.89 +  size_t SystemStartOptionsLen;
   19.90 +  size_t i;
   19.91 +
   19.92 +  KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
   19.93 +
   19.94 +  WDF_DRIVER_CONFIG_INIT(&config, XenVbd_AddDevice);
   19.95 +  status = WdfDriverCreate(
   19.96 +                      DriverObject,
   19.97 +                      RegistryPath,
   19.98 +                      WDF_NO_OBJECT_ATTRIBUTES,
   19.99 +                      &config,
  19.100 +                      WDF_NO_HANDLE);
  19.101 +  if(!NT_SUCCESS(status))
  19.102 +  {
  19.103 +    KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
  19.104 +  }
  19.105 +
  19.106 +  RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
  19.107 +  InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
  19.108 +  status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
  19.109 +  if(!NT_SUCCESS(status))
  19.110 +  {
  19.111 +    KdPrint((__DRIVER_NAME "     ZwOpenKey returned %08x\n", status));
  19.112 +  }
  19.113 +
  19.114 +  RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
  19.115 +  status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
  19.116 +  if(!NT_SUCCESS(status))
  19.117 +  {
  19.118 +    KdPrint((__DRIVER_NAME "     ZwQueryKeyValue returned %08x\n", status));
  19.119 +  }
  19.120 +  //KdPrint((__DRIVER_NAME "     BufLen = %d\n", BufLen));
  19.121 +  KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
  19.122 +  KdPrint((__DRIVER_NAME "     Buf = %ws\n", KeyPartialValue->Data));
  19.123 +  SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
  19.124 +
  19.125 +  AutoEnumerate = FALSE;
  19.126 +
  19.127 +  RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
  19.128 +
  19.129 +  for (i = 0; i <= SystemStartOptionsLen/2; i++)
  19.130 +  {
  19.131 +    //KdPrint((__DRIVER_NAME "     pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
  19.132 +    
  19.133 +    switch (State)
  19.134 +    {
  19.135 +    case 0:
  19.136 +      if (SystemStartOptions[i] == L'G')
  19.137 +      {
  19.138 +        StartPos = i;
  19.139 +        State = 2;
  19.140 +      } else if (SystemStartOptions[i] != L' ')
  19.141 +      {
  19.142 +        State = 1;
  19.143 +      }
  19.144 +      break;
  19.145 +    case 1:
  19.146 +      if (SystemStartOptions[i] == L' ')
  19.147 +        State = 0;
  19.148 +      break;
  19.149 +    case 2:
  19.150 +      if (SystemStartOptions[i] == L'P')
  19.151 +        State = 3;
  19.152 +      else
  19.153 +        State = 0;
  19.154 +      break;
  19.155 +    case 3:
  19.156 +      if (SystemStartOptions[i] == L'L')
  19.157 +        State = 4;
  19.158 +      else
  19.159 +        State = 0;
  19.160 +      break;
  19.161 +    case 4:
  19.162 +      if (SystemStartOptions[i] == L'P')
  19.163 +        State = 5;
  19.164 +      else
  19.165 +        State = 0;
  19.166 +      break;
  19.167 +    case 5:
  19.168 +      if (SystemStartOptions[i] == L'V')
  19.169 +        State = 6;
  19.170 +      else
  19.171 +        State = 0;
  19.172 +      break;
  19.173 +    case 6:
  19.174 +      if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
  19.175 +        AutoEnumerate = TRUE;
  19.176 +      State = 0;
  19.177 +      break;
  19.178 +    }
  19.179 +  }
  19.180 +
  19.181 +  KdPrint((__DRIVER_NAME "     AutoEnumerate = %d\n", AutoEnumerate));
  19.182 +
  19.183 +  KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
  19.184 +
  19.185 +  return status;
  19.186 +}
  19.187 +
  19.188 +static WDFDEVICE GlobalDevice;
  19.189 +static PDEVICE_OBJECT Pdo;
  19.190 +
  19.191 +static NTSTATUS
  19.192 +XenVbd_AddDevice(
  19.193 +    IN WDFDRIVER Driver,
  19.194 +    IN PWDFDEVICE_INIT DeviceInit
  19.195 +    )
  19.196 +{
  19.197 +  WDF_CHILD_LIST_CONFIG ChildListConfig;
  19.198 +  NTSTATUS status;
  19.199 +  WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
  19.200 +
  19.201 +  UNREFERENCED_PARAMETER(Driver);
  19.202 +
  19.203 +  KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
  19.204 +
  19.205 +  Pdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
  19.206 +
  19.207 +  //*** just changed ***
  19.208 +  //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
  19.209 +  WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION), XenVbd_ChildListCreateDevice);
  19.210 +  WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES);
  19.211 +
  19.212 +  WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CONTROLLER);
  19.213 +  //WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
  19.214 +  WdfDeviceInitSetExclusive(DeviceInit, FALSE);
  19.215 +  
  19.216 +  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
  19.217 +  pnpPowerCallbacks.EvtDevicePrepareHardware = XenVbd_PrepareHardware;
  19.218 +  pnpPowerCallbacks.EvtDeviceReleaseHardware = XenVbd_ReleaseHardware;
  19.219 +  pnpPowerCallbacks.EvtDeviceD0Entry = XenVbd_D0Entry;
  19.220 +  pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenVbd_D0EntryPostInterruptsEnabled;
  19.221 +  pnpPowerCallbacks.EvtDeviceD0Exit = XenVbd_D0Exit;
  19.222 +  WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
  19.223 +
  19.224 +  /*initialize storage for the device context*/
  19.225 +  //WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENVBD_DEVICE_DATA);
  19.226 +
  19.227 +  /*create a device instance.*/
  19.228 +  status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &GlobalDevice);  
  19.229 +  if(!NT_SUCCESS(status))
  19.230 +  {
  19.231 +    KdPrint((__DRIVER_NAME "WdfDeviceCreate failed with status 0x%08x\n", status));
  19.232 +    return status;
  19.233 +  }
  19.234 +  
  19.235 +  status = STATUS_SUCCESS;
  19.236 +
  19.237 +  KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
  19.238 +  return status;
  19.239 +}
  19.240 +
  19.241 +static NTSTATUS
  19.242 +XenVbd_PrepareHardware(
  19.243 +  IN WDFDEVICE    Device,
  19.244 +  IN WDFCMRESLIST ResourceList,
  19.245 +  IN WDFCMRESLIST ResourceListTranslated)
  19.246 +{
  19.247 +  NTSTATUS status = STATUS_SUCCESS;
  19.248 +
  19.249 +  UNREFERENCED_PARAMETER(ResourceList);
  19.250 +  UNREFERENCED_PARAMETER(ResourceListTranslated);
  19.251 +
  19.252 +  //KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
  19.253 +
  19.254 +  status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_EVTCHN, (PINTERFACE) &EvtChnInterface, sizeof(XEN_IFACE_EVTCHN), 1, NULL);
  19.255 +  if(!NT_SUCCESS(status))
  19.256 +  {
  19.257 +    KdPrint((__DRIVER_NAME "     WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
  19.258 +  }
  19.259 +
  19.260 +  status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XENBUS, (PINTERFACE)&XenBusInterface, sizeof(XEN_IFACE_XENBUS), 1, NULL);
  19.261 +  if(!NT_SUCCESS(status))
  19.262 +  {
  19.263 +    KdPrint((__DRIVER_NAME "     WdfFdoQueryForInterface (XenBus) failed with status 0x%08x\n", status));
  19.264 +  }
  19.265 +
  19.266 +  status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XEN, (PINTERFACE)&XenInterface, sizeof(XEN_IFACE_XEN), 1, NULL);
  19.267 +  if(!NT_SUCCESS(status))
  19.268 +  {
  19.269 +    KdPrint((__DRIVER_NAME "     WdfFdoQueryForInterface (Xen) failed with status 0x%08x\n", status));
  19.270 +  }
  19.271 +
  19.272 +  status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_GNTTBL, (PINTERFACE)&GntTblInterface, sizeof(XEN_IFACE_GNTTBL), 1, NULL);
  19.273 +  if(!NT_SUCCESS(status))
  19.274 +  {
  19.275 +    KdPrint((__DRIVER_NAME "     WdfFdoQueryForInterface (GntTbl) failed with status 0x%08x\n", status));
  19.276 +  }
  19.277 +  
  19.278 +  //KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
  19.279 +
  19.280 +  InitializeListHead(&DeviceListHead);
  19.281 +
  19.282 +  return status;
  19.283 +}
  19.284 +
  19.285 +static NTSTATUS
  19.286 +XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
  19.287 +{
  19.288 +  UNREFERENCED_PARAMETER(Device);
  19.289 +  UNREFERENCED_PARAMETER(ResourcesTranslated);
  19.290 +
  19.291 +  // release interfaces here...
  19.292 +
  19.293 +  //XenVbd_Close();
  19.294 +
  19.295 +  return STATUS_SUCCESS;
  19.296 +}
  19.297 +
  19.298 +static NTSTATUS
  19.299 +XenVbd_D0Entry(
  19.300 +    IN WDFDEVICE  Device,
  19.301 +    IN WDF_POWER_DEVICE_STATE PreviousState
  19.302 +    )
  19.303 +{
  19.304 +  NTSTATUS status = STATUS_SUCCESS;
  19.305 +
  19.306 +  UNREFERENCED_PARAMETER(Device);
  19.307 +  UNREFERENCED_PARAMETER(PreviousState);
  19.308 +
  19.309 +  //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
  19.310 +
  19.311 +  
  19.312 +  //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
  19.313 +
  19.314 +  return status;
  19.315 +}
  19.316 +
  19.317 +static int EnumeratedDevices;
  19.318 +static KEVENT WaitDevicesEvent;
  19.319 +
  19.320 +static NTSTATUS
  19.321 +XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
  19.322 +{
  19.323 +  //OBJECT_ATTRIBUTES oa;
  19.324 +  NTSTATUS status = STATUS_SUCCESS;
  19.325 +  //HANDLE nothing;
  19.326 +  //char *response;
  19.327 +  PXENPCI_XEN_DEVICE_DATA PdoDeviceData;
  19.328 +  char **VbdDevices;
  19.329 +  char *msg;
  19.330 +  char buffer[128];
  19.331 +  int i;
  19.332 +  LARGE_INTEGER WaitTimeout;
  19.333 +
  19.334 +  UNREFERENCED_PARAMETER(Device);
  19.335 +  UNREFERENCED_PARAMETER(PreviousState);
  19.336 +
  19.337 +  //KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
  19.338 +
  19.339 +  PdoDeviceData = (PXENPCI_XEN_DEVICE_DATA)Pdo->DeviceExtension; //GetXenDeviceData(Device);
  19.340 +
  19.341 +  //KdPrint((__DRIVER_NAME "     BasePath = %s\n", PdoDeviceData->BasePath));
  19.342 +  PdoDeviceData->WatchHandler = XenVbd_HotPlugHandler;
  19.343 +
  19.344 +  EnumeratedDevices = 0;
  19.345 +  KeInitializeEvent(&WaitDevicesEvent, SynchronizationEvent, FALSE);  
  19.346 +
  19.347 +  if (AutoEnumerate)
  19.348 +  {
  19.349 +    msg = XenBusInterface.List(XBT_NIL, "device/vbd", &VbdDevices);
  19.350 +    if (!msg) {
  19.351 +      for (i = 0; VbdDevices[i]; i++)
  19.352 +      {
  19.353 +        KdPrint((__DRIVER_NAME "     found existing vbd device %s\n", VbdDevices[i]));
  19.354 +        RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
  19.355 +        XenVbd_HotPlugHandler(buffer, NULL);
  19.356 +        //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
  19.357 +      }
  19.358 +      KdPrint((__DRIVER_NAME "     Waiting for devices to be enumerated\n"));
  19.359 +      while (EnumeratedDevices != i)
  19.360 +      {
  19.361 +// TODO: need to not wait forever here...
  19.362 +        WaitTimeout.QuadPart = -600000000;
  19.363 +        if (KeWaitForSingleObject(&WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
  19.364 +        {
  19.365 +          KdPrint((__DRIVER_NAME "     Wait timed out\n"));
  19.366 +          break;
  19.367 +        }
  19.368 +        KdPrint((__DRIVER_NAME "     %d out of %d devices enumerated\n", EnumeratedDevices, i));
  19.369 +      }  
  19.370 +    }
  19.371 +  }
  19.372 +
  19.373 +  //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
  19.374 +
  19.375 +  return status;
  19.376 +}
  19.377 +
  19.378 +static NTSTATUS
  19.379 +XenVbd_D0Exit(
  19.380 +    IN WDFDEVICE Device,
  19.381 +    IN WDF_POWER_DEVICE_STATE  TargetState
  19.382 +    )
  19.383 +{
  19.384 +  NTSTATUS status = STATUS_SUCCESS;
  19.385 +  //char *response;
  19.386 +
  19.387 +  UNREFERENCED_PARAMETER(Device);
  19.388 +  UNREFERENCED_PARAMETER(TargetState);
  19.389 +
  19.390 +  //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Exit\n"));
  19.391 +
  19.392 +  //response = XenBusInterface.RemWatch(XBT_NIL, XenBusInterface.InterfaceHeader.Context, XenVbd_HotPlugHandler, NULL);
  19.393 +
  19.394 +  //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Exit\n"));
  19.395 +
  19.396 +  return status;
  19.397 +}
  19.398 +
  19.399 +static VOID 
  19.400 +XenVbd_IoDefault(
  19.401 +    IN WDFQUEUE  Queue,
  19.402 +    IN WDFREQUEST  Request
  19.403 +    )
  19.404 +{
  19.405 +  UNREFERENCED_PARAMETER(Queue);
  19.406 +
  19.407 +  //KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
  19.408 +
  19.409 +  WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
  19.410 +
  19.411 +  //KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
  19.412 +}
  19.413 +
  19.414 +static __inline uint64_t
  19.415 +GET_ID_FROM_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData)
  19.416 +{
  19.417 +  uint64_t free;
  19.418 +
  19.419 +  free = ChildDeviceData->shadow_free;
  19.420 +
  19.421 +  //KdPrint((__DRIVER_NAME "     A free = %d\n", free));
  19.422 +  
  19.423 +  ChildDeviceData->shadow_free = ChildDeviceData->shadow[free].req.id;
  19.424 +
  19.425 +  //KdPrint((__DRIVER_NAME "     A shadow_free now = %d\n", ChildDeviceData->shadow_free));
  19.426 +
  19.427 +  ChildDeviceData->shadow[free].req.id = 0x0fffffee; /* debug */
  19.428 +  return free;
  19.429 +}
  19.430 +
  19.431 +static __inline VOID
  19.432 +ADD_ID_TO_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, uint64_t Id)
  19.433 +{
  19.434 +  ChildDeviceData->shadow[Id].req.id  = ChildDeviceData->shadow_free;
  19.435 +  ChildDeviceData->shadow[Id].Irp = NULL;
  19.436 +  ChildDeviceData->shadow_free = Id;
  19.437 +}
  19.438 +
  19.439 +static VOID
  19.440 +XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp);
  19.441 +
  19.442 +static PMDL
  19.443 +AllocatePages(int Pages)
  19.444 +{
  19.445 +  PMDL Mdl;
  19.446 +  PVOID Buf;
  19.447 +
  19.448 +  Buf = ExAllocatePoolWithTag(NonPagedPool, Pages * PAGE_SIZE, XENVBD_POOL_TAG);
  19.449 +  if (Buf == NULL)
  19.450 +  {
  19.451 +    KdPrint((__DRIVER_NAME "     AllocatePages Failed at ExAllocatePoolWithTag\n"));
  19.452 +  }
  19.453 +  Mdl = IoAllocateMdl(Buf, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
  19.454 +  if (Mdl == NULL)
  19.455 +  {
  19.456 +    KdPrint((__DRIVER_NAME "     AllocatePages Failed at IoAllocateMdl\n"));
  19.457 +  }
  19.458 +  MmBuildMdlForNonPagedPool(Mdl);
  19.459 +  
  19.460 +  return Mdl;
  19.461 +}
  19.462 +
  19.463 +static PMDL
  19.464 +AllocatePage()
  19.465 +{
  19.466 +  return AllocatePages(1);
  19.467 +}
  19.468 +
  19.469 +static VOID
  19.470 +FreePages(PMDL Mdl)
  19.471 +{
  19.472 +  PVOID Buf = MmGetMdlVirtualAddress(Mdl);
  19.473 +  //KdPrint((__DRIVER_NAME "     FreePages Failed at IoAllocateMdl\n"));
  19.474 +  //KdPrint((__DRIVER_NAME "     FreePages Buf = %08x\n", Buf));
  19.475 +  IoFreeMdl(Mdl);
  19.476 +  ExFreePoolWithTag(Buf, XENVBD_POOL_TAG);
  19.477 +}
  19.478 +
  19.479 +static VOID
  19.480 +XenVbd_DpcThreadProc(WDFDPC Dpc)
  19.481 +{
  19.482 +  PIRP Irp;
  19.483 +  RING_IDX i, rp;
  19.484 +  int j;
  19.485 +  blkif_response_t *rep;
  19.486 +  PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
  19.487 +  PSCSI_REQUEST_BLOCK Srb;
  19.488 +  PIO_STACK_LOCATION IrpSp;
  19.489 +  char *DataBuffer;
  19.490 +  int more_to_do;
  19.491 +  int IrpCount;
  19.492 +  PIRP Irps[100];
  19.493 +  int BlockCount;
  19.494 +  KIRQL KIrql;
  19.495 +  WDFDEVICE ChildDevice;
  19.496 +  XenVbd_ListEntry *ListEntry;
  19.497 +
  19.498 +  //!!!IRQL_DISPATCH!!!
  19.499 +
  19.500 +  //KdPrint((__DRIVER_NAME " --> XenVbd_DpcThreadProc\n"));
  19.501 +
  19.502 +  ChildDevice = WdfDpcGetParentObject(Dpc);
  19.503 +
  19.504 +  ChildDeviceData = *GetChildDeviceData(ChildDevice);
  19.505 +
  19.506 +  IrpCount = 0;
  19.507 +  more_to_do = TRUE;
  19.508 +  KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
  19.509 +
  19.510 +  //ChildDeviceData->IrpAddedToRingAtLastDpc = ChildDeviceData->IrpAddedToRing;
  19.511 +
  19.512 +  while (more_to_do)
  19.513 +  {
  19.514 +    rp = ChildDeviceData->Ring.sring->rsp_prod;
  19.515 +    KeMemoryBarrier();
  19.516 +    for (i = ChildDeviceData->Ring.rsp_cons; i != rp; i++)
  19.517 +    {
  19.518 +      rep = RING_GET_RESPONSE(&ChildDeviceData->Ring, i);
  19.519 +      //ChildDeviceData->IrpRemovedFromRing++;
  19.520 +      Irp = ChildDeviceData->shadow[rep->id].Irp;
  19.521 +      IrpSp = IoGetCurrentIrpStackLocation(Irp);
  19.522 +      Srb = IrpSp->Parameters.Scsi.Srb;
  19.523 +
  19.524 +      if (rep->status != BLKIF_RSP_OKAY)
  19.525 +      {
  19.526 +        KdPrint((__DRIVER_NAME "     Xen Operation returned error in DpcThreadProc\n"));
  19.527 +        KdPrint((__DRIVER_NAME "       operation = %d, nr_segments = %d, sector_number = %d\n", ChildDeviceData->shadow[rep->id].req.operation, ChildDeviceData->shadow[rep->id].req.nr_segments, ChildDeviceData->shadow[rep->id].req.sector_number));
  19.528 +        for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
  19.529 +        {
  19.530 +          KdPrint((__DRIVER_NAME "       gref[%d] = %d\n", j, ChildDeviceData->shadow[rep->id].req.seg[j].gref));
  19.531 +        }
  19.532 +        KdPrint((__DRIVER_NAME "       MmGetMdlByteOffset = %d\n", MmGetMdlByteOffset(Irp->MdlAddress)));
  19.533 +      }
  19.534 +      for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
  19.535 +      {
  19.536 +        GntTblInterface.EndAccess(ChildDeviceData->shadow[rep->id].req.seg[j].gref);
  19.537 +      }
  19.538 +      BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
  19.539 +      if (Srb->Cdb[0] == SCSIOP_READ && ChildDeviceData->shadow[rep->id].Buf != NULL)
  19.540 +      {
  19.541 +        DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
  19.542 +        if (DataBuffer == NULL)
  19.543 +          KdPrint((__DRIVER_NAME "     MmGetSystemAddressForMdlSafe Failed in DpcThreadProc\n"));
  19.544 +        memcpy(DataBuffer, ChildDeviceData->shadow[rep->id].Buf, BlockCount * ChildDeviceData->BytesPerSector);
  19.545 +        FreePages(ChildDeviceData->shadow[rep->id].Mdl);
  19.546 +      }
  19.547 +      Srb->SrbStatus = SRB_STATUS_SUCCESS;
  19.548 +      Srb->ScsiStatus = 0;
  19.549 +      Irp->IoStatus.Status = STATUS_SUCCESS;
  19.550 +      Irp->IoStatus.Information = BlockCount * ChildDeviceData->BytesPerSector;
  19.551 +
  19.552 +      Irps[IrpCount++] = Irp;
  19.553 +
  19.554 +      ADD_ID_TO_FREELIST(ChildDeviceData, rep->id);
  19.555 +    }
  19.556 +
  19.557 +    ChildDeviceData->Ring.rsp_cons = i;
  19.558 +    if (i != ChildDeviceData->Ring.req_prod_pvt)
  19.559 +    {
  19.560 +      RING_FINAL_CHECK_FOR_RESPONSES(&ChildDeviceData->Ring, more_to_do);
  19.561 +    }
  19.562 +    else
  19.563 +    {
  19.564 +      ChildDeviceData->Ring.sring->rsp_event = i + 1;
  19.565 +      more_to_do = FALSE;
  19.566 +    }
  19.567 +  }
  19.568 +
  19.569 +  while (!RING_FULL(&ChildDeviceData->Ring) && (ListEntry = (XenVbd_ListEntry *)/*ExInterlocked*/RemoveHeadList(&ChildDeviceData->IrpListHead)) != (XenVbd_ListEntry *)&ChildDeviceData->IrpListHead)
  19.570 +  {
  19.571 +    //ChildDeviceData->IrpRemovedFromList++;
  19.572 +    XenVbd_PutIrpOnRing(ChildDevice, ListEntry->Irp);
  19.573 +    ExFreePoolWithTag(ListEntry, XENVBD_POOL_TAG);
  19.574 +  }
  19.575 +
  19.576 +  KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
  19.577 +
  19.578 +  for (j = 0; j < IrpCount; j++)
  19.579 +  {
  19.580 +    IoCompleteRequest(Irps[j], IO_NO_INCREMENT);
  19.581 +    //ChildDeviceData->IrpCompleted++;
  19.582 +  }
  19.583 +  //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc\n"));
  19.584 +  //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc (AddedToList = %d, RemovedFromList = %d, AddedToRing = %d, AddedToRingAtLastNotify = %d, AddedToRingAtLastInterrupt = %d, AddedToRingAtLastDpc = %d, RemovedFromRing = %d, IrpCompleted = %d)\n", ChildDeviceData->IrpAddedToList, ChildDeviceData->IrpRemovedFromList, ChildDeviceData->IrpAddedToRing, ChildDeviceData->IrpAddedToRingAtLastNotify, ChildDeviceData->IrpAddedToRingAtLastInterrupt, ChildDeviceData->IrpAddedToRingAtLastDpc, ChildDeviceData->IrpRemovedFromRing, ChildDeviceData->IrpCompleted));
  19.585 +}
  19.586 +
  19.587 +static BOOLEAN
  19.588 +XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
  19.589 +{
  19.590 +  BOOLEAN RetVal;
  19.591 +  PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
  19.592 +
  19.593 +  UNREFERENCED_PARAMETER(Interrupt);
  19.594 +  // !!!RUNS AT DIRQL!!!
  19.595 +
  19.596 +  //KdPrint((__DRIVER_NAME " --> XenVbd_Interrupt\n"));
  19.597 +
  19.598 +  ChildDeviceData = (PXENVBD_CHILD_DEVICE_DATA)ServiceContext;
  19.599 +  //ChildDeviceData->IrpAddedToRingAtLastInterrupt = ChildDeviceData->IrpAddedToRing;
  19.600 +  RetVal = WdfDpcEnqueue(ChildDeviceData->Dpc);
  19.601 +
  19.602 +  //KdPrint((__DRIVER_NAME " <-- XenVbd_Interrupt (RetVal = %d)\n", RetVal));  
  19.603 +
  19.604 +  return STATUS_SUCCESS;
  19.605 +}
  19.606 +
  19.607 +static VOID
  19.608 +XenVbd_BackEndStateHandler(char *Path, PVOID Data)
  19.609 +{
  19.610 +  PXENVBD_CHILD_DEVICE_DATA DeviceData;
  19.611 +  char TmpPath[128];
  19.612 +  char *Value;
  19.613 +  int NewState;
  19.614 +  PMDL Mdl;
  19.615 +  grant_ref_t ref;
  19.616 +  blkif_sring_t *SharedRing;
  19.617 +  ULONG PFN;
  19.618 +  XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
  19.619 +  NTSTATUS status;
  19.620 +
  19.621 +  DeviceData = (PXENVBD_CHILD_DEVICE_DATA)Data;
  19.622 +
  19.623 +  XenBusInterface.Read(XBT_NIL, Path, &Value);
  19.624 +
  19.625 +  NewState = atoi(Value);
  19.626 +  switch (NewState)
  19.627 +  {
  19.628 +  case XenbusStateUnknown:
  19.629 +    KdPrint((__DRIVER_NAME "     Backend State Changed to Unknown\n"));  
  19.630 +    break;
  19.631 +
  19.632 +  case XenbusStateInitialising:
  19.633 +    KdPrint((__DRIVER_NAME "     Backend State Changed to Initialising\n"));  
  19.634 +    break;
  19.635 +
  19.636 +  case XenbusStateInitWait:
  19.637 +    KdPrint((__DRIVER_NAME "     Backend State Changed to InitWait\n"));  
  19.638 +
  19.639 +    DeviceData->EventChannel = EvtChnInterface.AllocUnbound(0);
  19.640 +    EvtChnInterface.Bind(DeviceData->EventChannel, XenVbd_Interrupt, DeviceData);
  19.641 +    Mdl = AllocatePage();
  19.642 +    PFN = *MmGetMdlPfnArray(Mdl);
  19.643 +    SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
  19.644 +    SHARED_RING_INIT(SharedRing);
  19.645 +    FRONT_RING_INIT(&DeviceData->Ring, SharedRing, PAGE_SIZE);
  19.646 +    ref = GntTblInterface.GrantAccess(0, PFN, FALSE);
  19.647 +
  19.648 +    RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
  19.649 +    RtlStringCbCatA(TmpPath, 128, "/ring-ref");
  19.650 +    XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", ref);
  19.651 +
  19.652 +    RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
  19.653 +    RtlStringCbCatA(TmpPath, 128, "/event-channel");
  19.654 +    XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", DeviceData->EventChannel);
  19.655 +  
  19.656 +    RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
  19.657 +    RtlStringCbCatA(TmpPath, 128, "/state");
  19.658 +    XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
  19.659 +
  19.660 +    KdPrint((__DRIVER_NAME "     Set Frontend state to Initialised\n"));
  19.661 +    break;
  19.662 +
  19.663 +  case XenbusStateInitialised:
  19.664 +    KdPrint((__DRIVER_NAME "     Backend State Changed to Initialised\n"));
  19.665 +    // create the device
  19.666 +    break;
  19.667 +
  19.668 +  case XenbusStateConnected:
  19.669 +    KdPrint((__DRIVER_NAME "     Backend State Changed to Connected\n"));  
  19.670 +
  19.671 +    WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Description.Header, sizeof(Description));
  19.672 +
  19.673 +    Description.DeviceData = DeviceData;
  19.674 +
  19.675 +    RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
  19.676 +    RtlStringCbCatA(TmpPath, 128, "/type"); // should probably check that this is 'phy'
  19.677 +    XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
  19.678 +
  19.679 +    RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
  19.680 +    RtlStringCbCatA(TmpPath, 128, "/mode"); // should store this...
  19.681 +    XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
  19.682 +
  19.683 +    RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
  19.684 +    RtlStringCbCatA(TmpPath, 128, "/sector-size");
  19.685 +    XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
  19.686 +    // should complain if Value == NULL
  19.687 +    DeviceData->BytesPerSector = atoi(Value);
  19.688 +
  19.689 +    KdPrint((__DRIVER_NAME "     BytesPerSector = %d\n", DeviceData->BytesPerSector));    
  19.690 +
  19.691 +    RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
  19.692 +    RtlStringCbCatA(TmpPath, 128, "/sectors");
  19.693 +    XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
  19.694 +    // should complain if Value == NULL
  19.695 +    DeviceData->TotalSectors = (ULONGLONG)atol(Value);
  19.696 +
  19.697 +    KdPrint((__DRIVER_NAME "     TotalSectors = %d\n", DeviceData->TotalSectors));    
  19.698 +
  19.699 +    // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
  19.700 +    DeviceData->Geometry.MediaType = FixedMedia;
  19.701 +    DeviceData->Geometry.BytesPerSector = DeviceData->BytesPerSector;
  19.702 +    DeviceData->Geometry.SectorsPerTrack = 63;
  19.703 +    DeviceData->Geometry.TracksPerCylinder = 255;
  19.704 +    DeviceData->Geometry.Cylinders.QuadPart = DeviceData->TotalSectors / DeviceData->Geometry.SectorsPerTrack / DeviceData->Geometry.TracksPerCylinder;
  19.705 +    KdPrint((__DRIVER_NAME "     Geometry C/H/S = %d/%d/%d\n", DeviceData->Geometry.Cylinders.LowPart, DeviceData->Geometry.TracksPerCylinder, DeviceData->Geometry.SectorsPerTrack));
  19.706 +
  19.707 +    status = WdfChildListAddOrUpdateChildDescriptionAsPresent(WdfFdoGetDefaultChildList(GlobalDevice), &Description.Header, NULL);
  19.708 +    if (!NT_SUCCESS(status))
  19.709 +    {
  19.710 +      KdPrint((__DRIVER_NAME "     WdfChildListAddOrUpdateChildDescriptionAsPresent failed %08x\n", status));
  19.711 +    } 
  19.712 +
  19.713 +    RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
  19.714 +    RtlStringCbCatA(TmpPath, 128, "/state");
  19.715 +    XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", XenbusStateConnected);
  19.716 +
  19.717 +    KdPrint((__DRIVER_NAME "     Set Frontend state to Connected\n"));
  19.718 +    InterlockedIncrement(&EnumeratedDevices);
  19.719 +    KdPrint((__DRIVER_NAME "     Added a disk, notifying\n"));
  19.720 +    
  19.721 +    KeSetEvent(&WaitDevicesEvent, 1, FALSE);
  19.722 +
  19.723 +    break;
  19.724 +
  19.725 +  case XenbusStateClosing:
  19.726 +    KdPrint((__DRIVER_NAME "     Backend State Changed to Closing\n"));  
  19.727 +    break;
  19.728 +
  19.729 +  case XenbusStateClosed:
  19.730 +    KdPrint((__DRIVER_NAME "     Backend State Changed to Closed\n"));  
  19.731 +    break;
  19.732 +
  19.733 +  default:
  19.734 +    KdPrint((__DRIVER_NAME "     Backend State Changed to Undefined = %d\n", NewState));
  19.735 +    break;
  19.736 +  }
  19.737 +}
  19.738 +
  19.739 +static VOID
  19.740 +XenVbd_HotPlugHandler(char *Path, PVOID Data)
  19.741 +{
  19.742 +  PXENVBD_CHILD_DEVICE_DATA DeviceData;
  19.743 +  char **Bits;
  19.744 +  int Count;
  19.745 +  char TmpPath[128];
  19.746 +  char *Value;
  19.747 +
  19.748 +  UNREFERENCED_PARAMETER(Data);  
  19.749 +
  19.750 +  //KdPrint((__DRIVER_NAME " --> HotPlugHandler\n"));
  19.751 +
  19.752 +  //KdPrint((__DRIVER_NAME "     Path = %s\n", Path));
  19.753 +
  19.754 +  Bits = SplitString(Path, '/', 4, &Count);
  19.755 +  switch (Count)
  19.756 +  {
  19.757 +  case 0:
  19.758 +  case 1:
  19.759 +  case 2:
  19.760 +    break; // should never happen
  19.761 +  case 3:
  19.762 +    break;
  19.763 +  case 4:
  19.764 +    
  19.765 +    if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
  19.766 +      break;
  19.767 +    for (DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceListHead.Flink; DeviceData != (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead; DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceData->Entry.Flink)
  19.768 +    {
  19.769 +      if (strncmp(DeviceData->Path, Path, strlen(DeviceData->Path)) == 0 && Path[strlen(DeviceData->Path)] == '/')
  19.770 +      {
  19.771 +        break;
  19.772 +      }
  19.773 +    }
  19.774 +    if (DeviceData == (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead)
  19.775 +    {
  19.776 +      DeviceData = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENVBD_CHILD_DEVICE_DATA), XENVBD_POOL_TAG);
  19.777 +      memset(DeviceData, 0, sizeof(XENVBD_CHILD_DEVICE_DATA));
  19.778 +
  19.779 +      //KdPrint((__DRIVER_NAME "     Allocated ChildDeviceData = %08x\n", DeviceData));
  19.780 +      
  19.781 +      InsertTailList(&DeviceListHead, &DeviceData->Entry);
  19.782 +      RtlStringCbCopyA(DeviceData->Path, 128, Bits[0]);
  19.783 +      RtlStringCbCatA(DeviceData->Path, 128, "/");
  19.784 +      RtlStringCbCatA(DeviceData->Path, 128, Bits[1]);
  19.785 +      RtlStringCbCatA(DeviceData->Path, 128, "/");
  19.786 +      RtlStringCbCatA(DeviceData->Path, 128, Bits[2]);
  19.787 +
  19.788 +      DeviceData->DeviceIndex = atoi(Bits[2]);
  19.789 +
  19.790 +      RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
  19.791 +      RtlStringCbCatA(TmpPath, 128, "/backend");
  19.792 +      XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
  19.793 +      if (Value == NULL)
  19.794 +      {
  19.795 +        KdPrint((__DRIVER_NAME "     Read Failed\n"));
  19.796 +      }
  19.797 +      else
  19.798 +      {
  19.799 +        RtlStringCbCopyA(DeviceData->BackendPath, 128, Value);
  19.800 +      }
  19.801 +      RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
  19.802 +      RtlStringCbCatA(TmpPath, 128, "/state");
  19.803 +      XenBusInterface.AddWatch(XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, DeviceData);
  19.804 +    }
  19.805 +    break;
  19.806 +  }
  19.807 +  
  19.808 +  FreeSplitString(Bits, Count);
  19.809 +
  19.810 +  //KdPrint((__DRIVER_NAME " <-- HotPlugHandler\n"));  
  19.811 +
  19.812 +  return;
  19.813 +}
  19.814 +
  19.815 +static NTSTATUS
  19.816 +XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit)
  19.817 +{
  19.818 +  NTSTATUS status;
  19.819 +  WDFDEVICE ChildDevice;
  19.820 +  PXENVBD_DEVICE_IDENTIFICATION_DESCRIPTION XenVbdIdentificationDesc;
  19.821 +  DECLARE_UNICODE_STRING_SIZE(buffer, 50);
  19.822 +  WDF_OBJECT_ATTRIBUTES PdoAttributes;
  19.823 +  DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
  19.824 +  PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
  19.825 +  WDF_IO_QUEUE_CONFIG IoQueueConfig;
  19.826 +  unsigned int i;
  19.827 +  WDF_DPC_CONFIG DpcConfig;
  19.828 +  WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
  19.829 +
  19.830 +  UNREFERENCED_PARAMETER(ChildList);
  19.831 +
  19.832 +  //KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
  19.833 +
  19.834 +  XenVbdIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION, Header);
  19.835 +
  19.836 +  ChildDeviceData = XenVbdIdentificationDesc->DeviceData;
  19.837 +
  19.838 +  WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_MASS_STORAGE);
  19.839 +
  19.840 +  status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk&Ven_James&Prod_James&Rev_1.00\0");
  19.841 +  status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
  19.842 +
  19.843 +  status = RtlUnicodeStringPrintf(&buffer, L"%02d", ChildDeviceData->DeviceIndex);
  19.844 +  status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
  19.845 +
  19.846 +  status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk\0");
  19.847 +  status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
  19.848 +  status = RtlUnicodeStringPrintf(&buffer, L"XEN\\RAW\0");
  19.849 +  status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
  19.850 +  status = RtlUnicodeStringPrintf(&buffer, L"GenDisk\0");
  19.851 +  status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
  19.852 +
  19.853 +  status = RtlUnicodeStringPrintf(&buffer, L"vbd_%d", ChildDeviceData->DeviceIndex);
  19.854 +  status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
  19.855 +
  19.856 +  WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
  19.857 +  
  19.858 +  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, PXENVBD_CHILD_DEVICE_DATA);
  19.859 +
  19.860 +  WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, NULL, 0);
  19.861 +
  19.862 +  WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);
  19.863 +
  19.864 +  status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
  19.865 +  if (!NT_SUCCESS(status))
  19.866 +  {
  19.867 +    KdPrint((__DRIVER_NAME "     WdfDeviceCreate status = %08X\n", status));
  19.868 +  }
  19.869 +
  19.870 +  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQueueConfig, WdfIoQueueDispatchSequential);
  19.871 +  IoQueueConfig.EvtIoDefault = XenVbd_Child_IoDefault;
  19.872 +  IoQueueConfig.EvtIoDeviceControl = XenVbd_Child_IoDeviceControl;
  19.873 +
  19.874 +  *GetChildDeviceData(ChildDevice) = ChildDeviceData;
  19.875 +
  19.876 +  //ChildDeviceData->IrpAddedToList = 0;
  19.877 +  //ChildDeviceData->IrpRemovedFromList = 0;
  19.878 +  //ChildDeviceData->IrpAddedToRing = 0;
  19.879 +  //ChildDeviceData->IrpAddedToRingAtLastNotify = 0;
  19.880 +  //ChildDeviceData->IrpAddedToRingAtLastInterrupt = 0;
  19.881 +  //ChildDeviceData->IrpAddedToRingAtLastDpc = 0;
  19.882 +  //ChildDeviceData->IrpRemovedFromRing = 0;
  19.883 +  //ChildDeviceData->IrpCompleted = 0;
  19.884 +
  19.885 +  status = WdfIoQueueCreate(ChildDevice, &IoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ChildDeviceData->IoDefaultQueue);
  19.886 +  if(!NT_SUCCESS(status))
  19.887 +  {
  19.888 +    KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status));
  19.889 +    return status;
  19.890 +  }
  19.891 +
  19.892 +  ChildDeviceData->Device = ChildDevice;
  19.893 +  
  19.894 +  KeInitializeSpinLock(&ChildDeviceData->Lock);
  19.895 +  KeInitializeSpinLock(&ChildDeviceData->IrpListLock);
  19.896 +  InitializeListHead(&ChildDeviceData->IrpListHead);
  19.897 +
  19.898 +  ChildDeviceData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
  19.899 +  memset(ChildDeviceData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
  19.900 +  //KdPrint((__DRIVER_NAME "     Allocated shadow = %08x\n", ChildDeviceData->shadow));
  19.901 +  for (i = 0; i < BLK_RING_SIZE; i++)
  19.902 +    ChildDeviceData->shadow[i].req.id = i + 1;
  19.903 +  ChildDeviceData->shadow_free = 0;
  19.904 +  ChildDeviceData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
  19.905 +
  19.906 +  WDF_DPC_CONFIG_INIT(&DpcConfig, XenVbd_DpcThreadProc);
  19.907 +  WDF_OBJECT_ATTRIBUTES_INIT(&DpcObjectAttributes);
  19.908 +  DpcObjectAttributes.ParentObject = ChildDevice;
  19.909 +  WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &ChildDeviceData->Dpc);
  19.910 +
  19.911 +  //KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice\n"));
  19.912 +
  19.913 +  return status;
  19.914 +}
  19.915 +
  19.916 +
  19.917 +// Call with device lock held
  19.918 +static VOID
  19.919 +XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp)
  19.920 +{
  19.921 +  char *DataBuffer;
  19.922 +  PSCSI_REQUEST_BLOCK Srb;
  19.923 +  PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  19.924 +  PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
  19.925 +  blkif_request_t *req;
  19.926 +  int notify;
  19.927 +  int i;
  19.928 +  int j;
  19.929 +  int BlockCount;
  19.930 +  int sect_offset;
  19.931 +
  19.932 +  //KdPrint((__DRIVER_NAME " --> PutIrpOnRing\n"));
  19.933 +
  19.934 +  ChildDeviceData = *GetChildDeviceData(Device);
  19.935 +
  19.936 +  if (RING_FULL(&ChildDeviceData->Ring))
  19.937 +  {
  19.938 +    KdPrint((__DRIVER_NAME "     RING IS FULL - EXPECT BADNESS\n"));
  19.939 +  }
  19.940 +
  19.941 +  req = RING_GET_REQUEST(&ChildDeviceData->Ring, ChildDeviceData->Ring.req_prod_pvt);
  19.942 +
  19.943 +  //KdPrint((__DRIVER_NAME "     req = %08x\n", req));
  19.944 +
  19.945 +  Srb = irpSp->Parameters.Scsi.Srb;
  19.946 +
  19.947 +  req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
  19.948 +  BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
  19.949 +
  19.950 +  req->id = GET_ID_FROM_FREELIST(ChildDeviceData);
  19.951 +
  19.952 +  if (req->id == 0x0fffffff)
  19.953 +  {
  19.954 +    KdPrint((__DRIVER_NAME "     Something is horribly wrong in PutIrpOnRing\n"));
  19.955 +  }
  19.956 +
  19.957 +  //KdPrint((__DRIVER_NAME "     id = %d\n", req->id));
  19.958 +
  19.959 +  req->handle = 0;
  19.960 +  req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
  19.961 +  ChildDeviceData->shadow[req->id].Irp = Irp;
  19.962 +
  19.963 +  if ((MmGetMdlByteOffset(Irp->MdlAddress) & 0x1ff) == 0) // 0x1ff shouldn't be hardcoded...
  19.964 +  {
  19.965 +    // fast path - zero copy
  19.966 +    ChildDeviceData->shadow[req->id].Mdl = Irp->MdlAddress;
  19.967 +    ChildDeviceData->shadow[req->id].Buf = NULL; // we don't need the virtual address
  19.968 +  }
  19.969 +  else
  19.970 +  {
  19.971 +    // slow path - copy to bounce buffer
  19.972 +    ChildDeviceData->shadow[req->id].Mdl = AllocatePages((BlockCount * ChildDeviceData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
  19.973 +    ChildDeviceData->shadow[req->id].Buf = MmGetMdlVirtualAddress(ChildDeviceData->shadow[req->id].Mdl);
  19.974 +    if (ChildDeviceData->shadow[req->id].Buf == NULL)
  19.975 +    {
  19.976 +      KdPrint((__DRIVER_NAME "     MmGetMdlVirtualAddress returned NULL in PutIrpOnRing\n"));
  19.977 +    }
  19.978 +  }
  19.979 +
  19.980 +//  if (MmGetMdlByteOffset(Irp->MdlAddress) != 0)
  19.981 +//    KdPrint((__DRIVER_NAME "     ByteOffset == %08x - we can't cope with this yet!\n", MmGetMdlByteOffset(Irp->MdlAddress)));
  19.982 +  sect_offset = MmGetMdlByteOffset(ChildDeviceData->shadow[req->id].Mdl) >> 9;
  19.983 +  for (i = 0, req->nr_segments = 0; i < BlockCount; req->nr_segments++)
  19.984 +  {
  19.985 +    req->seg[req->nr_segments].gref = GntTblInterface.GrantAccess(0, MmGetMdlPfnArray(ChildDeviceData->shadow[req->id].Mdl)[req->nr_segments], FALSE);
  19.986 +    req->seg[req->nr_segments].first_sect = sect_offset;
  19.987 +    for (j = sect_offset; i < BlockCount && j < PAGE_SIZE / ChildDeviceData->BytesPerSector; j++, i++)
  19.988 +      req->seg[req->nr_segments].last_sect = (uint8_t)j;
  19.989 +    sect_offset = 0;
  19.990 +  }
  19.991 +  if (Srb->Cdb[0] == SCSIOP_WRITE && ChildDeviceData->shadow[req->id].Buf != NULL)
  19.992 +  {
  19.993 +    DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
  19.994 +    if (DataBuffer == NULL)
  19.995 +      KdPrint((__DRIVER_NAME "     MmGetSystemAddressForMdlSafe failed in PutIrpOnRing\n"));
  19.996 +    memcpy(ChildDeviceData->shadow[req->id].Buf, DataBuffer, BlockCount * ChildDeviceData->BytesPerSector);
  19.997 +    //MmUnmapLockedPages(DataBuffer, Irp->MdlAddress);
  19.998 +  }
  19.999 +  ChildDeviceData->shadow[req->id].req = *req;
 19.1000 +
 19.1001 +  ChildDeviceData->Ring.req_prod_pvt++;
 19.1002 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
 19.1003 +  if (notify)
 19.1004 +  {
 19.1005 +    EvtChnInterface.Notify(ChildDeviceData->EventChannel);
 19.1006 +    //KdPrint((__DRIVER_NAME "       Notified\n"));
 19.1007 +    //ChildDeviceData->IrpAddedToRing++;
 19.1008 +    //ChildDeviceData->IrpAddedToRingAtLastNotify = ChildDeviceData->IrpAddedToRing;
 19.1009 +  }
 19.1010 +  else
 19.1011 +  {
 19.1012 +    //ChildDeviceData->IrpAddedToRing++;
 19.1013 +  }
 19.1014 +  //KdPrint((__DRIVER_NAME " <-- PutIrpOnRing\n"));
 19.1015 +}
 19.1016 +
 19.1017 +static NTSTATUS
 19.1018 +XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp)
 19.1019 +{
 19.1020 +  char *DataBuffer;
 19.1021 +  NTSTATUS status = STATUS_SUCCESS;
 19.1022 +  PSCSI_REQUEST_BLOCK Srb;
 19.1023 +  PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
 19.1024 +  PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
 19.1025 +  KIRQL KIrql;
 19.1026 +  XenVbd_ListEntry *ListEntry;
 19.1027 +
 19.1028 +  //KdPrint((__DRIVER_NAME " --> WdmIrpPreprocessSCSI\n"));
 19.1029 +
 19.1030 +  ChildDeviceData = *GetChildDeviceData(Device);
 19.1031 +
 19.1032 +  Srb = irpSp->Parameters.Scsi.Srb;
 19.1033 +
 19.1034 +  switch (Srb->Function)
 19.1035 +  {
 19.1036 +  case SRB_FUNCTION_EXECUTE_SCSI:
 19.1037 +    //KdPrint((__DRIVER_NAME "     SRB_FUNCTION_EXECUTE_SCSI\n"));
 19.1038 +    switch(Srb->Cdb[0]) {
 19.1039 +    case SCSIOP_TEST_UNIT_READY:
 19.1040 +      //KdPrint((__DRIVER_NAME "     Command = TEST_UNIT_READY\n"));
 19.1041 +      Srb->SrbStatus = SRB_STATUS_SUCCESS;
 19.1042 +      Srb->ScsiStatus = 0;
 19.1043 +      status = STATUS_SUCCESS;
 19.1044 +      Irp->IoStatus.Status = status;
 19.1045 +      Irp->IoStatus.Information = 0;
 19.1046 +      IoCompleteRequest(Irp, IO_NO_INCREMENT);
 19.1047 +      break;
 19.1048 +    case SCSIOP_INQUIRY:
 19.1049 +      //KdPrint((__DRIVER_NAME "     Command = INQUIRY (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
 19.1050 +      if ((Srb->Cdb[1] & 1) == 0)
 19.1051 +      {
 19.1052 +        memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
 19.1053 +        DataBuffer = Srb->DataBuffer;
 19.1054 +        DataBuffer[0] = 0x00; // disk
 19.1055 +        DataBuffer[1] = 0x00; // not removable
 19.1056 +        memcpy(DataBuffer + 8, "James", 5); // vendor id
 19.1057 +        memcpy(DataBuffer + 16, "XenVBD", 6); // product id
 19.1058 +        Srb->SrbStatus = SRB_STATUS_SUCCESS;
 19.1059 +      }
 19.1060 +      else
 19.1061 +      {
 19.1062 +        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
 19.1063 +      }
 19.1064 +      Srb->ScsiStatus = 0;
 19.1065 +      status = STATUS_SUCCESS;
 19.1066 +      Irp->IoStatus.Status = status;
 19.1067 +      Irp->IoStatus.Information = 0;
 19.1068 +      IoCompleteRequest(Irp, IO_NO_INCREMENT);
 19.1069 +      break;
 19.1070 +    case SCSIOP_READ_CAPACITY:
 19.1071 +      DataBuffer = Srb->DataBuffer;
 19.1072 +      DataBuffer[0] = (unsigned char)(ChildDeviceData->TotalSectors >> 24) & 0xff;
 19.1073 +      DataBuffer[1] = (unsigned char)(ChildDeviceData->TotalSectors >> 16) & 0xff;
 19.1074 +      DataBuffer[2] = (unsigned char)(ChildDeviceData->TotalSectors >> 8) & 0xff;
 19.1075 +      DataBuffer[3] = (unsigned char)(ChildDeviceData->TotalSectors >> 0) & 0xff;
 19.1076 +      DataBuffer[4] = 0x00;
 19.1077 +      DataBuffer[5] = 0x00;
 19.1078 +      DataBuffer[6] = 0x02;
 19.1079 +      DataBuffer[7] = 0x00;
 19.1080 +      Srb->ScsiStatus = 0;
 19.1081 +      Srb->SrbStatus = SRB_STATUS_SUCCESS;
 19.1082 +      status = STATUS_SUCCESS;
 19.1083 +      Irp->IoStatus.Status = status;
 19.1084 +      Irp->IoStatus.Information = 0;
 19.1085 +      IoCompleteRequest(Irp, IO_NO_INCREMENT);
 19.1086 +      break;
 19.1087 +    case SCSIOP_MODE_SENSE:
 19.1088 +      //KdPrint((__DRIVER_NAME "     Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", Srb->Cdb[1] & 0x10, Srb->Cdb[2] & 0xC0, Srb->Cdb[2] & 0x3F));
 19.1089 +      switch(Srb->Cdb[2] & 0x3F)
 19.1090 +      {
 19.1091 +      default:
 19.1092 +        memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
 19.1093 +        Srb->ScsiStatus = 0;
 19.1094 +        Srb->SrbStatus = SRB_STATUS_SUCCESS;
 19.1095 +        status = STATUS_SUCCESS;
 19.1096 +        Irp->IoStatus.Status = status;
 19.1097 +        Irp->IoStatus.Information = Srb->DataTransferLength;
 19.1098 +        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 19.1099 +      }
 19.1100 +      break;
 19.1101 +    case SCSIOP_READ:
 19.1102 +    case SCSIOP_WRITE:
 19.1103 +      IoMarkIrpPending(Irp);
 19.1104 +
 19.1105 +      //KdPrint((__DRIVER_NAME "     Irp Acquiring Lock\n"));
 19.1106 +      KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
 19.1107 +      //KdPrint((__DRIVER_NAME "A    Got It\n"));
 19.1108 +
 19.1109 +      if (RING_FULL(&ChildDeviceData->Ring))
 19.1110 +      {
 19.1111 +        //KdPrint((__DRIVER_NAME "A    Inserting into list\n"));
 19.1112 +        ListEntry = (XenVbd_ListEntry *)ExAllocatePoolWithTag(NonPagedPool, sizeof(XenVbd_ListEntry), XENVBD_POOL_TAG);
 19.1113 +        //KdPrint((__DRIVER_NAME "     Allocate ListEntry = %08x\n", ListEntry));
 19.1114 +        if (ListEntry == NULL)
 19.1115 +        {
 19.1116 +          KdPrint((__DRIVER_NAME "     CANNOT ALLOCATE MEMORY FOR ListEntry!!!\n"));
 19.1117 +        }
 19.1118 +        ListEntry->Irp = Irp;
 19.1119 +        InsertTailList(&ChildDeviceData->IrpListHead, &ListEntry->Entry);
 19.1120 +        //ChildDeviceData->IrpAddedToList++;
 19.1121 +      }
 19.1122 +      else
 19.1123 +      {
 19.1124 +        XenVbd_PutIrpOnRing(Device, Irp);
 19.1125 +        //KdPrint((__DRIVER_NAME "     WdmIrpPreprocessSCSI (AddedToList = %d, RemovedFromList = %d, AddedToRing = %d, AddedToRingAtLastNotify = %d, AddedToRingAtLastInterrupt = %d, AddedToRingAtLastDpc = %d, RemovedFromRing = %d, IrpCompleted = %d)\n", ChildDeviceData->IrpAddedToList, ChildDeviceData->IrpRemovedFromList, ChildDeviceData->IrpAddedToRing, ChildDeviceData->IrpAddedToRingAtLastNotify, ChildDeviceData->IrpAddedToRingAtLastInterrupt, ChildDeviceData->IrpAddedToRingAtLastDpc, ChildDeviceData->IrpRemovedFromRing, ChildDeviceData->IrpCompleted));
 19.1126 +      }
 19.1127 +      KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
 19.1128 +      status = STATUS_PENDING;
 19.1129 +      break;
 19.1130 +    default:
 19.1131 +      status = STATUS_NOT_IMPLEMENTED;
 19.1132 +      Irp->IoStatus.Status = status;
 19.1133 +      Irp->IoStatus.Information = 0;
 19.1134 +      IoCompleteRequest(Irp, IO_NO_INCREMENT);
 19.1135 +      KdPrint((__DRIVER_NAME "     Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
 19.1136 +      break;
 19.1137 +    }
 19.1138 +    //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
 19.1139 +    break;
 19.1140 +  case SRB_FUNCTION_CLAIM_DEVICE:
 19.1141 +    //KdPrint((__DRIVER_NAME "     SRB_FUNCTION_CLAIM_DEVICE\n"));
 19.1142 +    ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
 19.1143 +    Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
 19.1144 +    Srb->SrbStatus = SRB_STATUS_SUCCESS;
 19.1145 +    status = STATUS_SUCCESS;
 19.1146 +    Irp->IoStatus.Status = status;
 19.1147 +    Irp->IoStatus.Information = 0;
 19.1148 +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 19.1149 +    break;
 19.1150 +  case SRB_FUNCTION_IO_CONTROL:
 19.1151 +    //KdPrint((__DRIVER_NAME "     SRB_FUNCTION_IO_CONTROL\n"));
 19.1152 +    //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
 19.1153 +    Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
 19.1154 +    status = STATUS_NOT_IMPLEMENTED;
 19.1155 +    //Irp->IoStatus.Status = status;
 19.1156 +    //Irp->IoStatus.Information = 0;
 19.1157 +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 19.1158 +    break;
 19.1159 +  case SRB_FUNCTION_FLUSH:
 19.1160 +    Srb->SrbStatus = SRB_STATUS_SUCCESS;
 19.1161 +    status = STATUS_SUCCESS;
 19.1162 +    Irp->IoStatus.Status = status;
 19.1163 +    Irp->IoStatus.Information = 0;
 19.1164 +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 19.1165 +    break;
 19.1166 +  default:
 19.1167 +    KdPrint((__DRIVER_NAME "     Unhandled Srb->Function = %08X\n", Srb->Function));
 19.1168 +    status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
 19.1169 +    break;
 19.1170 +  }
 19.1171 +
 19.1172 +  //KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI (AddedToList = %d, RemovedFromList = %d, AddedToRing = %d, AddedToRingAtLastNotify = %d, AddedToRingAtLastInterrupt = %d, RemovedFromRing = %d)\n", ChildDeviceData->IrpAddedToList, ChildDeviceData->IrpRemovedFromList, ChildDeviceData->IrpAddedToRing, ChildDeviceData->IrpAddedToRingAtLastNotify, ChildDeviceData->IrpAddedToRingAtLastInterrupt, ChildDeviceData->IrpCompleted));
 19.1173 +  //KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI\n"));
 19.1174 +
 19.1175 +  return status;
 19.1176 +}
 19.1177 +
 19.1178 +static VOID 
 19.1179 +XenVbd_Child_IoDefault(WDFQUEUE  Queue, WDFREQUEST  Request)
 19.1180 +{
 19.1181 +  UNREFERENCED_PARAMETER(Queue);
 19.1182 +
 19.1183 +  //KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
 19.1184 +
 19.1185 +  WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
 19.1186 +
 19.1187 +  //KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
 19.1188 +}
 19.1189 +
 19.1190 +static VOID 
 19.1191 +XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode)
 19.1192 +{
 19.1193 +  WDFDEVICE Device;
 19.1194 +  PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;  
 19.1195 +  PIRP Irp;
 19.1196 +  PSTORAGE_PROPERTY_QUERY Spq;
 19.1197 +  PSTORAGE_ADAPTER_DESCRIPTOR Sad;
 19.1198 +  PSTORAGE_DEVICE_DESCRIPTOR Sdd;
 19.1199 +  PSCSI_ADDRESS Sa;
 19.1200 +
 19.1201 +  UNREFERENCED_PARAMETER(Queue);
 19.1202 +  //UNREFERENCED_PARAMETER(Request);
 19.1203 +  UNREFERENCED_PARAMETER(OutputBufferLength);
 19.1204 +  UNREFERENCED_PARAMETER(InputBufferLength);
 19.1205 +
 19.1206 +  Device = WdfIoQueueGetDevice(Queue);
 19.1207 +
 19.1208 +  ChildDeviceData = *GetChildDeviceData(Device);
 19.1209 +
 19.1210 +  //KdPrint((__DRIVER_NAME " --> IoDeviceControl\n"));
 19.1211 +  //KdPrint((__DRIVER_NAME "     InputBufferLength = %d\n", InputBufferLength));
 19.1212 +  //KdPrint((__DRIVER_NAME "     OutputBufferLength = %d\n", OutputBufferLength));
 19.1213 +
 19.1214 +  Irp = WdfRequestWdmGetIrp(Request);
 19.1215 +
 19.1216 +  switch (IoControlCode)
 19.1217 +  {
 19.1218 +  case IOCTL_STORAGE_QUERY_PROPERTY:
 19.1219 +    //KdPrint((__DRIVER_NAME "     IOCTL_STORAGE_QUERY_PROPERTY\n"));    
 19.1220 +    Spq = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
 19.1221 +    if (Spq->PropertyId == StorageAdapterProperty && Spq->QueryType == PropertyStandardQuery)
 19.1222 +    {
 19.1223 +      //KdPrint((__DRIVER_NAME "     PropertyId = StorageAdapterProperty, QueryType = PropertyStandardQuery\n"));
 19.1224 +      if (OutputBufferLength >= 8)
 19.1225 +      {
 19.1226 +        Sad = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
 19.1227 +        Sad->Version = 1;
 19.1228 +        Sad->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
 19.1229 +        if (OutputBufferLength >= sizeof(STORAGE_ADAPTER_DESCRIPTOR))
 19.1230 +        {
 19.1231 +          Sad->MaximumTransferLength = 45056;
 19.1232 +          Sad->MaximumPhysicalPages = 11;
 19.1233 +          Sad->AlignmentMask = 0;
 19.1234 +          Sad->AdapterUsesPio = FALSE;
 19.1235 +          Sad->AdapterScansDown = FALSE;
 19.1236 +          Sad->CommandQueueing = FALSE;
 19.1237 +          Sad->AcceleratedTransfer = FALSE;
 19.1238 +          Sad->BusType = BusTypeScsi;
 19.1239 +          Sad->BusMajorVersion = 0;
 19.1240 +          Sad->BusMinorVersion = 0;
 19.1241 +        }
 19.1242 +      }
 19.1243 +      WdfRequestComplete(Request, STATUS_SUCCESS);
 19.1244 +    }
 19.1245 +    else if (Spq->PropertyId == StorageDeviceProperty && Spq->QueryType == PropertyStandardQuery)
 19.1246 +    {
 19.1247 +      //KdPrint((__DRIVER_NAME "     PropertyId = StorageDeviceProperty, QueryType = PropertyStandardQuery\n"));
 19.1248 +      if (OutputBufferLength >= 8)
 19.1249 +      {
 19.1250 +        Sdd = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
 19.1251 +        Sdd->Version = 1;
 19.1252 +        Sdd->Size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 31 - 1;
 19.1253 +        // 0       0        1         2       3
 19.1254 +        // 0       7        5         4       1
 19.1255 +        //"VENDOR\0PRODUCT\0Revision\0Serial\0"
 19.1256 +        if (OutputBufferLength >= sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 31)
 19.1257 +        {
 19.1258 +          Sdd->DeviceType = 0x00;
 19.1259 +          Sdd->DeviceTypeModifier = 0x00;
 19.1260 +          Sdd->RemovableMedia = FALSE;
 19.1261 +          Sdd->CommandQueueing = FALSE;
 19.1262 +          Sdd->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 0;
 19.1263 +          Sdd->ProductIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 7;
 19.1264 +          Sdd->ProductRevisionOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 15;
 19.1265 +          Sdd->SerialNumberOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 24;
 19.1266 +          Sdd->BusType = BusTypeScsi;
 19.1267 +          Sdd->RawPropertiesLength = 31;
 19.1268 +          memcpy(Sdd->RawDeviceProperties, "VENDOR\0PRODUCT\0Revision\0Serial\0", 31);
 19.1269 +        }
 19.1270 +      }
 19.1271 +      WdfRequestComplete(Request, STATUS_SUCCESS);
 19.1272 +    }
 19.1273 +    else
 19.1274 +    {
 19.1275 +      switch (Spq->PropertyId)
 19.1276 +      {
 19.1277 +      case StorageDeviceProperty:
 19.1278 +        //KdPrint((__DRIVER_NAME "     StorageDeviceProperty\n"));
 19.1279 +        break;        
 19.1280 +      case StorageAccessAlignmentProperty:
 19.1281 +        //KdPrint((__DRIVER_NAME "     StorageAccessAlignmentProperty\n"));
 19.1282 +        break;
 19.1283 +      case StorageAdapterProperty:
 19.1284 +        //KdPrint((__DRIVER_NAME "     StorageAdapterProperty\n"));
 19.1285 +         break;
 19.1286 +      case StorageDeviceIdProperty:
 19.1287 +        //KdPrint((__DRIVER_NAME "     StorageDeviceIdProperty\n"));
 19.1288 +         break;
 19.1289 +      case StorageDeviceUniqueIdProperty:
 19.1290 +        //KdPrint((__DRIVER_NAME "     StorageDeviceUniqueIdProperty\n"));
 19.1291 +        break;
 19.1292 +      case StorageDeviceWriteCacheProperty:
 19.1293 +        //KdPrint((__DRIVER_NAME "     StorageDeviceWriteCacheProperty\n"));
 19.1294 +        break;
 19.1295 +      default:
 19.1296 +        //KdPrint((__DRIVER_NAME "     Unknown Property %08x\n", Spq->PropertyId));
 19.1297 +         break;
 19.1298 +      }
 19.1299 +      switch (Spq->QueryType)
 19.1300 +      {
 19.1301 +      case PropertyStandardQuery:
 19.1302 +        //KdPrint((__DRIVER_NAME "     PropertyStandardQuery\n"));
 19.1303 +        break;        
 19.1304 +       //case PropertyIncludeSwIds:
 19.1305 +      //  //KdPrint((__DRIVER_NAME "     PropertyIncludeSwIds\n"));
 19.1306 +      //  break;        
 19.1307 +      case PropertyExistsQuery:
 19.1308 +        //KdPrint((__DRIVER_NAME "     PropertyExistsQuery\n"));
 19.1309 +        break;        
 19.1310 +      default:
 19.1311 +        //KdPrint((__DRIVER_NAME "     Unknown Query %08x\n", Spq->QueryType));
 19.1312 +        break;
 19.1313 +      }
 19.1314 +      WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
 19.1315 +    }
 19.1316 +    break;
 19.1317 +  // http://www.osronline.com/article.cfm?article=229
 19.1318 +  // 0x00070000 device = 0x70, Function = 0x000 = IOCTL_DISK_GET_DRIVE_GEOMETRY
 19.1319 +  // 0x00041018 device = 0x04, function = 0x406 = IOCTL_SCSI_GET_ADDRESS 
 19.1320 +  // 0x00049400 device = 0x04, function = 0x500 = ???IOCTL_STORAGE_QUERY_PROPERTY
 19.1321 +  // 0x00560030 device = 0x56, Function = 0x00c = 
 19.1322 +  case IOCTL_DISK_GET_DRIVE_GEOMETRY:
 19.1323 +    KdPrint((__DRIVER_NAME "     IOCTL_DISK_GET_DRIVE_GEOMETRY\n"));
 19.1324 +    memcpy(Irp->AssociatedIrp.SystemBuffer, &ChildDeviceData->Geometry, sizeof(DISK_GEOMETRY));
 19.1325 +    WdfRequestComplete(Request, STATUS_SUCCESS);
 19.1326 +    break;
 19.1327 +  case IOCTL_SCSI_GET_ADDRESS:
 19.1328 +    //KdPrint((__DRIVER_NAME "     IOCTL_SCSI_GET_ADDRESS\n"));
 19.1329 +    Sa = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
 19.1330 +    Sa->Length = sizeof(SCSI_ADDRESS);
 19.1331 +    Sa->PortNumber = 0;
 19.1332 +    Sa->PathId = 0;
 19.1333 +    Sa->TargetId = 0;
 19.1334 +    Sa->Lun = 0;
 19.1335 +    WdfRequestComplete(Request, STATUS_SUCCESS);
 19.1336 +    break;
 19.1337 +  default:
 19.1338 +    //KdPrint((__DRIVER_NAME "     Not Implemented IoControlCode=%08X\n", IoControlCode));
 19.1339 +    WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
 19.1340 +    break;
 19.1341 +  }
 19.1342 +
 19.1343 +  //KdPrint((__DRIVER_NAME " <-- IoDeviceControl\n"));
 19.1344 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/xenvbd/xenvbd.h	Sat Nov 10 14:40:56 2007 +1100
    20.3 @@ -0,0 +1,105 @@
    20.4 +#if !defined(_XENBUS_H_)
    20.5 +#define _XENBUS_H_
    20.6 +
    20.7 +#include <ntddk.h>
    20.8 +#include <wdm.h>
    20.9 +#include <wdf.h>
   20.10 +#include <initguid.h>
   20.11 +#include <ntdddisk.h>
   20.12 +
   20.13 +#define NTSTRSAFE_LIB
   20.14 +#include <ntstrsafe.h>
   20.15 +
   20.16 +#include <xen_windows.h>
   20.17 +#include <memory.h>
   20.18 +#include <grant_table.h>
   20.19 +#include <event_channel.h>
   20.20 +#include <hvm/params.h>
   20.21 +#include <hvm/hvm_op.h>
   20.22 +#include <evtchn_public.h>
   20.23 +#include <xenbus_public.h>
   20.24 +#include <io/ring.h>
   20.25 +#include <io/blkif.h>
   20.26 +#define __DRIVER_NAME "XenVbd"
   20.27 +#define XENVBD_POOL_TAG (ULONG) 'XenP'
   20.28 +
   20.29 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
   20.30 +#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
   20.31 +
   20.32 +typedef struct {
   20.33 +  blkif_request_t req;
   20.34 +  //int Id;
   20.35 +  PIRP Irp;
   20.36 +  PMDL Mdl;
   20.37 +  VOID *Buf;
   20.38 +  //int nr_segments;
   20.39 +  //unsigned long gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   20.40 +} blkif_shadow_t;
   20.41 +
   20.42 +typedef struct {
   20.43 +  LIST_ENTRY Entry;
   20.44 +  PIRP Irp;
   20.45 +} XenVbd_ListEntry;
   20.46 +
   20.47 +/*
   20.48 +typedef struct _XENVBD_QUEUE_DATA {
   20.49 +    XENVBD_CHILD_DEVICE_DATA DeviceData;
   20.50 +} XENVBD_QUEUE_DATA, *PXENVBD_QUEUE_DATA;
   20.51 +
   20.52 +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENVBD_QUEUE_DATA, GetQueueData)
   20.53 +*/
   20.54 +
   20.55 +//typedef unsigned long xenbus_transaction_t;
   20.56 +//typedef uint32_t XENSTORE_RING_IDX;
   20.57 +
   20.58 +extern XEN_IFACE_EVTCHN EvtChnInterface;
   20.59 +extern XEN_IFACE_XENBUS XenBusInterface;
   20.60 +
   20.61 +struct {
   20.62 +  LIST_ENTRY Entry;
   20.63 +  KSPIN_LOCK Lock;
   20.64 +  WDFQUEUE IoDefaultQueue;
   20.65 +  WDFDEVICE Device;
   20.66 +  char Path[128];
   20.67 +  char BackendPath[128];
   20.68 +  ULONG DeviceIndex;
   20.69 +  evtchn_port_t EventChannel;
   20.70 +  //blkif_sring_t *SharedRing;
   20.71 +  ULONG RingBufPFN;
   20.72 +  int BackendState;
   20.73 +  int FrontendState;
   20.74 +  blkif_front_ring_t Ring;
   20.75 +  blkif_shadow_t *shadow;
   20.76 +  uint64_t shadow_free;
   20.77 +
   20.78 +  LIST_ENTRY IrpListHead;
   20.79 +  KSPIN_LOCK IrpListLock;
   20.80 +
   20.81 +  WDFDPC Dpc;
   20.82 +
   20.83 +  ULONG BytesPerSector;
   20.84 +  ULONGLONG TotalSectors;
   20.85 +  DISK_GEOMETRY Geometry;
   20.86 +
   20.87 +  //int IrpAddedToList;
   20.88 +  //int IrpRemovedFromList;
   20.89 +  //int IrpAddedToRing;
   20.90 +  //int IrpAddedToRingAtLastNotify;
   20.91 +  //int IrpAddedToRingAtLastInterrupt;
   20.92 +  //int IrpAddedToRingAtLastDpc;
   20.93 +  //int IrpRemovedFromRing;
   20.94 +  //int IrpCompleted;
   20.95 +
   20.96 +} typedef XENVBD_CHILD_DEVICE_DATA, *PXENVBD_CHILD_DEVICE_DATA, **PPXENVBD_CHILD_DEVICE_DATA;
   20.97 +
   20.98 +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PXENVBD_CHILD_DEVICE_DATA, GetChildDeviceData);
   20.99 +
  20.100 +typedef struct _XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION
  20.101 +{
  20.102 +  WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Header;
  20.103 +  PXENVBD_CHILD_DEVICE_DATA DeviceData;
  20.104 +  //ULONG DeviceIndex;
  20.105 +  //char Path[128];
  20.106 +} XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION, *PXENVBD_DEVICE_IDENTIFICATION_DESCRIPTION;
  20.107 +
  20.108 +#endif