windows-nt/Source/XPSP1/NT/drivers/ddk/wdmaudio/mpu401/adapter.cpp
2020-09-26 16:20:57 +08:00

328 lines
10 KiB
C++

/*****************************************************************************
* 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;
}