You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
843 lines
27 KiB
843 lines
27 KiB
/*----------------------------------------------------------------------
|
|
pnpadd.c - Handle pnp adding devices.
|
|
|----------------------------------------------------------------------*/
|
|
#include "precomp.h"
|
|
|
|
#ifdef NT50
|
|
|
|
NTSTATUS AddBoardDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo,
|
|
OUT PDEVICE_OBJECT *NewDevObj);
|
|
|
|
NTSTATUS AddPortDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo,
|
|
OUT PDEVICE_OBJECT *NewDevObj,
|
|
IN int port_index);
|
|
|
|
NTSTATUS CheckPortName(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN PSERIAL_DEVICE_EXTENSION ParentExt,
|
|
IN int port_index);
|
|
|
|
#define CFG_ID_ISA_BRD_INDEX 0
|
|
#define CFG_ID_NODE_INDEX 1
|
|
static int read_config_data(PDEVICE_OBJECT Pdo, int *ret_val, int val_id);
|
|
static int write_config_data(PDEVICE_OBJECT Pdo, int val, int val_id);
|
|
static int derive_unique_node_index(int *ret_val);
|
|
static int GetPnpIdStr(PDEVICE_OBJECT Pdo, char *ret_val);
|
|
|
|
|
|
/*----------------------------------------------------------------------
|
|
SerialAddDevice -
|
|
This routine creates a functional device object for boards or
|
|
com ports in the system and attaches them to the physical device
|
|
objects for the boards or ports.
|
|
|
|
Arguments:
|
|
DriverObject - a pointer to the object for this driver
|
|
PhysicalDeviceObject - a pointer to the physical object we need to attach to
|
|
|
|
Return Value:
|
|
status from device creation and initialization
|
|
|----------------------------------------------------------------------*/
|
|
NTSTATUS SerialAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo)
|
|
{
|
|
PDEVICE_OBJECT fdo = NULL;
|
|
PDEVICE_OBJECT lowerDevice = NULL;
|
|
PDEVICE_OBJECT NewDevObj = NULL;
|
|
NTSTATUS status;
|
|
#if DBG_STACK
|
|
int i;
|
|
#endif
|
|
int stat;
|
|
int board_device = 1; // asume pnp board device(not pnp port)
|
|
//PDEVICE_OBJECT deviceOjbect;
|
|
PSERIAL_DEVICE_EXTENSION deviceExtension;
|
|
ULONG resultLength;
|
|
USTR_240 *us; // equal to 240 normal chars length
|
|
char *ptr;
|
|
int port_index;
|
|
|
|
// Using stack array instead of static buffer for unicode conversion
|
|
|
|
char cstr[320];
|
|
|
|
//char temp_szNt50DevObjName[80];
|
|
#if DBG_STACK
|
|
DWORD stkchkend;
|
|
DWORD stkchk;
|
|
DWORD *stkptr;
|
|
#endif
|
|
|
|
MyKdPrint(D_PnpAdd,("RK:SerialAddDevice Start DrvObj:%x, PDO:%x\n",
|
|
DriverObject, Pdo))
|
|
|
|
MyKdPrint(D_Pnp, ("SerialAddDevice\n"))
|
|
#if DBG_STACK
|
|
stkchk = 0;
|
|
stkptr = (DWORD *)&DriverObject;
|
|
for (i=0; i<50; i++)
|
|
{
|
|
stkchk += *stkptr++;
|
|
}
|
|
#endif
|
|
|
|
//PAGED_CODE();
|
|
|
|
if (Pdo == NULL) {
|
|
// Bugbug: This is where enumeration occurs.
|
|
// One possible use for this is to add the user defined
|
|
// ports from the registry
|
|
// For now: just return no more devices
|
|
MyKdPrint(D_Error, ("NullPDO.\n"))
|
|
return (STATUS_NO_MORE_ENTRIES);
|
|
}
|
|
|
|
us = ExAllocatePool(NonPagedPool, sizeof(USTR_240));
|
|
if ( us == NULL ) {
|
|
MyKdPrint(D_Error, ("SerialAddDevice no memory.\n"))
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
// configure the unicode string to: point the buffer ptr to the wstr.
|
|
us->ustr.Buffer = us->wstr;
|
|
us->ustr.Length = 0;
|
|
us->ustr.MaximumLength = sizeof(USTR_240) - sizeof(UNICODE_STRING);
|
|
|
|
// get the friendly name
|
|
// "Comtrol xxxx xx" for board, "Comtrol Port(COM24)" for port.
|
|
status = IoGetDeviceProperty (Pdo,
|
|
DevicePropertyFriendlyName,
|
|
us->ustr.MaximumLength,
|
|
us->ustr.Buffer,
|
|
&resultLength);
|
|
us->ustr.Length = (USHORT) resultLength;
|
|
// ptr = UToC1(&us->ustr);
|
|
ptr = UToCStr( cstr,
|
|
&us->ustr,
|
|
sizeof( cstr ));
|
|
MyKdPrint(D_Pnp, ("FriendlyName:%s\n", ptr))
|
|
|
|
// get the class-name
|
|
// "MultiPortSerial" for board, "Ports" for port.
|
|
status = IoGetDeviceProperty (Pdo,
|
|
DevicePropertyClassName, // Ports
|
|
us->ustr.MaximumLength,
|
|
us->ustr.Buffer,
|
|
&resultLength);
|
|
us->ustr.Length = (USHORT) resultLength;
|
|
// ptr = UToC1(&us->ustr);
|
|
ptr = UToCStr( cstr,
|
|
&us->ustr,
|
|
sizeof( cstr ));
|
|
MyKdPrint(D_Pnp, ("ClassName:%s\n", ptr))
|
|
if (my_toupper(*ptr) == 'P') // "Ports"
|
|
{
|
|
MyKdPrint(D_Pnp, ("A Port!\n"))
|
|
board_device = 0; // its a port pnp device
|
|
}
|
|
// else it's the default: a board device
|
|
|
|
// get the dev-desc
|
|
// "RocketPort Port0" for port, "RocketPort 8 Port, ISA-BUS" for board
|
|
status = IoGetDeviceProperty (Pdo,
|
|
DevicePropertyDeviceDescription,
|
|
us->ustr.MaximumLength,
|
|
us->ustr.Buffer,
|
|
&resultLength);
|
|
us->ustr.Length = (USHORT) resultLength;
|
|
// ptr = UToC1(&us->ustr);
|
|
ptr = UToCStr( cstr,
|
|
&us->ustr,
|
|
sizeof( cstr ));
|
|
MyKdPrint(D_Pnp, ("DevDesc:%s\n", ptr))
|
|
|
|
// Find out what the PnP manager thinks my NT Hardware ID is
|
|
// "CtmPort0000" for port, "rckt1002" for isa-board
|
|
// for pci we are getting a huge string, 400 bytes long, not good...
|
|
status = IoGetDeviceProperty (Pdo,
|
|
DevicePropertyHardwareID, // port0000
|
|
us->ustr.MaximumLength,
|
|
us->ustr.Buffer,
|
|
&resultLength);
|
|
MyKdPrint(D_Pnp, ("status:%d\n", status))
|
|
us->ustr.Length = (USHORT) resultLength;
|
|
MyKdPrint(D_Pnp, ("Len:%d\n",resultLength))
|
|
// ptr = UToC1(&us->ustr);
|
|
ptr = UToCStr( cstr,
|
|
&us->ustr,
|
|
sizeof( cstr ));
|
|
MyKdPrint(D_Pnp, ("DevHdwID:%s\n", ptr))
|
|
|
|
if (board_device) // record board type according to pnp
|
|
{
|
|
// if (strlen(ptr) < 12)
|
|
// {
|
|
// i = gethint(&ptr[4], NULL);
|
|
// MyKdPrint(D_Pnp, ("HdwID:%d\n", i))
|
|
// Hardware_Id = i;
|
|
// }
|
|
}
|
|
else // its a port pnp device, find the port-index
|
|
{
|
|
while ((*ptr != 0) && (*ptr != '0'))
|
|
++ptr;
|
|
port_index = getint(ptr, NULL);
|
|
MyKdPrint(D_Pnp, ("port_index:%d\n", port_index))
|
|
}
|
|
|
|
#if 0
|
|
// key name
|
|
// {50906CB8-BA12-11D1-BF5D-0000F805F530}\0001 for board
|
|
status = IoGetDeviceProperty (Pdo,
|
|
DevicePropertyDriverKeyName, // 4D36....
|
|
us->ustr.MaximumLength,
|
|
us->ustr.Buffer,
|
|
&resultLength);
|
|
us->ustr.Length = (USHORT) resultLength;
|
|
MyKdPrint(D_Pnp, ("KeyName:%s\n", UToC1(&us->ustr)))
|
|
|
|
|
|
// Find out what the PnP manager thinks my NT Hardware ID is
|
|
// \Device\003354 typical
|
|
status = IoGetDeviceProperty (Pdo,
|
|
DevicePropertyPhysicalDeviceObjectName, // \Device\003354
|
|
us->ustr.MaximumLength,
|
|
us->ustr.Buffer,
|
|
&resultLength);
|
|
us->ustr.Length = (USHORT) resultLength;
|
|
MyKdPrint(D_Pnp, ("DevName:%s\n", UToC1(&us->ustr)))
|
|
|
|
if (board_device)
|
|
{
|
|
int i,j;
|
|
// we need to use this later as this is what our config data is
|
|
// stored under. Since we want to read in our config before
|
|
// creating the board and port extensions(where the config
|
|
// record eventually ends up), we setup the first entry in
|
|
// the static array of device configuration records as our
|
|
// own as a temporary measure so our read options routine
|
|
// has a place to put the config data.
|
|
strcpy(temp_szNt50DevObjName, UToC1(&us->ustr));
|
|
// strip off the forward slashes
|
|
i=0;
|
|
j=0;
|
|
while (temp_szNt50DevObjName[i] != 0)
|
|
{
|
|
if (temp_szNt50DevObjName[i] != '\\')
|
|
temp_szNt50DevObjName[j++] = temp_szNt50DevObjName[i];
|
|
i++;
|
|
}
|
|
temp_szNt50DevObjName[j] = 0;
|
|
}
|
|
#endif
|
|
ExFreePool(us);
|
|
us = NULL;
|
|
|
|
MyKdPrint(D_Pnp, ("CreateFdo\n"))
|
|
|
|
if (board_device)
|
|
{
|
|
status = AddBoardDevice(DriverObject, Pdo, &NewDevObj);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
MyKdPrint(D_Error, ("Err, Creating Board Obj\n"))
|
|
return status;
|
|
}
|
|
deviceExtension = NewDevObj->DeviceExtension;
|
|
//strcpy(deviceExtension->config->szNt50DevObjName, temp_szNt50DevObjName);
|
|
|
|
// read in our device configuration from the registry
|
|
stat = read_device_options(deviceExtension);
|
|
|
|
} // board device
|
|
else
|
|
{
|
|
status = AddPortDevice(DriverObject, Pdo, &NewDevObj, port_index);
|
|
}
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
MyKdPrint(D_Error,("Error on NewPort Create!\n"))
|
|
|
|
return status;
|
|
}
|
|
fdo = NewDevObj;
|
|
|
|
// Layer our FDO on top of the PDO
|
|
// The return value is a pointer to the device object to which the
|
|
// fdo is actually attached.
|
|
lowerDevice = IoAttachDeviceToDeviceStack(fdo, Pdo);
|
|
|
|
MyKdPrint(D_PnpAdd,("RK:SerialAddDevice New FDO:%x, Ext:%x TopOfStack:%x\n",
|
|
fdo, fdo->DeviceExtension, lowerDevice))
|
|
|
|
// No status. Do the best we can.
|
|
MyAssert(lowerDevice);
|
|
|
|
// fdo source, pdo is target, save handle to lower device object
|
|
deviceExtension = fdo->DeviceExtension;
|
|
deviceExtension->LowerDeviceObject = lowerDevice;
|
|
deviceExtension->Pdo = Pdo; // save off the handle to the pdo
|
|
|
|
// Set the stack requirement for this device object to 2 + the size of the
|
|
// lower device's stack size. This will allow the same Irp that comes in
|
|
// for Open and Close calls to be used for the PoCallDriver calls to change
|
|
// the power state of the device.
|
|
// fdo->StackSize = lowerDevice->StackSize + 2;
|
|
|
|
fdo->Flags |= DO_POWER_PAGABLE;
|
|
|
|
#if DBG_STACK
|
|
stkchkend = 0;
|
|
stkptr = (DWORD *)&DriverObject;
|
|
for (i=0; i<50; i++)
|
|
{
|
|
stkchkend += *stkptr++;
|
|
}
|
|
if (stkchkend != stkchk)
|
|
{
|
|
MyKdPrint(D_Error, ("Err, ******** STACK CHECK FAIL!!!!\n"))
|
|
}
|
|
else
|
|
{
|
|
MyKdPrint(D_Error, ("OK Stack chk\n"))
|
|
}
|
|
#endif
|
|
|
|
MyKdPrint(D_PnpAdd, ("End SerialAddDevice\n"))
|
|
|
|
MyKdPrint(D_Pnp, ("End SerialAddDevice\n"))
|
|
return status;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
AddBoardDevice - Setup and Create a board device in response to
|
|
AddDevice ioctl.
|
|
|----------------------------------------------------------------------*/
|
|
NTSTATUS AddBoardDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo,
|
|
OUT PDEVICE_OBJECT *NewDevObj)
|
|
{
|
|
PSERIAL_DEVICE_EXTENSION NewExtension = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
char tmpstr[110];
|
|
ULONG Hardware_ID = 0;
|
|
int num_ports = 0;
|
|
int stat;
|
|
static int max_isa_board_index = 0;
|
|
int device_node_index = -1;
|
|
int isa_board_index = -1;
|
|
|
|
MyKdPrint(D_Pnp, ("AddBoardDevice\n"))
|
|
|
|
// Find out what the PnP manager thinks my NT pnp Hardware ID is
|
|
tmpstr[0] = 0;
|
|
stat = GetPnpIdStr(Pdo, tmpstr);
|
|
if (stat)
|
|
{
|
|
MyKdPrint(D_Error, ("Err, HdwID 1B\n"))
|
|
}
|
|
MyKdPrint(D_Test, ("DevHdwID:%s\n", tmpstr))
|
|
|
|
// Parse this info, tells us what type of board we have
|
|
stat = HdwIDStrToID(&Hardware_ID, tmpstr);
|
|
if (stat)
|
|
{
|
|
MyKdPrint(D_Error, ("Err, HdwID 1A:%s\n", tmpstr))
|
|
}
|
|
MyKdPrint(D_Pnp, ("HdwID:%x\n", Hardware_ID))
|
|
|
|
// Read in our Node Index, see if we are new...
|
|
stat = read_config_data(Pdo, &device_node_index, CFG_ID_NODE_INDEX);
|
|
|
|
if (stat) // not exist
|
|
{
|
|
derive_unique_node_index(&device_node_index);
|
|
MyKdPrint(D_Test, ("Derive Node ID:%d\n", device_node_index))
|
|
stat = write_config_data(Pdo, device_node_index, CFG_ID_NODE_INDEX);
|
|
}
|
|
else
|
|
{
|
|
MyKdPrint(D_Test, ("Node ID:%d\n", device_node_index))
|
|
}
|
|
if (device_node_index < 0)
|
|
device_node_index = 0;
|
|
|
|
#ifdef S_RK
|
|
// try to order the ISA boards
|
|
if ((Hardware_ID >= 0x1000) && (Hardware_ID <= 0x2fff)) // its ISA
|
|
{
|
|
stat = read_config_data(Pdo, &isa_board_index, CFG_ID_ISA_BRD_INDEX);
|
|
MyKdPrint(D_Pnp,("Read isa_board_index:%d\n", isa_board_index))
|
|
}
|
|
#endif
|
|
|
|
//----- create a board device
|
|
Driver.Stop_Poll = 1; // flag to stop poll access
|
|
|
|
if (Driver.driver_ext == NULL)
|
|
{
|
|
status = CreateDriverDevice(Driver.GlobalDriverObject,
|
|
&NewExtension); // create the driver device
|
|
#ifdef S_VS
|
|
init_eth_start();
|
|
#endif
|
|
}
|
|
|
|
status = CreateBoardDevice(Driver.GlobalDriverObject,
|
|
&NewExtension); // create the board device
|
|
|
|
*NewDevObj = NewExtension->DeviceObject;
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
Driver.Stop_Poll = 0; // flag to stop poll access
|
|
Eprintf("CreateBoardDevice Err1A");
|
|
return status;
|
|
}
|
|
|
|
// DoPnpAssoc(Pdo);
|
|
|
|
// copy over our key name used to find config info in the registry
|
|
Sprintf(NewExtension->config->szNt50DevObjName, "Device%d", device_node_index);
|
|
#if 0
|
|
//strcpy(NewExtension->config->szNt50DevObjName, PnpKeyName);
|
|
#endif
|
|
|
|
NewExtension->config->Hardware_ID = Hardware_ID;
|
|
num_ports = id_to_num_ports(Hardware_ID);
|
|
MyKdPrint(D_Test, ("NumPorts:%d\n", num_ports))
|
|
|
|
// read in our device configuration from the registry
|
|
stat = read_device_options(NewExtension);
|
|
|
|
//if (!(Hardware_ID == NET_DEVICE_VS1000)) // jam in
|
|
// NewExtension->config->NumPorts = num_ports;
|
|
|
|
if (NewExtension->config->NumPorts == 0)
|
|
NewExtension->config->NumPorts = num_ports;
|
|
|
|
// check for ModemDevice, etc.
|
|
if (IsModemDevice(Hardware_ID))
|
|
NewExtension->config->ModemDevice = 1;
|
|
|
|
MyKdPrint(D_Pnp, ("Num Ports:%d\n",NewExtension->config->NumPorts))
|
|
|
|
#ifdef S_RK
|
|
// try to order the ISA boards
|
|
if ((Hardware_ID >= 0x1000) && (Hardware_ID <= 0x2fff)) // its ISA
|
|
{
|
|
if (isa_board_index == -1) // new
|
|
{
|
|
isa_board_index = max_isa_board_index;
|
|
stat = write_config_data(Pdo, isa_board_index, CFG_ID_ISA_BRD_INDEX);
|
|
MyKdPrint(D_Pnp,("Save IsaIndex:%d\n", isa_board_index))
|
|
}
|
|
// bump so next isa board gets new index
|
|
if (max_isa_board_index >= isa_board_index)
|
|
max_isa_board_index = isa_board_index + 1;
|
|
NewExtension->config->ISABrdIndex = isa_board_index;
|
|
} // isa board
|
|
#endif
|
|
|
|
Driver.Stop_Poll = 0; // flag to stop poll access
|
|
|
|
status = STATUS_SUCCESS;
|
|
return status;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
derive_unique_node_index -
|
|
|----------------------------------------------------------------------*/
|
|
static int derive_unique_node_index(int *ret_val)
|
|
{
|
|
HANDLE DrvHandle = NULL;
|
|
HANDLE DevHandle = NULL;
|
|
char tmpstr[40];
|
|
int i, stat;
|
|
|
|
// force a creation of "Parameters" if not exist
|
|
stat = our_open_driver_reg(&DrvHandle, KEY_ALL_ACCESS);
|
|
|
|
for (i=0; i< 100; i++)
|
|
{
|
|
Sprintf(tmpstr,"Device%d", i);
|
|
stat = our_open_key(&DevHandle,
|
|
DrvHandle, tmpstr, KEY_READ);
|
|
|
|
if (stat) // does not exist
|
|
{
|
|
// create it, so next one won't pick up the same
|
|
stat = our_open_key(&DevHandle,
|
|
DrvHandle, tmpstr, KEY_ALL_ACCESS);
|
|
|
|
ZwClose(DevHandle);
|
|
ZwClose(DrvHandle);
|
|
*ret_val = i;
|
|
return 0; // ok
|
|
}
|
|
}
|
|
|
|
ZwClose(DevHandle);
|
|
ZwClose(DrvHandle);
|
|
return 1; // err
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
GetPnpIdStr -
|
|
|----------------------------------------------------------------------*/
|
|
static int GetPnpIdStr(PDEVICE_OBJECT Pdo, char *ret_val)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
UNICODE_STRING ustr;
|
|
ULONG resultLength = 0;
|
|
char *ptr;
|
|
|
|
// configure the unicode string to: point the buffer ptr to the wstr.
|
|
ustr.Buffer = ExAllocatePool(PagedPool, 1002);
|
|
if ( ustr.Buffer == NULL ) {
|
|
return -1;
|
|
}
|
|
ustr.Length = 0;
|
|
ustr.MaximumLength = 1000;
|
|
|
|
MyKdPrint(D_Pnp, ("AddBoardDevice\n"))
|
|
|
|
// Find out what the PnP manager thinks my NT Hardware ID is
|
|
// "CtmPort0000" for port, "rckt1002" for isa-board
|
|
// for pci we are getting a multi-wstring, 400 bytes long with
|
|
// "PCI\VEN_11FE&DEV_0003&SUBSYS00000...",0,"PCI\VEN.."
|
|
status = IoGetDeviceProperty (Pdo,
|
|
DevicePropertyHardwareID, // port0000
|
|
ustr.MaximumLength,
|
|
ustr.Buffer,
|
|
&resultLength);
|
|
ustr.Length = (USHORT) resultLength;
|
|
if (ustr.Length > 100)
|
|
ustr.Length = 100; // limit
|
|
ptr = UToC1(&ustr);
|
|
|
|
strcpy(ret_val, ptr);
|
|
|
|
ExFreePool(ustr.Buffer);
|
|
MyKdPrint(D_Pnp, ("DevHdwID:%s\n", ret_val))
|
|
return 0;
|
|
}
|
|
|
|
#if 0
|
|
/*----------------------------------------------------------------------
|
|
DoPnpAssoc - Weird pnp stuff I haven't figured out yet
|
|
|----------------------------------------------------------------------*/
|
|
static int DoPnpAssoc(PDEVICE_OBJECT Pdo)
|
|
{
|
|
if (!Driver.NoPnpPorts)
|
|
{
|
|
#ifdef DO_BUS_SHINGLES
|
|
//
|
|
// Tell the PlugPlay system that this device will need an interface
|
|
// device class shingle.
|
|
//
|
|
// It may be that the driver cannot hang the shingle until it starts
|
|
// the device itself, so that it can query some of its properties.
|
|
// (Aka the shingles guid (or ref string) is based on the properties
|
|
// of the device.)
|
|
//
|
|
status = IoRegisterDeviceInterface (
|
|
Pdo, // BusPhysicalDeviceObject
|
|
(LPGUID) &GUID_CTMPORT_BUS_ENUMERATOR,
|
|
NULL, // No ref string
|
|
&NewExtension->DevClassAssocName);
|
|
#endif
|
|
//
|
|
// If for any reason you need to save values in a safe location that
|
|
// clients of this DeviceClassAssociate might be interested in reading
|
|
// here is the time to do so, with the function
|
|
// IoOpenDeviceClassRegistryKey
|
|
// the symbolic link name used is was returned in
|
|
// deviceData->DevClassAssocName (the same name which is returned by
|
|
// IoGetDeviceClassAssociations and the SetupAPI equivs.
|
|
//
|
|
|
|
//status = IoGetDeviceProperty (BusPhysicalDeviceObject,
|
|
// DevicePropertyPhysicalDeviceObjectName,
|
|
// 0,
|
|
// NULL,
|
|
// &nameLength);
|
|
//IoGetDeviceProperty (BusPhysicalDeviceObject,
|
|
// DevicePropertyPhysicalDeviceObjectName,
|
|
// nameLength,
|
|
// deviceName,
|
|
// &nameLength);
|
|
//Game_KdPrint (deviceData, GAME_DBG_SS_TRACE,
|
|
// ("AddDevice: %x to %x->%x (%ws) \n",
|
|
// deviceObject,
|
|
// NewExtension->TopOfStack,
|
|
// BusPhysicalDeviceObject,
|
|
// deviceName));
|
|
|
|
|
|
//
|
|
// Turn on the shingle and point it to the given device object.
|
|
//
|
|
#ifdef DO_BUS_SHINGLES
|
|
status = IoSetDeviceInterfaceState (
|
|
&NewExtension->DevClassAssocName,
|
|
TRUE);
|
|
|
|
if (!NT_SUCCESS (status)) {
|
|
Game_KdPrint (deviceData, GAME_DBG_SS_ERROR,
|
|
("AddDevice: IoSetDeviceClass failed (%x)", status));
|
|
return status;
|
|
}
|
|
#endif
|
|
//IoInvalidateDeviceRelations (NewExtension->DeviceObject, BusRelations);
|
|
} // !NoPnpPorts
|
|
#endif
|
|
|
|
/*----------------------------------------------------------------------
|
|
write_config_data -
|
|
|----------------------------------------------------------------------*/
|
|
static int write_config_data(PDEVICE_OBJECT Pdo, int val, int val_id)
|
|
{
|
|
HANDLE keyHandle;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
USTR_40 uname;
|
|
|
|
status = IoOpenDeviceRegistryKey(Pdo, PLUGPLAY_REGKEY_DRIVER,
|
|
KEY_WRITE, &keyHandle);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
MyKdPrint(D_Error, ("Err7V\n"))
|
|
return 1;
|
|
}
|
|
switch(val_id)
|
|
{
|
|
case CFG_ID_ISA_BRD_INDEX:
|
|
CToUStr((PUNICODE_STRING)&uname, "isa_board_index", sizeof(uname));
|
|
break;
|
|
|
|
case CFG_ID_NODE_INDEX:
|
|
CToUStr((PUNICODE_STRING)&uname, "CtmNodeId", sizeof(uname));
|
|
break;
|
|
}
|
|
status = ZwSetValueKey (keyHandle,
|
|
(PUNICODE_STRING) &uname,
|
|
0, // type optional
|
|
REG_DWORD,
|
|
&val,
|
|
sizeof(REG_DWORD));
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
MyKdPrint(D_Error, ("Err8V\n"))
|
|
}
|
|
ZwClose(keyHandle);
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
read_config_data -
|
|
|----------------------------------------------------------------------*/
|
|
static int read_config_data(PDEVICE_OBJECT Pdo, int *ret_val, int val_id)
|
|
{
|
|
HANDLE keyHandle;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG tmparr[100];
|
|
USTR_40 uname;
|
|
PKEY_VALUE_PARTIAL_INFORMATION parInfo =
|
|
(PKEY_VALUE_PARTIAL_INFORMATION) &tmparr[0];
|
|
ULONG length;
|
|
int ret_stat = 1; // err
|
|
|
|
//----- go grab some configuration info from registry
|
|
// PLUGPLAY_REGKEY_DRIVER opens up the control\class\{guid}\node
|
|
// PLUGPLAY_REGKEY_DEVICE opens up the enum\enum-type\node\Device Parameters
|
|
status = IoOpenDeviceRegistryKey(Pdo,
|
|
PLUGPLAY_REGKEY_DRIVER,
|
|
STANDARD_RIGHTS_READ,
|
|
&keyHandle);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
return 2; // err
|
|
}
|
|
switch(val_id)
|
|
{
|
|
case CFG_ID_ISA_BRD_INDEX:
|
|
CToUStr((PUNICODE_STRING)&uname, "isa_board_index", sizeof(uname));
|
|
break;
|
|
|
|
case CFG_ID_NODE_INDEX:
|
|
CToUStr((PUNICODE_STRING)&uname, "CtmNodeId", sizeof(uname));
|
|
break;
|
|
}
|
|
// try to order the ISA boards
|
|
status = ZwQueryValueKey (keyHandle,
|
|
(PUNICODE_STRING) &uname,
|
|
KeyValuePartialInformation,
|
|
parInfo,
|
|
sizeof(tmparr),
|
|
&length);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
if (parInfo->Type == REG_DWORD)
|
|
{
|
|
ret_stat = 0; // ok
|
|
*ret_val = *((ULONG *) &parInfo->Data[0]);
|
|
//MyKdPrint(D_Pnp,("Read isa_board_index:%d\n", isa_board_index))
|
|
}
|
|
}
|
|
ZwClose(keyHandle);
|
|
|
|
return ret_stat;
|
|
}
|
|
/*----------------------------------------------------------------------
|
|
AddPortDevice - Setup and Create a pnp port device in response to
|
|
AddDevice ioctl. This can be caused by either:
|
|
* pdo port objects ejected from our driver at board startup.
|
|
|----------------------------------------------------------------------*/
|
|
NTSTATUS AddPortDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo,
|
|
OUT PDEVICE_OBJECT *NewDevObj,
|
|
IN int port_index)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
|
PSERIAL_DEVICE_EXTENSION NewExtension;
|
|
PSERIAL_DEVICE_EXTENSION ext;
|
|
PSERIAL_DEVICE_EXTENSION ParExt;
|
|
|
|
MyKdPrint(D_Pnp, ("AddPortDevice\n"))
|
|
|
|
// Find the parent device
|
|
ext = (PSERIAL_DEVICE_EXTENSION) Pdo->DeviceExtension;
|
|
if (ext == NULL)
|
|
{
|
|
MyKdPrint(D_Pnp, ("Er7E\n"))
|
|
return STATUS_SERIAL_NO_DEVICE_INITED;
|
|
}
|
|
else
|
|
ParExt = ext->board_ext;
|
|
|
|
CheckPortName(Pdo, ParExt, port_index);
|
|
|
|
//----- create a port device
|
|
Driver.Stop_Poll = 1; // flag to stop poll access
|
|
|
|
status = CreatePortDevice(
|
|
Driver.GlobalDriverObject,
|
|
ParExt, // parent ext.
|
|
&NewExtension, // new device ext.
|
|
port_index, // port index, channel number
|
|
1); // is_fdo
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
Driver.Stop_Poll = 0; // flag to stop poll access
|
|
MyKdPrint(D_Error, ("Error Creating Port\n"))
|
|
return STATUS_SERIAL_NO_DEVICE_INITED;
|
|
}
|
|
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
*NewDevObj = NewExtension->DeviceObject;
|
|
|
|
status = StartPortHardware(NewExtension, port_index);
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
Driver.Stop_Poll = 0; // flag to stop poll access
|
|
MyKdPrint(D_Error, ("5D\n"))
|
|
// bugbug: should delete our port here
|
|
return STATUS_SERIAL_NO_DEVICE_INITED;
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
Driver.Stop_Poll = 0; // flag to stop poll access
|
|
Eprintf("CreateBoardDevice Err1A");
|
|
return status;
|
|
}
|
|
|
|
Driver.Stop_Poll = 0; // flag to stop poll access
|
|
|
|
status = STATUS_SUCCESS;
|
|
return status;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
CheckPortName - Make sure the port-name for us in the registry works.
|
|
Get the pnp-port name held in the enum branch, if ours does not match,
|
|
then change it to match(use the pnp-port name.)
|
|
|----------------------------------------------------------------------*/
|
|
NTSTATUS CheckPortName(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN PSERIAL_DEVICE_EXTENSION ParentExt,
|
|
IN int port_index)
|
|
{
|
|
HANDLE keyHandle;
|
|
NTSTATUS status;
|
|
char namestr[20];
|
|
|
|
PORT_CONFIG *port_config;
|
|
|
|
MyKdPrint(D_Pnp, ("CheckPortName\n"))
|
|
|
|
//----- go grab PORTNAME configuration info from registry
|
|
// serial keeps params under ENUM branch so we open DEVICE not DRIVER
|
|
// which is considered CLASS area.
|
|
// opens: enum\device\node\Device Parameters area
|
|
// status = IoOpenDeviceRegistryKey(Pdo, PLUGPLAY_REGKEY_DRIVER,
|
|
|
|
namestr[0] = 0;
|
|
status = IoOpenDeviceRegistryKey(Pdo,
|
|
PLUGPLAY_REGKEY_DEVICE,
|
|
STANDARD_RIGHTS_READ,
|
|
&keyHandle);
|
|
|
|
// go get "Device Parameters\PortName"="COM5"
|
|
// also, key params: PollingPeriod=, Serenumerable=
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
status = get_reg_value(keyHandle, namestr, "PortName", 15);
|
|
if (status) // err
|
|
{
|
|
namestr[0] = 0;
|
|
MyKdPrint(D_Error, ("No PortName\n"))
|
|
}
|
|
else
|
|
{
|
|
MyKdPrint(D_Pnp, ("PortName:%s\n", namestr))
|
|
}
|
|
ZwClose(keyHandle);
|
|
}
|
|
|
|
if ((strlen(namestr) > 10) || (strlen(namestr) <= 0))
|
|
{
|
|
MyKdPrint(D_Error, ("Bad PortName Er1E\n"))
|
|
}
|
|
|
|
port_config = &ParentExt->config->port[port_index];
|
|
|
|
if (my_lstricmp(port_config->Name, namestr) != 0) // it does not match!
|
|
{
|
|
MyKdPrint(D_Pnp, ("port name fixup to:%s, from%s\n",
|
|
namestr, port_config->Name))
|
|
// fix it, use one assigned by port class installer
|
|
strcpy(port_config->Name, namestr);
|
|
write_port_name(ParentExt, port_index);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif // nt50
|