Windows NT Device Driver Toolkits
by Patrick Tennberg


Listing One
// Getting, claiming, and using resources with WinDK.

// Get the resources from the registry
CRegistry *pRegistry = new CRegistry(m_DriverRegPath);

pRegistry->SetRelativePath(Concatenate(pDeviceName,L"\\Parameters"));
pRegistry->GetKey(L"PortBase",&m_PortBase);
pRegistry->GetKey(L"PortRange",&m_PortRange);
pRegistry->GetKey(L"Irq",&m_Irq);
delete pRegistry;

BOOLEAN fConflict;

CResource *pResources = new CResource(ISA,0,this,2);
pResources->AddPortResource(m_MappedAddress);
pResources->AddInterruptResource(m_Interrupt);
pResources->AssignCardsResources(m_DriverRegPath,&conflict);
delete pResources;

// Accessing the I/O ports using WinDK
WINDK_MAPPED_ADDRESS m_MappedAddress

// map the device ports
m_MappedAddress.Length                      = m_PortRange;
m_MappedAddress.PortType                    = PORT_MAPPED;
m_MappedAddress.UnmappedAddress.LowPart     = m_PortBase;
m_MappedAddress.UnmappedAddress.HighPart    = 0;
m_MappedAddress.Flags                       = CmResourceShareDeviceExclusive;

// map I/O address
status = MapIoAddress(Isa, busNumber, m_MappedAddress);

// Write to port
WRITE_PORT_UCHAR((PUCHAR)(m_MappedAddress.pAddress+RESET_ALL),0);

// Map an interrupt
WINDK_INTERRUPT_RESOURCE m_Interrupt;

// Setup an interrupt with WinDK
m_Interrupt.Level       = m_Irq;
m_Interrupt.Vector      = m_Irq;
m_Interrupt.Affinity    = 0;
m_Interrupt.Flags       = CmResourceShareDeviceExclusive;
m_Interrupt.Mode        = Latched;

// DpcForIsr and Isr is static functions they can however use member functions
InitializeInterrupt(
    ISA,
    0,
    reinterpret_cast<PIO_DPC_ROUTINE>(DpcForIsr),
    reinterpret_cast<PIO_DPC_ROUTINE>(Isr),
    this,
    m_Interrupt    
    );// Claming resources with WinDK
// The resources are automatically released in the destructor

// Unmap the I/O address
UnmapIoAddress(m_MappedAddress);


Listing Two
// Getting, claiming, and using resources with DriverWorks. Using the registry 
// with Driver::Works. Driver::Works has it's own way of defining devices in
// the registry. The advantage of using there model is that
// you can use the KConfigurationQuery class and CreateRegistryPath
m_RegPath = KDevice::CreateRegistryPath(L"MyDevice",m_Unit);

KRegistryKey unitKey(*m_RegPath); 
    
if (NT_SUCCESS(unitKey.LastError()))
{   
    unitKey.QueryValue(L"PortBase", &m_PortBase);
    unitKey.QueryValue(L"PortRange", &m_PortRange);        
    unitKey.QueryValue(L"Irq", &m_Irq);
}
// Claming resources with Driver::Works
KResourceRequest resReq(Isa,0,0);

resReq.AddPort(m_PortBase, m_PortBase, m_PortRange, 2, 0,
                              CmResourceShareDeviceExclusive);
resReq.AddIrq(m_Irq,m_Irq);   
resReq.Submit(this,m_DriverRegPath);

// Accessing the I/O ports using Driver::Works
KIoRange m_Ports;

// BusType, Offset, I/O port base, I/O port range
fStatus = m_Ports.Initialize(Isa,0,m_PortBase,m_PortRange);
// Write to the port
m_Ports.outb(RESET_ALL,0);

// Map an interrupt with Driver::Works
KInterrupt m_Interrupt;

// Setup the interrupt
m_Interrupt.Initialize(Isa,0,m_Irq,m_Irq,Latched,FALSE,FALSE);
    
// The Isr can be a member of the device class, it can also be an static
// member function to avoid the overhead of an extra function call.
m_Interrupt.Connect(LinkTo(Isr),this);

// Initialize a DPC object which may be queued by interrupt service routine
InitializeDpcForIsr(LinkTo(DpcForIsr));

// Release claimed resources
KResourceRequest resReq(Isa,0,0);
        
resReq.Release(this,m_DriverRegPath);

// The destructor unmaps the memory automatically



2


