/***************************************************************************** * adapter.cpp - MPU401 adapter driver implementation. ***************************************************************************** * Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved. * * Created 6/19/97, a-seemap * */ // // All the GUIDS for all the miniports end up in this object. // #define PUT_GUIDS_HERE #define STR_MODULENAME "MPU401Adapter: " #define PC_NEW_NAMES 1 #define kUseDMusicMiniport 1 #include "portcls.h" #include "ksdebug.h" #if (kUseDMusicMiniport) #include "dmusicks.h" #endif // kUseDMusicMiniport /***************************************************************************** * Defines */ #define MAX_MINIPORTS 1 #if (DBG) #define SUCCEEDS(s) ASSERT(NT_SUCCESS(s)) #else #define SUCCEEDS(s) (s) #endif /***************************************************************************** * Referenced forward */ extern "C" NTSTATUS AddDevice ( IN PVOID Context1, IN PVOID Context2 ); NTSTATUS StartDevice ( IN PDEVICE_OBJECT pDeviceObject, // Context for the class driver. IN PIRP pIrp, // Context for the class driver. IN PRESOURCELIST ResourceList // List of hardware resources. ); #pragma code_seg("INIT") /***************************************************************************** * DriverEntry() ***************************************************************************** * This function is called by the operating system when the driver is loaded. * All adapter drivers can use this code without change. */ extern "C" NTSTATUS DriverEntry ( IN PVOID Context1, // Context for the class driver. IN PVOID Context2 // Context for the class driver. ) { PAGED_CODE(); _DbgPrintF(DEBUGLVL_VERBOSE, ("DriverEntry")); // _DbgPrintF(DEBUGLVL_ERROR, ("Starting breakpoint for debugging")); // // Tell the class driver to initialize the driver. // return PcInitializeAdapterDriver((PDRIVER_OBJECT)Context1, (PUNICODE_STRING)Context2, (PDRIVER_ADD_DEVICE)AddDevice); } #pragma code_seg("PAGE") /***************************************************************************** * AddDevice() ***************************************************************************** * This function is called by the operating system when the device is added. * All adapter drivers can use this code without change. */ NTSTATUS AddDevice ( IN PVOID Context1, // Context for the class driver. IN PVOID Context2 // Context for the class driver. ) { PAGED_CODE(); _DbgPrintF(DEBUGLVL_VERBOSE, ("AddDevice")); // // Tell the class driver to add the device. // return PcAddAdapterDevice((PDRIVER_OBJECT)Context1,(PDEVICE_OBJECT)Context2,StartDevice,MAX_MINIPORTS,0); } #pragma code_seg("PAGE") /***************************************************************************** * InstallSubdevice() ***************************************************************************** * This function creates and registers a subdevice consisting of a port * driver, a minport driver and a set of resources bound together. It will * also optionally place a pointer to an interface on the port driver in a * specified location before initializing the port driver. This is done so * that a common ISR can have access to the port driver during initialization, * when the ISR might fire. */ NTSTATUS InstallSubdevice ( IN PVOID Context1, IN PVOID Context2, IN PWCHAR Name, IN REFGUID PortClassId, IN REFGUID MiniportClassId, IN PUNKNOWN UnknownAdapter OPTIONAL, //not used - null IN PRESOURCELIST ResourceList, //not optional, but can be EMPTY! IN REFGUID PortInterfaceId, OUT PUNKNOWN * OutPortInterface, OPTIONAL //not used - null OUT PUNKNOWN * OutPortUnknown OPTIONAL //not used - null ) { PAGED_CODE(); _DbgPrintF(DEBUGLVL_VERBOSE, ("InstallSubdevice")); ASSERT(Context1); ASSERT(Context2); ASSERT(Name); ASSERT(ResourceList); // // Create the port driver object // PPORT port; NTSTATUS ntStatus = PcNewPort(&port,PortClassId); if (NT_SUCCESS(ntStatus)) { // // Deposit the port somewhere if it's needed. // if (OutPortInterface) { // // Failure here doesn't cause the entire routine to fail. // (void) port->QueryInterface ( PortInterfaceId, (PVOID *) OutPortInterface ); } PMINIPORT miniport; // // Create the miniport object // ntStatus = PcNewMiniport(&miniport,MiniportClassId); if (NT_SUCCESS(ntStatus)) { // // Init the port driver and miniport in one go. // ntStatus = port->Init( (PDEVICE_OBJECT)Context1, (PIRP)Context2, miniport, NULL, // interruptsync created in miniport. ResourceList); if (NT_SUCCESS(ntStatus)) { // // Register the subdevice (port/miniport combination). // ntStatus = PcRegisterSubdevice( (PDEVICE_OBJECT)Context1, Name, port ); if (!(NT_SUCCESS(ntStatus))) { _DbgPrintF(DEBUGLVL_TERSE, ("StartDevice: PcRegisterSubdevice failed")); } } else { _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: port->Init failed")); } // // We don't need the miniport any more. Either the port has it, // or we've failed, and it should be deleted. // miniport->Release(); } else { _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: PcNewMiniport failed")); } if (NT_SUCCESS(ntStatus)) { // // Deposit the port as an unknown if it's needed. // if (OutPortUnknown) { // // Failure here doesn't cause the entire routine to fail. // (void) port->QueryInterface ( IID_IUnknown, (PVOID *) OutPortUnknown ); } } else { // // Retract previously delivered port interface. // if (OutPortInterface && (*OutPortInterface)) { (*OutPortInterface)->Release(); *OutPortInterface = NULL; } } // // Release the reference which existed when PcNewPort() gave us the // pointer in the first place. This is the right thing to do // regardless of the outcome. // port->Release(); } else { _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: PcNewPort failed")); } return ntStatus; } #pragma code_seg("PAGE") /***************************************************************************** * StartDevice() ***************************************************************************** * This function is called by the operating system when the device is started. * It is responsible for starting the miniport. * This code is specific to the adapter because it calls out miniports for * functions that are specific to the adapter. */ NTSTATUS StartDevice ( IN PDEVICE_OBJECT pDeviceObject, // Context for the class driver. IN PIRP pIrp, // Context for the class driver. IN PRESOURCELIST ResourceList // List of hardware resources. ) { PAGED_CODE(); ASSERT(pDeviceObject); ASSERT(pIrp); ASSERT(ResourceList); if (!ResourceList) { _DbgPrintF(DEBUGLVL_TERSE, ("StartDevice: NULL resource list")); return STATUS_INVALID_PARAMETER; } NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES; if (ResourceList->NumberOfEntries()) { #if (kUseDMusicMiniport) // // Start the UART miniport. // ntStatus = InstallSubdevice( pDeviceObject, pIrp, L"Uart", CLSID_PortDMus, CLSID_MiniportDriverDMusUART, NULL, ResourceList, IID_IPortDMus, NULL, NULL // Not physically connected to anything. ); #else // (kUseDMusicMiniport) // // Start the UART miniport. // ntStatus = InstallSubdevice( pDeviceObject, pIrp, L"Uart", CLSID_PortMidi, CLSID_MiniportDriverUart, NULL, ResourceList, IID_IPortMidi, NULL, NULL // Not physically connected to anything. ); #endif // (kUseDMusicMiniport) } else { _DbgPrintF(DEBUGLVL_TERSE, ("StartDevice: no entries in resource list")); } return ntStatus; }