mirror of https://github.com/lianthony/NT4.0
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.
1380 lines
32 KiB
1380 lines
32 KiB
/*++
|
|
Module Name:
|
|
|
|
ctape.h
|
|
|
|
Abstract:
|
|
|
|
Rescan.c has the support functions for ctape.c
|
|
to get all the tape device info. (scsi and non scsi).
|
|
This also does the actual scsi bus rescan.
|
|
|
|
Author:
|
|
|
|
Dieter Achtelstetter (A-DACH) 8/4/1994
|
|
|
|
NOTE:
|
|
--*/
|
|
|
|
extern "C" {
|
|
#include <nt.h>
|
|
#include <ntddscsi.h>
|
|
#include <ntdddisk.h>
|
|
#include <ntddcdrm.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
}
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <process.h>
|
|
#include <memory.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <WINREG.H>
|
|
#include <CTYPE.H>
|
|
#include <WCHAR.H>
|
|
#include <ntddpcm.h>
|
|
#include "resource.h"
|
|
#include "..\..\pcmcia\pcminfo\getconf.h"
|
|
#include "index.h"
|
|
#include "setup.h"
|
|
#include "device.h"
|
|
#include "rescan.h"
|
|
#include "detect.h"
|
|
#include "uni.h"
|
|
#include "debug.h"
|
|
#include "adapreg.h"
|
|
#include "qic117.h"
|
|
|
|
|
|
|
|
//#define GetTapeInfoDEBUG
|
|
|
|
|
|
|
|
#ifdef GetTapeInfoDEBUG
|
|
|
|
int
|
|
main(
|
|
int argc,
|
|
char ** argv,
|
|
char ** argp)
|
|
{
|
|
struct DeviceInfoT TapeDeviceInfo[20]; //Struct to hold ol the info on all the tape devices.
|
|
DWORD TapeDeviceCount;
|
|
BOOL Ret;
|
|
|
|
|
|
//---- Rescan bus and then get all the device info.
|
|
Ret = GetAllTapeDeviceInfo(TRUE,TapeDeviceInfo,&TapeDeviceCount);
|
|
if(Ret != TRUE)
|
|
{
|
|
printf("Error Getting Tape info stuff\n");
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
#endif
|
|
|
|
VOID
|
|
GenerateDeviceDisplayName(
|
|
PDEVICEINFO DeviceInfo);
|
|
|
|
VOID
|
|
GetScsiTapeDeviceMap(
|
|
UCHAR PortNumber,
|
|
UCHAR BUS,
|
|
UCHAR DeviceID,
|
|
UCHAR DeviceLUN,
|
|
UCHAR * DeviceName,
|
|
DWORD BuffLen);
|
|
|
|
VOID
|
|
SaveDeviceInfo(
|
|
PSCSI_INQUIRY_DATA InquiryData,
|
|
PINQUIRYDATA DetailedInquiryData,
|
|
PDEVICEINFO DeviceInfo);
|
|
|
|
HANDLE
|
|
OpenScsiPort(
|
|
BYTE Port);
|
|
|
|
DWORD
|
|
ExtractDeviceInfo(
|
|
PSCSI_ADAPTER_BUS_INFO AdapterInfo,
|
|
BYTE ScsiPortNumber,
|
|
int ScsiBusIndex,
|
|
PDEVICEINFO_LIST DeviceInfo,
|
|
UCHAR * DeviceCount,
|
|
BYTE DeviceTypes);
|
|
|
|
BOOL
|
|
GetScsiPortInfo(
|
|
BYTE Port,
|
|
BOOL Rescan,
|
|
PSCSI_ADAPTER_BUS_INFO AdapterInfoBuffer,
|
|
DWORD AdapterInfoBufferSize);
|
|
|
|
|
|
VOID InitAdapter(
|
|
PSCSI_ADAPTER_REGC AdapterReg,
|
|
PSCSI_HOST_ADAPTER Adapter,
|
|
int ScsiPortNumber);
|
|
|
|
VOID
|
|
SetDeviceType(
|
|
PDEVICEINFO DeviceInfo,
|
|
PSCSI_INQUIRY_DATA InquiryData);
|
|
|
|
VOID
|
|
GetAdapterResources(
|
|
PSCSI_HOST_ADAPTER Adapter);
|
|
|
|
|
|
VOID
|
|
GetAdapterFrindlyName(
|
|
PSCSI_HOST_ADAPTER AdapterInfo,
|
|
PSCSI_ADAPTER_REGC AdapterReg,
|
|
POPTIONLISTC OptionList);
|
|
|
|
VOID
|
|
AddQic117DetectDevice(
|
|
PDEVICEINFO_LIST TapeDeviceList);
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetScsiMiniPortDriverName
|
|
//*
|
|
//* PURPOSE:
|
|
//*
|
|
//*
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
void
|
|
GetScsiMiniPortDriverName(
|
|
int PortNumber,
|
|
PCHAR DriverNameBuffer,
|
|
DWORD DriverNameBufferSize)
|
|
{
|
|
CHAR RegKeyString[MaxRegKeySize];
|
|
HKEY HK;
|
|
int Ret;
|
|
DWORD Type;
|
|
SCSI_ADAPTER_REGC ScsiAdapterReg;
|
|
|
|
ScsiAdapterReg.OpenAdapterRegKey(PortNumber);
|
|
|
|
|
|
ScsiAdapterReg.GetAdapterRegDriverName(
|
|
DriverNameBuffer,
|
|
DriverNameBufferSize);
|
|
|
|
#if 0
|
|
//
|
|
//---- Create Reg key string to open
|
|
//
|
|
_snprintf(RegKeyString,MaxRegKeySize,SCSI_PORT_STRING, PortNumber);
|
|
|
|
//
|
|
//----- Open the Scsi port key
|
|
//
|
|
Ret = RegOpenKeyA(HKEY_LOCAL_MACHINE,RegKeyString,&HK);
|
|
if(Ret != ERROR_SUCCESS)
|
|
return;
|
|
|
|
//
|
|
//--- Get the driver name
|
|
//
|
|
Ret = RegQueryValueExA(HK,DRIVER_STRING,
|
|
NULL,&Type,(BYTE*)DriverNameBuffer,&DriverNameBufferSize);
|
|
if(Ret != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(HK);
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
DebugPrintf(("-- GetScsiMiniPortDriverName (NEW) :%s\n",DriverNameBuffer));
|
|
//RegCloseKey(HK);
|
|
}
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetAllTapeDeviceInfo
|
|
//*
|
|
//* PURPOSE: Gets the info on all tape devices and stores is in PAR2.
|
|
//* If PAR1 == TRUE it will Rescan for any TAPE devices
|
|
//* and then do the same.
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
BOOL
|
|
GetAllTapeDeviceInfo(
|
|
BOOL Rescan,
|
|
PDEVICEINFO_LIST TapeDeviceList,
|
|
POPTIONLISTC OptionList)
|
|
{
|
|
BOOL ScsiStatus,NonScsiStatus;
|
|
|
|
TapeDeviceList->SetReboot(FALSE);
|
|
|
|
//
|
|
//--- Clear the current list
|
|
//
|
|
TapeDeviceList->Clear();
|
|
|
|
//
|
|
//----- Get all the scsi tape devices.
|
|
//
|
|
ScsiStatus = GetAllScsiTapeDeviceInfo(Rescan,
|
|
TapeDeviceList,OptionList);
|
|
|
|
//
|
|
//---- Get nono scsi devices
|
|
//
|
|
NonScsiStatus = GetAllNonScsiTapeDeviceInfo(Rescan,
|
|
Rescan,TapeDeviceList,OptionList);
|
|
|
|
return(NonScsiStatus && ScsiStatus);
|
|
}
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:DetectQIC117
|
|
//* RETURNS:
|
|
//*********************************************************************
|
|
BOOL
|
|
DetectQIC117(
|
|
VOID)
|
|
{
|
|
OPTIONC Option;
|
|
DWORD Ret;
|
|
BOOL Remove=TRUE;
|
|
BOOL Disabled;
|
|
|
|
Option.SetDriverName("qic117");
|
|
|
|
//
|
|
//---- We can only detect the qic117 device
|
|
//---- by starting the driver.
|
|
//
|
|
|
|
if(!Option.IsDisabled() )
|
|
{
|
|
Ret = Option.StartDriver();
|
|
if(Ret == ERROR_SERVICE_DISABLED)
|
|
{
|
|
//
|
|
//--- The service key is still intacked but the
|
|
//--- driver was disbaled using the SetupDi* APIS.
|
|
//
|
|
Option.DelService();
|
|
Disabled=TRUE;
|
|
}
|
|
else
|
|
Disabled=FALSE;
|
|
}
|
|
else
|
|
Disabled=TRUE;
|
|
|
|
|
|
if( Disabled )
|
|
{
|
|
//
|
|
//---- The service is not installed but the driver is
|
|
//---- in the drivers directory. Lets start the driver
|
|
//---- to see if the device is pressent.
|
|
//
|
|
DWORD Ret;
|
|
|
|
//
|
|
//---- Atempt to create the service
|
|
//
|
|
Ret = Option.CreateService();
|
|
|
|
//
|
|
//---- If the servie already existed
|
|
//---- make shure it is set to start
|
|
//
|
|
if(Ret == ERROR_SERVICE_EXISTS)
|
|
{
|
|
|
|
if(!Option.SetStartUpType(SERVICE_SYSTEM_START))
|
|
return(FALSE);
|
|
|
|
Ret = NO_ERROR;
|
|
Remove = TRUE;
|
|
}
|
|
|
|
//
|
|
//---- Start the driver
|
|
//
|
|
if(Ret == NO_ERROR)
|
|
{
|
|
BOOL Found=FALSE;
|
|
|
|
Ret = Option.StartDriver();
|
|
|
|
if(Ret != ERROR_BAD_UNIT
|
|
&& Ret != ERROR_MR_MID_NOT_FOUND)
|
|
{
|
|
//
|
|
//--- There is a qic117 device
|
|
//
|
|
Found = TRUE;
|
|
|
|
|
|
|
|
}
|
|
//
|
|
//--- We only enabled the service so that
|
|
//--- we can detect the device. The user still
|
|
//--- has to install the driver threw the inf
|
|
//--- so I will disable the service again.
|
|
//
|
|
|
|
if(Remove)
|
|
Option.SetStartUpType(SERVICE_DISABLED);
|
|
|
|
return(Found);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:AddQic117DetectDevice
|
|
//*
|
|
//* PURPOSE: Gets the info on all non scsi tape devices and stores is in PAR2.
|
|
//* If PAR1 == TRUE it will Rescan for any TAPE devices and then do the same.
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
|
|
VOID
|
|
AddQic117DetectDevice(
|
|
PDEVICEINFO_LIST TapeDeviceList)
|
|
{
|
|
PTAPEDEVC TapeDevice;
|
|
PDEVICEINFO TapeDeviceInfo;
|
|
|
|
|
|
//
|
|
//--- Add a new tape device to the list
|
|
//
|
|
TapeDevice = TapeDeviceList->Append();
|
|
TapeDeviceInfo = &TapeDevice->DeviceInfo;
|
|
|
|
|
|
strcpy((PCHAR)TapeDeviceInfo->DeviceDisplayName,"Floppy Tape Device");
|
|
TapeDeviceInfo->Option.SetDriverName("QIC117");
|
|
TapeDeviceInfo->Option.SetOption("QIC117");
|
|
|
|
strcpy((PCHAR)TapeDeviceInfo->VendorId,"QIC117");
|
|
strcpy((PCHAR)TapeDeviceInfo->ProductId,"QIC117");
|
|
|
|
|
|
TapeDeviceInfo->DeviceClaimed = FALSE;
|
|
TapeDeviceInfo->SubType = SUB_TYPE_FLOPPY;
|
|
TapeDeviceInfo->DeviceType = TYPE_TAPE;
|
|
|
|
TapeDevice->InitType();
|
|
|
|
//TapeDeviceList->SetReboot(TRUE);
|
|
|
|
|
|
}
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetAllNonScsiTapeDeviceInfo
|
|
//*
|
|
//* PURPOSE: Gets the info on all non scsi tape devices and stores is in PAR2.
|
|
//* If PAR1 == TRUE it will Rescan for any TAPE devices and then do the same.
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
BOOL
|
|
GetAllNonScsiTapeDeviceInfo(
|
|
BOOL RatleDevice,
|
|
BOOL Rescan,
|
|
PDEVICEINFO_LIST TapeDeviceList,
|
|
POPTIONLISTC OptionList)
|
|
{
|
|
int Ret;
|
|
//int i = 0;
|
|
//int TapeDeviceIndex = -1;
|
|
DWORD Device=0;
|
|
PTAPEDEVC TapeDevice;
|
|
PDEVICEINFO TapeDeviceInfo;
|
|
|
|
BYTE Buff2[MaxRegKeySize];
|
|
QIC117 TapeInfo;
|
|
|
|
|
|
if(Rescan)
|
|
{
|
|
|
|
if(DetectQIC117())
|
|
{
|
|
|
|
//
|
|
//--- A qic117 device was found in the detection
|
|
//--- process lets add it to the device list.
|
|
//
|
|
AddQic117DetectDevice(TapeDeviceList);
|
|
return(TRUE);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(Device = 0; Device < MAX_DEVICE_COUNT;Device++)
|
|
{
|
|
|
|
|
|
//
|
|
//--- Open the tape info for the Non scsi tape device of number Device
|
|
//
|
|
if( !TapeInfo.Open(Device,Rescan))
|
|
{
|
|
//
|
|
//--- Device doesn't exist
|
|
//
|
|
continue;
|
|
}
|
|
|
|
|
|
//
|
|
//--- Add a new tape device to the list
|
|
//
|
|
TapeDevice = TapeDeviceList->Append();
|
|
TapeDeviceInfo = &TapeDevice->DeviceInfo;
|
|
|
|
|
|
//
|
|
//--- Get the registry info for this device
|
|
//
|
|
TapeInfo.GetRegTapeInfo(TapeDeviceInfo);
|
|
|
|
if(RatleDevice)
|
|
{
|
|
//
|
|
//---- I get the device name in the registry. But qic117 tape devices will
|
|
//---- actualy have the drivers name in the registry till someone did something to the
|
|
//---- tape device.
|
|
//---- So if it still has the driver name in the registry i will
|
|
//---- get the tape status. This does the trick.
|
|
//----
|
|
//
|
|
if(!_strnicmp((PCHAR)TapeDeviceInfo->DeviceDisplayName,
|
|
"QIC-40/QIC-80",sizeof("QIC-40/QIC-80")-1) ||
|
|
|
|
!_strnicmp((PCHAR)TapeDeviceInfo->DeviceDisplayName,
|
|
"Floppy tape drive",sizeof("Floppy tape drive")-1)
|
|
|
|
)
|
|
{
|
|
|
|
Ret = DoRatleDevice((PCHAR)TapeDeviceInfo->DeviceName,Device);
|
|
if(Ret == TRUE);
|
|
{
|
|
//
|
|
//---- We actualy rattled somthing
|
|
//---- So we need to get the identifier again.
|
|
//
|
|
TapeInfo.GetRegDeviceIdentifier(
|
|
(PCHAR) TapeDeviceInfo->DeviceDisplayName,
|
|
DEVICE_DISPLAY_NAME_LEN);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
//--- Set device type . If the driver name is QIC117 it is a floppy tape
|
|
//--- else I do not know
|
|
//
|
|
|
|
if(!_stricmp(TapeDeviceInfo->Option.GetDriverName(),QIC117S))
|
|
TapeDeviceInfo->SubType = SUB_TYPE_FLOPPY;
|
|
else
|
|
TapeDeviceInfo->SubType = SUB_TYPE_OTHER;
|
|
|
|
|
|
|
|
|
|
TapeDeviceInfo->DeviceType = TYPE_TAPE;
|
|
|
|
//
|
|
//---- If we got this info threw the detection process
|
|
//---- We still need to officialy installe the driver for this device.
|
|
//---- If we say this device is not claimed this will happen.
|
|
//
|
|
TapeDeviceInfo->DeviceClaimed = TRUE;
|
|
|
|
|
|
TapeDevice->InitType();
|
|
|
|
DebugPrintf(("-- GetAllNonScsiTapeDeviceInfo\n"));
|
|
DebugPrintf(("-- .DeviceDisplayName=%s\n",
|
|
(char*)TapeDeviceInfo->DeviceDisplayName));
|
|
DebugPrintf(("-- .DeviceName=%s\n",
|
|
(char*)TapeDeviceInfo->DeviceName));
|
|
DebugPrintf(("-- .DeviceDriverName=%s\n",
|
|
TapeDeviceInfo->Option.GetDriverName()));
|
|
|
|
|
|
TapeInfo.Close();
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:DoRatleDevice
|
|
//*
|
|
//* PURPOSE: Since the qic117 driver dosn't but the actual device Indenifier in the
|
|
//* registry till the tape device has been tuched i need to do this myself.
|
|
//* I do this by getting the tape status.
|
|
//*
|
|
//* RETURNS: TRUE if it actualy did somthing FALSE if it did not.
|
|
//*
|
|
//*********************************************************************
|
|
BOOL
|
|
DoRatleDevice(
|
|
PCHAR DeviceName,
|
|
DWORD Device)
|
|
{
|
|
HANDLE hTape;
|
|
CHAR TapeString[100];
|
|
|
|
//
|
|
//----Open the tape in DeviceName.
|
|
//
|
|
_snprintf(TapeString,100,"\\\\.\\%s",DeviceName);
|
|
hTape = CreateFileA(TapeString,GENERIC_READ,0,0,OPEN_EXISTING,0,NULL);
|
|
if(hTape == INVALID_HANDLE_VALUE)
|
|
{
|
|
//
|
|
//--- Couldn't open tape device.
|
|
//---- Probaply somthing else has it open
|
|
//
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
//---- Ratle the tape.
|
|
//
|
|
GetTapeStatus(hTape);
|
|
|
|
CloseHandle(hTape);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:OpenScsiPort
|
|
//*
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
HANDLE
|
|
OpenScsiPort(
|
|
BYTE Port)
|
|
{
|
|
CHAR ScsiPortString[20];
|
|
|
|
//
|
|
//---- Init ScsiPortString to first scsiport
|
|
//
|
|
_snprintf(ScsiPortString,20,"\\\\.\\Scsi%d:",Port);
|
|
|
|
//
|
|
//---- Open the scsi port
|
|
//
|
|
return( CreateFileA( ScsiPortString,GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,0) );
|
|
|
|
}
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetAllScsiTapeDeviceInfo
|
|
//*
|
|
//* PURPOSE: Gets the info on all scsi tape devices and stores is
|
|
//* in PAR2. If PAR1 == TRUE it will Rescan for any TAPE
|
|
//* devices and then do the same.
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
BOOL
|
|
GetAllScsiTapeDeviceInfo(
|
|
BOOL Rescan,
|
|
PDEVICEINFO_LIST TapeDeviceList,
|
|
POPTIONLISTC OptionList)
|
|
{
|
|
BYTE ScsiPortNumber = 0;
|
|
UCHAR Count;
|
|
|
|
//
|
|
//---- Will hold all the info for all the devices on one port
|
|
//
|
|
PSCSI_ADAPTER_BUS_INFO AdapterInfoBuffer;
|
|
|
|
//
|
|
//---- Index into DeviceInfo
|
|
//
|
|
|
|
int ScsiBusIndex;
|
|
int DeviceIndex = 0;
|
|
|
|
|
|
//
|
|
//---- Allocate memory for bus data
|
|
//
|
|
AdapterInfoBuffer = (PSCSI_ADAPTER_BUS_INFO) malloc(0x400);
|
|
if(AdapterInfoBuffer == NULL)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
//
|
|
//---- Loop they all the scsiports if we faile to open one
|
|
//---- we are done and will get out of this loop
|
|
//
|
|
while (TRUE)
|
|
{
|
|
|
|
if( !GetScsiPortInfo(ScsiPortNumber,Rescan,
|
|
AdapterInfoBuffer,0x400) )
|
|
break;
|
|
|
|
|
|
//
|
|
//---- Loop threw all the bus's on the current adapter.
|
|
//
|
|
for (ScsiBusIndex=0; ScsiBusIndex < AdapterInfoBuffer->NumberOfBuses; ScsiBusIndex++)
|
|
{
|
|
|
|
DeviceIndex += ExtractDeviceInfo(
|
|
AdapterInfoBuffer,
|
|
ScsiPortNumber,
|
|
ScsiBusIndex,
|
|
TapeDeviceList,
|
|
&Count,
|
|
SEQUENTIAL_ACCESS_DEVICE);
|
|
|
|
}
|
|
|
|
ScsiPortNumber++;
|
|
}
|
|
//
|
|
//----- We are done
|
|
//
|
|
free(AdapterInfoBuffer);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetAllScsiTapeDeviceInfo
|
|
//*
|
|
//* PURPOSE: Gets the info on all scsi tape devices and stores is
|
|
//* in PAR2. If PAR1 == TRUE it will Rescan for any TAPE
|
|
//* devices and then do the same.
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
BOOL
|
|
GetAllScsiInfo(
|
|
BOOL Rescan,
|
|
PSCSI_HOST_ADAPTER_LIST AdapterList,
|
|
POPTIONLISTC OptionList)
|
|
{
|
|
PSCSI_HOST_ADAPTER AdapterInfo;
|
|
PSCSIDEVC Adapter;
|
|
BYTE ScsiPortNumber = 0;
|
|
UCHAR Count;
|
|
SCSI_ADAPTER_REGC AdapterReg;
|
|
|
|
//
|
|
//---- Will hold all the info for all the devices on one port
|
|
//
|
|
PSCSI_ADAPTER_BUS_INFO AdapterInfoBuffer;
|
|
|
|
//
|
|
//---- Index into DeviceInfo
|
|
//
|
|
|
|
int ScsiBusIndex;
|
|
int DeviceIndex = 0;
|
|
|
|
//
|
|
//---- Allocate memory for bus data
|
|
//
|
|
AdapterInfoBuffer = (PSCSI_ADAPTER_BUS_INFO) malloc(0x400);
|
|
if(AdapterInfoBuffer == NULL)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//--- Make shure we start with an empty list
|
|
//
|
|
AdapterList->Clear();
|
|
|
|
|
|
//
|
|
//---- Loop they all the scsiports if we faile to open one
|
|
//---- we are done and will get out of this loop
|
|
//
|
|
|
|
|
|
while (GetScsiPortInfo(ScsiPortNumber,Rescan,
|
|
AdapterInfoBuffer,0x400))
|
|
{
|
|
|
|
|
|
//
|
|
//---- We have a new SCSI adapter
|
|
//
|
|
|
|
//
|
|
//--- Open the registry info for this adapter
|
|
//
|
|
AdapterReg.OpenAdapterRegKey(ScsiPortNumber);
|
|
|
|
|
|
|
|
//
|
|
//---- Add a new adapter structure to the list
|
|
//
|
|
Adapter = AdapterList->Append();
|
|
AdapterInfo = &Adapter->AdapterInfo;
|
|
|
|
|
|
//
|
|
//--- Init the basic adapter info
|
|
//
|
|
InitAdapter(
|
|
&AdapterReg,
|
|
AdapterInfo,
|
|
ScsiPortNumber);
|
|
|
|
|
|
//
|
|
//---- Get the adapters frindly name
|
|
//
|
|
|
|
GetAdapterFrindlyName(
|
|
AdapterInfo,
|
|
&AdapterReg,
|
|
OptionList);
|
|
|
|
|
|
|
|
DeviceIndex = 0;
|
|
|
|
//
|
|
//---- Loop threw all the bus's on the current adapter.
|
|
//
|
|
for (ScsiBusIndex=0; ScsiBusIndex < AdapterInfoBuffer->NumberOfBuses; ScsiBusIndex++)
|
|
{
|
|
|
|
DeviceIndex += ExtractDeviceInfo(
|
|
AdapterInfoBuffer,
|
|
ScsiPortNumber,
|
|
ScsiBusIndex,
|
|
&AdapterInfo->Devices,
|
|
&Count,
|
|
ALL_DEVICES);
|
|
|
|
AdapterInfo->BusCount++;
|
|
}
|
|
|
|
ScsiPortNumber++;
|
|
|
|
}
|
|
|
|
//
|
|
//----- We are done
|
|
//
|
|
free(AdapterInfoBuffer);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetAdapterFrindlyName
|
|
//*
|
|
//*********************************************************************
|
|
|
|
|
|
VOID
|
|
GetAdapterFrindlyName(
|
|
PSCSI_HOST_ADAPTER AdapterInfo,
|
|
PSCSI_ADAPTER_REGC AdapterReg,
|
|
POPTIONLISTC OptionList)
|
|
{
|
|
|
|
if(! *AdapterInfo->Option.GetOptionName() )
|
|
{
|
|
//
|
|
//--- We do not have the devices frindly name
|
|
//--- so we need to get it from the inf.
|
|
//
|
|
if(OptionList->FindOptionOnOption(&AdapterInfo->Option))
|
|
{
|
|
//
|
|
//--- We got a frindly name for this device
|
|
//--- out of OptionList so lets save it in the registry.
|
|
//--- This is done so if someone removes the
|
|
//--- driver for this adapter but didn't reboot
|
|
//--- I still have a frindly name for it.
|
|
//
|
|
|
|
AdapterReg->SetAdapterRegFrindlyName(
|
|
AdapterInfo->Option.GetOptionName());
|
|
|
|
AdapterReg->SetAdapterRegMfgName(
|
|
AdapterInfo->Option.GetMfgName());
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//----- Error. We have a scsi port but where unable to
|
|
//----- find its frindly name in any INF of CLASS
|
|
//----- SCSIAdapter. If we have a driver name we will use it
|
|
//----- if not we will use IDS_UnknowSCSIAdapter
|
|
//
|
|
|
|
if( *AdapterInfo->Option.GetDriverName() )
|
|
{
|
|
AdapterInfo->Option.SetOptionName(
|
|
AdapterInfo->Option.GetDriverName());
|
|
}
|
|
else
|
|
{
|
|
AdapterInfo->Option.SetOptionName(
|
|
Astr(GetString(IDS_UnknowSCSIAdapter)));
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetAllScsiTapeDeviceInfo
|
|
//*
|
|
//* PURPOSE: Gets the info on all scsi tape devices and stores is
|
|
//* in PAR2. If PAR1 == TRUE it will Rescan for any TAPE
|
|
//* devices and then do the same.
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
VOID InitAdapter(
|
|
PSCSI_ADAPTER_REGC AdapterReg,
|
|
PSCSI_HOST_ADAPTER AdapterInfo,
|
|
int ScsiPortNumber)
|
|
{
|
|
AdapterInfo->BusCount = 0;
|
|
AdapterInfo->Port = ScsiPortNumber;
|
|
|
|
//
|
|
//--- Init both DriverName and Option with driver name
|
|
//--- from the scsiport registry info
|
|
//
|
|
|
|
AdapterReg->GetAdapterRegDriverName(
|
|
AdapterInfo->Option.GetDriverName(),
|
|
MAX_OPTION_LENGTH);
|
|
|
|
|
|
|
|
AdapterInfo->Option.SetOption(AdapterInfo->Option.GetDriverName());
|
|
|
|
|
|
//
|
|
//--- See if we saved the frindly name already
|
|
//
|
|
AdapterReg->GetAdapterRegFrindlyName(
|
|
AdapterInfo->Option.GetOptionName(),
|
|
MAX_OPTION_DISPLAY_STRING_LENGTH);
|
|
|
|
AdapterReg->GetAdapterRegMfgName(
|
|
AdapterInfo->Option.GetMfgName(),
|
|
MAX_OPTION_DISPLAY_STRING_LENGTH);
|
|
|
|
|
|
//
|
|
//---- Crate the ScsiPort# string
|
|
//
|
|
swprintf(AdapterInfo->DeviceName,L"ScsiPort%i",ScsiPortNumber);
|
|
|
|
//
|
|
//--- Get the resources for this adapter
|
|
//
|
|
GetAdapterResources(AdapterInfo);
|
|
|
|
}
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetAdapterResources
|
|
//*
|
|
//* PURPOSE:
|
|
//* RETURNS:
|
|
//*********************************************************************
|
|
VOID
|
|
GetAdapterResources(
|
|
PSCSI_HOST_ADAPTER AdapterInfo)
|
|
{
|
|
CHAR RegKeyString[MaxRegKeySize];
|
|
HKEY HKInitiator;
|
|
LONG Ret;
|
|
DWORD ValueType;
|
|
BYTE ResourceListBuff[512];
|
|
DWORD ResourceListBuffSize = 512;
|
|
|
|
//
|
|
//---- Open adapter key
|
|
//
|
|
|
|
_snprintf(RegKeyString,MaxRegKeySize,
|
|
SCSI_INITIATOR_RESOURCE_STRING, (char*)AdapterInfo->Option.GetDriverName());
|
|
|
|
Ret = RegOpenKeyA(HKEY_LOCAL_MACHINE,RegKeyString,&HKInitiator);
|
|
if(Ret != ERROR_SUCCESS)
|
|
return;
|
|
|
|
//
|
|
//---- Get resources for this adapter from the resourcemap in
|
|
//---- the registry.
|
|
//
|
|
|
|
_snwprintf((WCHAR*)RegKeyString,MaxRegKeySize,
|
|
L"\\Device\\%s.Raw",AdapterInfo->DeviceName);
|
|
|
|
Ret = RegQueryValueEx(HKInitiator,
|
|
(WCHAR*)RegKeyString,
|
|
0,
|
|
&ValueType,
|
|
ResourceListBuff,
|
|
&ResourceListBuffSize);
|
|
|
|
if(Ret != ERROR_SUCCESS)
|
|
return;
|
|
|
|
//
|
|
//---- Extract the resource info
|
|
//
|
|
|
|
|
|
ExtractResourceFromResourceList(
|
|
&AdapterInfo->Configuration,
|
|
(VOID*) ResourceListBuff,
|
|
FirstResourceOnly,
|
|
NULL);
|
|
}
|
|
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:OpenScsiPort
|
|
//*
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
BOOL
|
|
GetScsiPortInfo(
|
|
BYTE Port,
|
|
BOOL Rescan,
|
|
PSCSI_ADAPTER_BUS_INFO AdapterInfoBuffer,
|
|
DWORD AdapterInfoBufferSize)
|
|
{
|
|
HANDLE ScsiPortHandle;
|
|
DWORD BytesTransferred;
|
|
|
|
//
|
|
//---- Open Scsi Port
|
|
//
|
|
|
|
ScsiPortHandle = OpenScsiPort( Port);
|
|
|
|
if( ScsiPortHandle == INVALID_HANDLE_VALUE )
|
|
return(FALSE);
|
|
|
|
//
|
|
//---- Rescan Current Scsi Port if Rescan == TRUE
|
|
//
|
|
if(Rescan)
|
|
{
|
|
if( !DeviceIoControl( ScsiPortHandle,
|
|
IOCTL_SCSI_RESCAN_BUS,NULL,0,NULL,0,&BytesTransferred,NULL ) )
|
|
{
|
|
CloseHandle(ScsiPortHandle);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
//---- Get all the bus data.
|
|
//
|
|
memset(AdapterInfoBuffer,0,0x400);
|
|
if (!DeviceIoControl( ScsiPortHandle,
|
|
IOCTL_SCSI_GET_INQUIRY_DATA,NULL,0,AdapterInfoBuffer,
|
|
AdapterInfoBufferSize,&BytesTransferred,NULL))
|
|
{
|
|
CloseHandle( ScsiPortHandle);
|
|
return(FALSE);
|
|
}
|
|
|
|
CloseHandle(ScsiPortHandle);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetAllScsiTapeDeviceInfo
|
|
//*
|
|
//* PURPOSE: Gets the info on all scsi tape devices and stores is
|
|
//* in PAR2. If PAR1 == TRUE it will Rescan for any TAPE
|
|
//* devices and then do the same.
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
DWORD
|
|
ExtractDeviceInfo(
|
|
PSCSI_ADAPTER_BUS_INFO AdapterInfo,
|
|
BYTE ScsiPortNumber,
|
|
int ScsiBusIndex,
|
|
PDEVICEINFO_LIST TapeDeviceList,
|
|
UCHAR * DeviceCount,
|
|
BYTE DeviceTypes)
|
|
{
|
|
PSCSI_BUS_DATA BusData;
|
|
PSCSI_INQUIRY_DATA InquiryData;
|
|
PINQUIRYDATA DetailedInquiryData;
|
|
int ScsiDeviceIndex;
|
|
int DeviceIndex = -1;
|
|
PDEVICEINFO CurDeviceInfo;
|
|
PTAPEDEVC TapeDevice;
|
|
|
|
|
|
//
|
|
//---- Pointer to current Addapter info.
|
|
//
|
|
BusData = &AdapterInfo->BusData[ScsiBusIndex];
|
|
|
|
InquiryData = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + BusData->InquiryDataOffset);
|
|
|
|
for (ScsiDeviceIndex=0; ScsiDeviceIndex < BusData->NumberOfLogicalUnits; ScsiDeviceIndex++)
|
|
{
|
|
//
|
|
// Determine the perpherial type.
|
|
//
|
|
|
|
//
|
|
//---- We are looking for a specific type or we want them all
|
|
//
|
|
if( (((PINQUIRYDATA)InquiryData->InquiryData)->DeviceType == DeviceTypes) ||
|
|
DeviceTypes == ALL_DEVICES)
|
|
{
|
|
|
|
DeviceIndex++;
|
|
|
|
|
|
TapeDevice = TapeDeviceList->Append();
|
|
CurDeviceInfo = &TapeDevice->DeviceInfo;
|
|
|
|
|
|
SetDeviceType(CurDeviceInfo ,InquiryData);
|
|
|
|
//
|
|
//---- Set pointer to product info
|
|
//
|
|
DetailedInquiryData = ((PINQUIRYDATA)InquiryData->InquiryData);
|
|
DetailedInquiryData->VendorSpecific[0] = 0;
|
|
|
|
CurDeviceInfo->PortNumber = ScsiPortNumber;
|
|
CurDeviceInfo->InitiatorID = BusData->InitiatorBusId;
|
|
CurDeviceInfo->BUS = ScsiBusIndex;
|
|
|
|
GetScsiMiniPortDriverName(ScsiPortNumber,
|
|
(char*)CurDeviceInfo->InitiatorNameString,60);
|
|
|
|
SaveDeviceInfo(
|
|
InquiryData,DetailedInquiryData,CurDeviceInfo);
|
|
|
|
//
|
|
//--- If this is a tape device
|
|
//--- do the tape device specific stuff.
|
|
//--- Like map the device name to a driver .
|
|
//
|
|
if(DeviceTypes == SEQUENTIAL_ACCESS_DEVICE)
|
|
{
|
|
|
|
GetScsiTapeDeviceMap(
|
|
ScsiPortNumber,
|
|
ScsiBusIndex,
|
|
InquiryData->TargetId,
|
|
InquiryData->Lun,
|
|
CurDeviceInfo->DeviceName,
|
|
60);
|
|
|
|
//FindOptionThatWouldClaimeDevice(CurDeviceInfo);
|
|
}
|
|
|
|
TapeDevice->InitType();
|
|
}
|
|
|
|
InquiryData = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + InquiryData->NextInquiryDataOffset);
|
|
}
|
|
|
|
return(*DeviceCount);
|
|
}
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:SaveDeviceInfo
|
|
//*
|
|
//*********************************************************************
|
|
VOID
|
|
SetDeviceType(
|
|
PDEVICEINFO DeviceInfo,
|
|
PSCSI_INQUIRY_DATA InquiryData)
|
|
{
|
|
|
|
//
|
|
//---- Translate devcie types.
|
|
//
|
|
|
|
|
|
DebugPrintf(("-- SetDeviceType: %i\n",
|
|
((PINQUIRYDATA)InquiryData->InquiryData)->DeviceType));
|
|
|
|
|
|
switch( ((PINQUIRYDATA)InquiryData->InquiryData)->DeviceType )
|
|
{
|
|
case DIRECT_ACCESS_DEVICE:
|
|
case OPTICAL_DEVICE:
|
|
|
|
if( ((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia )
|
|
DeviceInfo->DeviceType = TYPE_RM_DISK;
|
|
else
|
|
DeviceInfo->DeviceType = TYPE_DISK;
|
|
break;
|
|
case SEQUENTIAL_ACCESS_DEVICE:
|
|
DeviceInfo->DeviceType = TYPE_TAPE;
|
|
break;
|
|
case PRINTER_DEVICE:
|
|
DeviceInfo->DeviceType = TYPE_PRINTER;
|
|
break;
|
|
case PROCESSOR_DEVICE:
|
|
DeviceInfo->DeviceType = TYPE_SCANNER;
|
|
break;
|
|
case WRITE_ONCE_READ_MULTIPLE_DEVICE:
|
|
DeviceInfo->DeviceType = TYPE_WORM;
|
|
break;
|
|
case READ_ONLY_DIRECT_ACCESS_DEVICE:
|
|
DeviceInfo->DeviceType = TYPE_CD_ROM;
|
|
break;
|
|
case SCANNER_DEVICE:
|
|
DeviceInfo->DeviceType = TYPE_SCANNER;
|
|
break;
|
|
//case OPTICAL_DEVICE:
|
|
// DeviceInfo->DeviceType = TYPE_OPTICAL;
|
|
// break;
|
|
case MEDIUM_CHANGER:
|
|
DeviceInfo->DeviceType = TYPE_JUKEBOX;
|
|
break;
|
|
case COMMUNICATION_DEVICE:
|
|
DeviceInfo->DeviceType = TYPE_JUKEBOX;
|
|
break;
|
|
default:
|
|
DeviceInfo->DeviceType = TYPE_NON;
|
|
break;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
|
|
}
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:SaveDeviceInfo
|
|
//*
|
|
//*********************************************************************
|
|
VOID
|
|
SaveDeviceInfo(
|
|
PSCSI_INQUIRY_DATA InquiryData,
|
|
PINQUIRYDATA DetailedInquiryData,
|
|
PDEVICEINFO DeviceInfo)
|
|
{
|
|
|
|
DeviceInfo->ID = InquiryData->TargetId;
|
|
DeviceInfo->LUN = InquiryData->Lun;
|
|
strncpy((char*)DeviceInfo->VendorId,(char*)DetailedInquiryData->VendorId,
|
|
sizeof( (((INQUIRYDATA * )0)->VendorId)) );
|
|
strncpy((char*)DeviceInfo->ProductId,(char*)DetailedInquiryData->ProductId,
|
|
sizeof( (((INQUIRYDATA * )0)->ProductId)) );
|
|
strncpy((char*)DeviceInfo->ProductRevisionLevel,(char*)DetailedInquiryData->ProductRevisionLevel,
|
|
sizeof( (((INQUIRYDATA * )0)->ProductRevisionLevel)) );
|
|
|
|
DeviceInfo->DeviceClaimed = InquiryData->DeviceClaimed;
|
|
DeviceInfo->SubType = SUB_TYPE_SCSI;
|
|
|
|
//
|
|
//--- No idea on option list index at this time
|
|
//
|
|
|
|
//DeviceInfo->OptionIndex = UNKNOW_OPTIONLIST_INDEX;
|
|
|
|
|
|
GenerateDeviceDisplayName(DeviceInfo);
|
|
|
|
|
|
DebugPrintf(("-- SaveDeviceInfo\n"));
|
|
DebugPrintf(("-- DeviceInfo->ID=%i\n",DeviceInfo->ID));
|
|
DebugPrintf(("-- DeviceInfo->LUN=%i\n",DeviceInfo->LUN));
|
|
DebugPrintf(("-- DeviceInfo->VendorId=%s\n",DeviceInfo->VendorId));
|
|
DebugPrintf(("-- DeviceInfo->ProductId=%s\n",DeviceInfo->ProductId));
|
|
DebugPrintf(("-- DeviceInfo->ProductRevisionLevel=%s\n",DeviceInfo->ProductRevisionLevel));
|
|
DebugPrintf(("-- DeviceInfo->DeviceClaimed=%i\n",DeviceInfo->DeviceClaimed));
|
|
DebugPrintf(("-- DeviceInfo->DeviceInfo->SubType=%i\n",DeviceInfo->SubType));
|
|
|
|
|
|
}
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GenerateDeviceDisplayName
|
|
//*
|
|
//* PURPOSE: Creates a DeviceName that the user will see from
|
|
//* VendorId + ProductId
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
VOID
|
|
GenerateDeviceDisplayName(
|
|
PDEVICEINFO DeviceInfo)
|
|
{
|
|
UCHAR * p;
|
|
int i;
|
|
//
|
|
//--- Make a copy of VendorId and ProductId.
|
|
//--- Since I do not want to change the original for detection.
|
|
//
|
|
memcpy((char*)DeviceInfo->DisplayVendorId,(char*)DeviceInfo->VendorId,VENDER_ID_LEN);
|
|
memcpy((char*)DeviceInfo->DisplayProductId,(char*)DeviceInfo->ProductId,PRODUCT_ID_LEN);
|
|
|
|
DeviceInfo->DisplayVendorId[VENDER_ID_LEN] = '\0';
|
|
DeviceInfo->DisplayProductId[PRODUCT_ID_LEN] = '\0';
|
|
|
|
|
|
//
|
|
//--- Remove trailing non printible chars and spaces
|
|
//
|
|
p = DeviceInfo->DisplayVendorId + VENDER_ID_LEN-1;
|
|
while( (p > DeviceInfo->DisplayVendorId) && ( !isprint(*p) ||(*p == ' ')) )
|
|
{
|
|
*p = '\0';
|
|
p--;
|
|
}
|
|
|
|
p = DeviceInfo->DisplayProductId + PRODUCT_ID_LEN-1;
|
|
while( (p > DeviceInfo->DisplayProductId) && ( !isprint(*p) || (*p == ' ')) )
|
|
{
|
|
*p = '\0';
|
|
p--;
|
|
}
|
|
|
|
//
|
|
//---- Create DeviceDisplayName
|
|
//
|
|
strcpy((char*)DeviceInfo->DeviceDisplayName,(char*)DeviceInfo->DisplayVendorId);
|
|
strcat((char*)DeviceInfo->DeviceDisplayName," ");
|
|
strcat((char*)DeviceInfo->DeviceDisplayName,(char*)DeviceInfo->DisplayProductId);
|
|
|
|
|
|
}
|
|
|
|
|
|
//*********************************************************************
|
|
//* FUNCTION:GetScsiTapeDeviceMap
|
|
//*
|
|
//* PURPOSE: Get the tape# identifer from the registry for this
|
|
//* tape device.
|
|
//* RETURNS:
|
|
//*
|
|
//*********************************************************************
|
|
VOID
|
|
GetScsiTapeDeviceMap(
|
|
UCHAR PortNumber,
|
|
UCHAR BUS,
|
|
UCHAR DeviceID,
|
|
UCHAR DeviceLUN,
|
|
UCHAR * DeviceName,
|
|
DWORD BuffLen)
|
|
{
|
|
CHAR RegKeyString[MaxRegKeySize];
|
|
HKEY HK;
|
|
int Ret;
|
|
DWORD Type;
|
|
DWORD Len = BuffLen;
|
|
|
|
//
|
|
//---- Create Reg key string to open
|
|
//
|
|
_snprintf(RegKeyString,MaxRegKeySize,SCSI_DEVICE_NAME_STRING,
|
|
PortNumber,
|
|
BUS,
|
|
DeviceID,
|
|
DeviceLUN);
|
|
|
|
//
|
|
//--- Open key
|
|
//
|
|
Ret = RegOpenKeyA(HKEY_LOCAL_MACHINE,RegKeyString,&HK);
|
|
if(Ret != ERROR_SUCCESS)
|
|
{
|
|
//
|
|
//--- Key didn't open
|
|
//
|
|
strcpy((char*)DeviceName,Astr(GetString(IDS_NotAvailible)) );
|
|
return;
|
|
}
|
|
|
|
//
|
|
//--- Get value data for TAPE_DEVICE_STRING. This is
|
|
//--- the tape% string
|
|
//
|
|
Ret = RegQueryValueExA( HK, TAPE_DEVICE_STRING,
|
|
NULL, &Type,(LPBYTE) DeviceName, &Len);
|
|
if(Ret != ERROR_SUCCESS)
|
|
{
|
|
//
|
|
//--- Value Name not found
|
|
//
|
|
strcpy((char*)DeviceName,Astr(GetString(IDS_NotAvailible)) );
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|