2 * Copyright (C) 2009, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
3 * Copyright 2006-2008, V.
4 * For WinAoE contact information, see http://winaoe.org/
6 * This file is part of WinVBlock, derived from WinAoE.
8 * WinVBlock is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * WinVBlock is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with WinVBlock. If not, see <http://www.gnu.org/licenses/>.
31 #include "winvblock.h"
45 static irp__handler_decl (
46 Bus_DispatchNotSupported
48 static irp__handler_decl (
51 winvblock__bool STDCALL Bus_AddChild (
52 IN PDEVICE_OBJECT BusDeviceObject,
54 IN winvblock__bool Boot
56 static NTSTATUS STDCALL Bus_IoCompletionRoutine (
57 IN PDEVICE_OBJECT DeviceObject,
62 typedef struct _BUS_TARGETLIST
65 struct _BUS_TARGETLIST *Next;
69 static PBUS_TARGETLIST Bus_Globals_TargetList = NULL;
70 static KSPIN_LOCK Bus_Globals_TargetListSpinLock;
71 static ULONG Bus_Globals_NextDisk = 0;
72 PDEVICE_OBJECT bus__fdo = NULL;
80 KeInitializeSpinLock ( &Bus_Globals_TargetListSpinLock );
81 return STATUS_SUCCESS;
89 UNICODE_STRING DosDeviceName;
90 PBUS_TARGETLIST Walker,
95 KeAcquireSpinLock ( &Bus_Globals_TargetListSpinLock, &Irql );
96 Walker = Bus_Globals_TargetList;
97 while ( Walker != NULL )
100 ExFreePool ( Walker );
103 KeReleaseSpinLock ( &Bus_Globals_TargetListSpinLock, Irql );
104 RtlInitUnicodeString ( &DosDeviceName, L"\\DosDevices\\AoE" );
105 IoDeleteSymbolicLink ( &DosDeviceName );
111 IN winvblock__uint8_ptr ClientMac,
112 IN winvblock__uint8_ptr ServerMac,
113 winvblock__uint16 Major,
114 winvblock__uint8 Minor,
118 PBUS_TARGETLIST Walker,
122 KeAcquireSpinLock ( &Bus_Globals_TargetListSpinLock, &Irql );
123 Last = Bus_Globals_TargetList;
124 Walker = Bus_Globals_TargetList;
125 while ( Walker != NULL )
127 if ( ( RtlCompareMemory ( &Walker->Target.ClientMac, ClientMac, 6 ) ==
129 && ( RtlCompareMemory ( &Walker->Target.ServerMac, ServerMac, 6 ) ==
130 6 ) && Walker->Target.Major == Major
131 && Walker->Target.Minor == Minor )
133 if ( Walker->Target.LBASize != LBASize )
135 DBG ( "LBASize changed for e%d.%d " "(%I64u->%I64u)\n", Major,
136 Minor, Walker->Target.LBASize, LBASize );
137 Walker->Target.LBASize = LBASize;
139 KeQuerySystemTime ( &Walker->Target.ProbeTime );
140 KeReleaseSpinLock ( &Bus_Globals_TargetListSpinLock, Irql );
144 Walker = Walker->Next;
148 ( PBUS_TARGETLIST ) ExAllocatePool ( NonPagedPool,
149 sizeof ( BUS_TARGETLIST ) ) ) ==
152 DBG ( "ExAllocatePool Target\n" );
153 KeReleaseSpinLock ( &Bus_Globals_TargetListSpinLock, Irql );
157 RtlCopyMemory ( Walker->Target.ClientMac, ClientMac, 6 );
158 RtlCopyMemory ( Walker->Target.ServerMac, ServerMac, 6 );
159 Walker->Target.Major = Major;
160 Walker->Target.Minor = Minor;
161 Walker->Target.LBASize = LBASize;
162 KeQuerySystemTime ( &Walker->Target.ProbeTime );
166 Bus_Globals_TargetList = Walker;
172 KeReleaseSpinLock ( &Bus_Globals_TargetListSpinLock, Irql );
176 Bus_CleanupTargetList (
183 * Establish a pointer into the bus device's extension space
185 bus__type_ptr STDCALL
187 driver__dev_ext_ptr dev_ext_ptr
190 winvblock__uint8_ptr tmp = ( winvblock__uint8_ptr ) dev_ext_ptr;
191 bus__type_ptr bus_ptr =
192 ( bus__type_ptr ) ( tmp + sizeof ( driver__dev_ext ) );
197 * Establish a pointer into the child disk device's extension space
199 disk__type_ptr STDCALL
201 driver__dev_ext_ptr dev_ext_ptr
204 winvblock__uint8_ptr tmp = ( winvblock__uint8_ptr ) dev_ext_ptr;
205 disk__type_ptr disk_ptr =
206 ( disk__type_ptr ) ( tmp + sizeof ( driver__dev_ext ) );
211 * Add a child node to the bus
213 * @v BusDeviceObject The bus to add the node to
214 * @v Disk The disk to add
215 * @v Boot Is this a boot device?
217 * Returns TRUE for success, FALSE for failure
219 winvblock__bool STDCALL
221 IN PDEVICE_OBJECT BusDeviceObject,
223 IN winvblock__bool Boot
227 * @v Status Status of last operation
228 * @v BusDeviceExtension Shortcut to the bus' device extension
229 * @v DeviceObject The new node's device object
230 * @v DeviceExtension The new node's device extension
231 * @v Walker Walks the child nodes
234 PDEVICE_OBJECT DeviceObject;
235 driver__dev_ext_ptr bus_dev_ext_ptr,
237 bus__type_ptr bus_ptr;
238 size_t new_dev_ext_size;
239 disk__type_ptr disk_ptr,
241 DEVICE_TYPE DiskType =
242 Disk.DiskType == OpticalDisc ? FILE_DEVICE_CD_ROM : FILE_DEVICE_DISK;
245 OpticalDisc ? FILE_READ_ONLY_DEVICE | FILE_REMOVABLE_MEDIA : Disk.DiskType
246 == FloppyDisk ? FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE : 0;
250 * Establish pointers into the bus device's extension space
252 bus_dev_ext_ptr = ( driver__dev_ext_ptr ) BusDeviceObject->DeviceExtension;
253 bus_ptr = get_bus_ptr ( bus_dev_ext_ptr );
255 * Create the child device
258 sizeof ( driver__dev_ext ) + sizeof ( disk__type ) +
259 driver__handling_table_size;
262 IoCreateDevice ( bus_dev_ext_ptr->DriverObject, new_dev_ext_size,
264 FILE_AUTOGENERATED_DEVICE_NAME |
265 FILE_DEVICE_SECURE_OPEN | DiskType2, FALSE,
268 Error ( "Bus_AddChild IoCreateDevice", Status );
272 * Establish pointers into the child disk device's extension space
274 disk_dev_ext_ptr = ( driver__dev_ext_ptr ) DeviceObject->DeviceExtension;
275 disk_ptr = get_disk_ptr ( disk_dev_ext_ptr );
277 * Clear the extension space and establish parameters
279 RtlZeroMemory ( disk_dev_ext_ptr, new_dev_ext_size );
280 disk_dev_ext_ptr->IsBus = FALSE;
281 disk_dev_ext_ptr->dispatch = Disk_Dispatch;
282 disk_dev_ext_ptr->Self = DeviceObject;
283 disk_dev_ext_ptr->DriverObject = bus_dev_ext_ptr->DriverObject;
284 disk_dev_ext_ptr->State = NotStarted;
285 disk_dev_ext_ptr->OldState = NotStarted;
286 disk_dev_ext_ptr->irp_handler_stack_ptr =
287 ( winvblock__uint8 * ) disk_dev_ext_ptr + sizeof ( driver__dev_ext ) +
288 sizeof ( disk__type );
289 RtlCopyMemory ( disk_dev_ext_ptr->irp_handler_stack_ptr,
290 driver__handling_table, driver__handling_table_size );
291 disk_dev_ext_ptr->irp_handler_stack_size =
292 driver__handling_table_size / sizeof ( irp__handling );
294 * Copy the provided disk parameters into the disk extension space
296 RtlCopyMemory ( disk_ptr, &Disk, sizeof ( disk__type ) );
297 disk_ptr->dev_ext_ptr = disk_dev_ext_ptr;
298 disk_ptr->Parent = BusDeviceObject;
299 disk_ptr->next_sibling_ptr = NULL;
300 KeInitializeEvent ( &disk_ptr->SearchEvent, SynchronizationEvent, FALSE );
301 KeInitializeSpinLock ( &disk_ptr->SpinLock );
302 disk_ptr->BootDrive = Boot;
303 disk_ptr->Unmount = FALSE;
304 disk_ptr->DiskNumber = InterlockedIncrement ( &Bus_Globals_NextDisk ) - 1;
306 * Some device parameters
308 DeviceObject->Flags |= DO_DIRECT_IO; /* FIXME? */
309 DeviceObject->Flags |= DO_POWER_INRUSH; /* FIXME? */
311 * Determine the disk's geometry differently for AoE/MEMDISK
313 disk_ptr->Initialize ( disk_dev_ext_ptr );
315 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
317 * Add the new device's extension to the bus' list of children
319 if ( bus_ptr->first_child_ptr == NULL )
321 bus_ptr->first_child_ptr = disk_ptr;
325 Walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
326 while ( Walker->next_sibling_ptr != NULL )
327 Walker = Walker->next_sibling_ptr;
328 Walker->next_sibling_ptr = disk_ptr;
341 bus__type_ptr bus_ptr;
343 bus_ptr = get_bus_ptr ( DeviceExtension );
344 KeInitializeEvent ( &event, NotificationEvent, FALSE );
345 IoCopyCurrentIrpStackLocationToNext ( Irp );
346 IoSetCompletionRoutine ( Irp,
347 ( PIO_COMPLETION_ROUTINE ) Bus_IoCompletionRoutine,
348 ( PVOID ) & event, TRUE, TRUE, TRUE );
349 status = IoCallDriver ( bus_ptr->LowerDeviceObject, Irp );
350 if ( status == STATUS_PENDING )
353 KeWaitForSingleObject ( &event, Executive, KernelMode, FALSE, NULL );
355 if ( NT_SUCCESS ( status = Irp->IoStatus.Status ) )
357 DeviceExtension->OldState = DeviceExtension->State;
358 DeviceExtension->State = Started;
360 status = STATUS_SUCCESS;
361 Irp->IoStatus.Status = status;
362 IoCompleteRequest ( Irp, IO_NO_INCREMENT );
363 *completion_ptr = TRUE;
372 DBG ( "BUS PNP test\n" );
373 return STATUS_SUCCESS;
376 irp__handling handling_table[] = {
378 * Major, minor, any major?, any minor?, handler
379 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
380 * Note that the fall-through case must come FIRST!
381 * Why? It sets completion to true, so others won't be called
383 {IRP_MJ_PNP, IRP_MN_START_DEVICE, FALSE, FALSE, pnp_start_dev}
385 {IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_RELATIONS, FALSE, FALSE, foo}
388 size_t handling_table_size = sizeof ( handling_table );
390 irp__handler_decl ( Bus_DispatchPnP )
394 PDEVICE_RELATIONS DeviceRelations;
395 bus__type_ptr bus_ptr;
396 disk__type_ptr Walker,
401 * Establish a pointer into the bus device's extension space
403 bus_ptr = get_bus_ptr ( DeviceExtension );
405 switch ( Stack->MinorFunction )
407 case IRP_MN_REMOVE_DEVICE:
408 DeviceExtension->OldState = DeviceExtension->State;
409 DeviceExtension->State = Deleted;
410 Irp->IoStatus.Information = 0;
411 Irp->IoStatus.Status = STATUS_SUCCESS;
412 IoSkipCurrentIrpStackLocation ( Irp );
413 Status = IoCallDriver ( bus_ptr->LowerDeviceObject, Irp );
414 Walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
415 while ( Walker != NULL )
417 Next = Walker->next_sibling_ptr;
418 IoDeleteDevice ( Walker->dev_ext_ptr->Self );
421 bus_ptr->Children = 0;
422 bus_ptr->first_child_ptr = NULL;
423 IoDetachDevice ( bus_ptr->LowerDeviceObject );
424 IoDeleteDevice ( DeviceExtension->Self );
426 case IRP_MN_QUERY_DEVICE_RELATIONS:
427 if ( Stack->Parameters.QueryDeviceRelations.Type != BusRelations
428 || Irp->IoStatus.Information )
430 Status = Irp->IoStatus.Status;
434 Walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
435 while ( Walker != NULL )
438 Walker = Walker->next_sibling_ptr;
441 ( PDEVICE_RELATIONS ) ExAllocatePool ( NonPagedPool,
442 sizeof ( DEVICE_RELATIONS ) +
443 ( sizeof ( PDEVICE_OBJECT ) *
445 if ( DeviceRelations == NULL )
447 Irp->IoStatus.Information = 0;
448 Status = STATUS_INSUFFICIENT_RESOURCES;
451 DeviceRelations->Count = Count;
454 Walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
455 while ( Walker != NULL )
457 ObReferenceObject ( Walker->dev_ext_ptr->Self );
458 DeviceRelations->Objects[Count] = Walker->dev_ext_ptr->Self;
460 Walker = Walker->next_sibling_ptr;
462 Irp->IoStatus.Information = ( ULONG_PTR ) DeviceRelations;
463 Status = STATUS_SUCCESS;
465 case IRP_MN_QUERY_PNP_DEVICE_STATE:
466 Irp->IoStatus.Information = 0;
467 Status = STATUS_SUCCESS;
469 case IRP_MN_QUERY_STOP_DEVICE:
470 DeviceExtension->OldState = DeviceExtension->State;
471 DeviceExtension->State = StopPending;
472 Status = STATUS_SUCCESS;
474 case IRP_MN_CANCEL_STOP_DEVICE:
475 DeviceExtension->State = DeviceExtension->OldState;
476 Status = STATUS_SUCCESS;
478 case IRP_MN_STOP_DEVICE:
479 DeviceExtension->OldState = DeviceExtension->State;
480 DeviceExtension->State = Stopped;
481 Status = STATUS_SUCCESS;
483 case IRP_MN_QUERY_REMOVE_DEVICE:
484 DeviceExtension->OldState = DeviceExtension->State;
485 DeviceExtension->State = RemovePending;
486 Status = STATUS_SUCCESS;
488 case IRP_MN_CANCEL_REMOVE_DEVICE:
489 DeviceExtension->State = DeviceExtension->OldState;
490 Status = STATUS_SUCCESS;
492 case IRP_MN_SURPRISE_REMOVAL:
493 DeviceExtension->OldState = DeviceExtension->State;
494 DeviceExtension->State = SurpriseRemovePending;
495 Status = STATUS_SUCCESS;
498 Status = Irp->IoStatus.Status;
501 Irp->IoStatus.Status = Status;
502 IoSkipCurrentIrpStackLocation ( Irp );
503 Status = IoCallDriver ( bus_ptr->LowerDeviceObject, Irp );
507 irp__handler_decl ( Bus_DispatchDeviceControl )
510 winvblock__uint8_ptr Buffer;
512 PBUS_TARGETLIST TargetWalker;
513 bus__type_ptr bus_ptr;
514 disk__type_ptr DiskWalker,
516 PMOUNT_TARGETS Targets;
522 * Establish a pointer into the bus device's extension space
524 bus_ptr = get_bus_ptr ( DeviceExtension );
526 switch ( Stack->Parameters.DeviceIoControl.IoControlCode )
529 DBG ( "Got IOCTL_AOE_SCAN...\n" );
531 KeAcquireSpinLock ( &Bus_Globals_TargetListSpinLock, &Irql );
534 TargetWalker = Bus_Globals_TargetList;
535 while ( TargetWalker != NULL )
538 TargetWalker = TargetWalker->Next;
542 ( PMOUNT_TARGETS ) ExAllocatePool ( NonPagedPool,
543 sizeof ( MOUNT_TARGETS ) +
546 ( MOUNT_TARGET ) ) ) ) ==
549 DBG ( "ExAllocatePool Targets\n" );
550 Irp->IoStatus.Information = 0;
551 Status = STATUS_INSUFFICIENT_RESOURCES;
554 Irp->IoStatus.Information =
555 sizeof ( MOUNT_TARGETS ) + ( Count * sizeof ( MOUNT_TARGET ) );
556 Targets->Count = Count;
559 TargetWalker = Bus_Globals_TargetList;
560 while ( TargetWalker != NULL )
562 RtlCopyMemory ( &Targets->Target[Count], &TargetWalker->Target,
563 sizeof ( MOUNT_TARGET ) );
565 TargetWalker = TargetWalker->Next;
567 RtlCopyMemory ( Irp->AssociatedIrp.SystemBuffer, Targets,
569 DeviceIoControl.OutputBufferLength <
570 ( sizeof ( MOUNT_TARGETS ) +
572 sizeof ( MOUNT_TARGET ) ) ) ? Stack->
573 Parameters.DeviceIoControl.OutputBufferLength
574 : ( sizeof ( MOUNT_TARGETS ) +
575 ( Count * sizeof ( MOUNT_TARGET ) ) ) ) );
576 ExFreePool ( Targets );
578 KeReleaseSpinLock ( &Bus_Globals_TargetListSpinLock, Irql );
579 Status = STATUS_SUCCESS;
582 DBG ( "Got IOCTL_AOE_SHOW...\n" );
585 DiskWalker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
586 while ( DiskWalker != NULL )
589 DiskWalker = DiskWalker->next_sibling_ptr;
593 ( PMOUNT_DISKS ) ExAllocatePool ( NonPagedPool,
594 sizeof ( MOUNT_DISKS ) +
596 sizeof ( MOUNT_DISK ) ) ) )
599 DBG ( "ExAllocatePool Disks\n" );
600 Irp->IoStatus.Information = 0;
601 Status = STATUS_INSUFFICIENT_RESOURCES;
604 Irp->IoStatus.Information =
605 sizeof ( MOUNT_DISKS ) + ( Count * sizeof ( MOUNT_DISK ) );
606 Disks->Count = Count;
609 DiskWalker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
610 while ( DiskWalker != NULL )
612 Disks->Disk[Count].Disk = DiskWalker->DiskNumber;
613 RtlCopyMemory ( &Disks->Disk[Count].ClientMac,
614 &DiskWalker->AoE.ClientMac, 6 );
615 RtlCopyMemory ( &Disks->Disk[Count].ServerMac,
616 &DiskWalker->AoE.ServerMac, 6 );
617 Disks->Disk[Count].Major = DiskWalker->AoE.Major;
618 Disks->Disk[Count].Minor = DiskWalker->AoE.Minor;
619 Disks->Disk[Count].LBASize = DiskWalker->LBADiskSize;
621 DiskWalker = DiskWalker->next_sibling_ptr;
623 RtlCopyMemory ( Irp->AssociatedIrp.SystemBuffer, Disks,
625 DeviceIoControl.OutputBufferLength <
626 ( sizeof ( MOUNT_DISKS ) +
628 sizeof ( MOUNT_DISK ) ) ) ? Stack->
629 Parameters.DeviceIoControl.OutputBufferLength
630 : ( sizeof ( MOUNT_DISKS ) +
631 ( Count * sizeof ( MOUNT_DISK ) ) ) ) );
632 ExFreePool ( Disks );
634 Status = STATUS_SUCCESS;
636 case IOCTL_AOE_MOUNT:
637 Buffer = Irp->AssociatedIrp.SystemBuffer;
638 DBG ( "Got IOCTL_AOE_MOUNT for client: %02x:%02x:%02x:%02x:%02x:%02x "
639 "Major:%d Minor:%d\n", Buffer[0], Buffer[1], Buffer[2],
640 Buffer[3], Buffer[4], Buffer[5],
641 *( winvblock__uint16_ptr ) ( &Buffer[6] ),
642 ( winvblock__uint8 ) Buffer[8] );
643 Disk.Initialize = AoE_SearchDrive;
644 RtlCopyMemory ( Disk.AoE.ClientMac, Buffer, 6 );
645 RtlFillMemory ( Disk.AoE.ServerMac, 6, 0xff );
646 Disk.AoE.Major = *( winvblock__uint16_ptr ) ( &Buffer[6] );
647 Disk.AoE.Minor = ( winvblock__uint8 ) Buffer[8];
648 Disk.AoE.MaxSectorsPerPacket = 1;
649 Disk.AoE.Timeout = 200000; /* 20 ms. */
650 Disk.IsRamdisk = FALSE;
651 if ( !Bus_AddChild ( DeviceObject, Disk, FALSE ) )
653 DBG ( "Bus_AddChild() failed\n" );
657 if ( bus_ptr->PhysicalDeviceObject != NULL )
658 IoInvalidateDeviceRelations ( bus_ptr->PhysicalDeviceObject,
661 Irp->IoStatus.Information = 0;
662 Status = STATUS_SUCCESS;
664 case IOCTL_AOE_UMOUNT:
665 Buffer = Irp->AssociatedIrp.SystemBuffer;
666 DBG ( "Got IOCTL_AOE_UMOUNT for disk: %d\n", *( PULONG ) Buffer );
667 DiskWalker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
668 DiskWalkerPrevious = DiskWalker;
669 while ( ( DiskWalker != NULL )
670 && ( DiskWalker->DiskNumber != *( PULONG ) Buffer ) )
672 DiskWalkerPrevious = DiskWalker;
673 DiskWalker = DiskWalker->next_sibling_ptr;
675 if ( DiskWalker != NULL )
677 if ( DiskWalker->BootDrive )
679 DBG ( "Cannot unmount a boot drive.\n" );
680 Irp->IoStatus.Information = 0;
681 Status = STATUS_INVALID_DEVICE_REQUEST;
684 DBG ( "Deleting disk %d\n", DiskWalker->DiskNumber );
685 if ( DiskWalker == ( disk__type_ptr ) bus_ptr->first_child_ptr )
687 bus_ptr->first_child_ptr =
688 ( winvblock__uint8_ptr ) DiskWalker->next_sibling_ptr;
692 DiskWalkerPrevious->next_sibling_ptr =
693 DiskWalker->next_sibling_ptr;
695 DiskWalker->Unmount = TRUE;
696 DiskWalker->next_sibling_ptr = NULL;
697 if ( bus_ptr->PhysicalDeviceObject != NULL )
698 IoInvalidateDeviceRelations ( bus_ptr->PhysicalDeviceObject,
702 Irp->IoStatus.Information = 0;
703 Status = STATUS_SUCCESS;
706 Irp->IoStatus.Information = 0;
707 Status = STATUS_INVALID_DEVICE_REQUEST;
710 Irp->IoStatus.Status = Status;
711 IoCompleteRequest ( Irp, IO_NO_INCREMENT );
715 irp__handler_decl ( Bus_DispatchSystemControl )
717 bus__type_ptr bus_ptr = get_bus_ptr ( DeviceExtension );
719 IoSkipCurrentIrpStackLocation ( Irp );
720 return IoCallDriver ( bus_ptr->LowerDeviceObject, Irp );
723 irp__handler_decl ( Bus_Dispatch )
726 bus__type_ptr bus_ptr = get_bus_ptr ( DeviceExtension );
728 switch ( Stack->MajorFunction )
731 PoStartNextPowerIrp ( Irp );
732 IoSkipCurrentIrpStackLocation ( Irp );
733 Status = PoCallDriver ( bus_ptr->LowerDeviceObject, Irp );
737 Bus_DispatchPnP ( DeviceObject, Irp, Stack, DeviceExtension,
740 case IRP_MJ_SYSTEM_CONTROL:
742 Bus_DispatchSystemControl ( DeviceObject, Irp, Stack,
743 DeviceExtension, completion_ptr );
745 case IRP_MJ_DEVICE_CONTROL:
747 Bus_DispatchDeviceControl ( DeviceObject, Irp, Stack,
748 DeviceExtension, completion_ptr );
751 Status = STATUS_NOT_SUPPORTED;
752 Irp->IoStatus.Status = Status;
753 IoCompleteRequest ( Irp, IO_NO_INCREMENT );
758 static NTSTATUS STDCALL
759 Bus_IoCompletionRoutine (
760 IN PDEVICE_OBJECT DeviceObject,
765 KeSetEvent ( Event, 0, FALSE );
766 return STATUS_MORE_PROCESSING_REQUIRED;
770 Bus_GetDeviceCapabilities (
771 IN PDEVICE_OBJECT DeviceObject,
772 IN PDEVICE_CAPABILITIES DeviceCapabilities
775 IO_STATUS_BLOCK ioStatus;
778 PDEVICE_OBJECT targetObject;
779 PIO_STACK_LOCATION irpStack;
782 RtlZeroMemory ( DeviceCapabilities, sizeof ( DEVICE_CAPABILITIES ) );
783 DeviceCapabilities->Size = sizeof ( DEVICE_CAPABILITIES );
784 DeviceCapabilities->Version = 1;
785 DeviceCapabilities->Address = -1;
786 DeviceCapabilities->UINumber = -1;
788 KeInitializeEvent ( &pnpEvent, NotificationEvent, FALSE );
789 targetObject = IoGetAttachedDeviceReference ( DeviceObject );
791 IoBuildSynchronousFsdRequest ( IRP_MJ_PNP, targetObject, NULL, 0, NULL,
792 &pnpEvent, &ioStatus );
793 if ( pnpIrp == NULL )
795 status = STATUS_INSUFFICIENT_RESOURCES;
799 pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
800 irpStack = IoGetNextIrpStackLocation ( pnpIrp );
801 RtlZeroMemory ( irpStack, sizeof ( IO_STACK_LOCATION ) );
802 irpStack->MajorFunction = IRP_MJ_PNP;
803 irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
804 irpStack->Parameters.DeviceCapabilities.Capabilities =
806 status = IoCallDriver ( targetObject, pnpIrp );
807 if ( status == STATUS_PENDING )
809 KeWaitForSingleObject ( &pnpEvent, Executive, KernelMode, FALSE,
811 status = ioStatus.Status;
814 ObDereferenceObject ( targetObject );
820 IN PDRIVER_OBJECT DriverObject,
821 IN PDEVICE_OBJECT PhysicalDeviceObject
825 UNICODE_STRING DeviceName,
827 size_t new_dev_ext_size;
828 driver__dev_ext_ptr bus_dev_ext_ptr;
829 bus__type_ptr bus_ptr;
833 return STATUS_SUCCESS;
834 RtlInitUnicodeString ( &DeviceName, L"\\Device\\AoE" );
835 RtlInitUnicodeString ( &DosDeviceName, L"\\DosDevices\\AoE" );
837 sizeof ( driver__dev_ext ) + sizeof ( bus__type ) +
838 driver__handling_table_size + handling_table_size;
841 IoCreateDevice ( DriverObject, new_dev_ext_size, &DeviceName,
842 FILE_DEVICE_CONTROLLER, FILE_DEVICE_SECURE_OPEN,
843 FALSE, &bus__fdo ) ) )
845 return Error ( "Bus_AddDevice IoCreateDevice", Status );
848 ( Status = IoCreateSymbolicLink ( &DosDeviceName, &DeviceName ) ) )
850 IoDeleteDevice ( bus__fdo );
851 return Error ( "Bus_AddDevice IoCreateSymbolicLink", Status );
854 bus_dev_ext_ptr = ( driver__dev_ext_ptr ) bus__fdo->DeviceExtension;
855 RtlZeroMemory ( bus_dev_ext_ptr, new_dev_ext_size );
856 bus_dev_ext_ptr->IsBus = TRUE;
857 bus_dev_ext_ptr->dispatch = Bus_Dispatch;
858 bus_dev_ext_ptr->DriverObject = DriverObject;
859 bus_dev_ext_ptr->Self = bus__fdo;
860 bus_dev_ext_ptr->State = NotStarted;
861 bus_dev_ext_ptr->OldState = NotStarted;
862 bus_dev_ext_ptr->irp_handler_stack_ptr =
863 ( winvblock__uint8 * ) bus_dev_ext_ptr + sizeof ( driver__dev_ext ) +
864 sizeof ( bus__type );
865 RtlCopyMemory ( bus_dev_ext_ptr->irp_handler_stack_ptr,
866 driver__handling_table, driver__handling_table_size );
867 RtlCopyMemory ( ( winvblock__uint8 * ) bus_dev_ext_ptr->
868 irp_handler_stack_ptr + driver__handling_table_size,
869 handling_table, handling_table_size );
870 bus_dev_ext_ptr->irp_handler_stack_size =
871 ( driver__handling_table_size +
872 handling_table_size ) / sizeof ( irp__handling );
874 * Establish a pointer into the bus device's extension space
876 bus_ptr = get_bus_ptr ( bus_dev_ext_ptr );
877 bus_ptr->PhysicalDeviceObject = PhysicalDeviceObject;
878 bus_ptr->Children = 0;
879 bus_ptr->first_child_ptr = NULL;
880 KeInitializeSpinLock ( &bus_ptr->SpinLock );
881 bus__fdo->Flags |= DO_DIRECT_IO; /* FIXME? */
882 bus__fdo->Flags |= DO_POWER_INRUSH; /* FIXME? */
884 * Add the bus to the device tree
886 if ( PhysicalDeviceObject != NULL )
888 if ( ( bus_ptr->LowerDeviceObject =
889 IoAttachDeviceToDeviceStack ( bus__fdo,
890 PhysicalDeviceObject ) ) == NULL )
892 IoDeleteDevice ( bus__fdo );
894 return Error ( "AddDevice IoAttachDeviceToDeviceStack",
895 STATUS_NO_SUCH_DEVICE );
898 bus__fdo->Flags &= ~DO_DEVICE_INITIALIZING;
900 bus_dev_ext_ptr->State = Started;
902 return STATUS_SUCCESS;