328 lines
10 KiB
C++
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;
|
|
}
|