windows-nt/Source/XPSP1/NT/sdktools/pcmcmd/tuples.c

1254 lines
24 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
tuples.c
Abstract:
This program converses with the PCMCIA support driver to display
tuple and other information.
Author:
Bob Rinne
Environment:
User process.
Notes:
Revision History:
Ravisankar Pudipeddi (ravisp) June 27 1997
- command line options & support for multiple controllers
Neil Sandlin (neilsa) Sept 20, 1998
- more commands
--*/
#include <pch.h>
//
// Tuple output strings
//
StringTable CommandCodes[] = {
"CISTPL_NULL", CISTPL_NULL,
"CISTPL_DEVICE", CISTPL_DEVICE,
"CISTPL_LONGLINK_MFC", CISTPL_LONGLINK_MFC,
"CISTPL_CHECKSUM", CISTPL_CHECKSUM,
"CISTPL_LONGLINK_A", CISTPL_LONGLINK_A,
"CISTPL_LONGLINK_C", CISTPL_LONGLINK_C,
"CISTPL_LINKTARGET", CISTPL_LINKTARGET,
"CISTPL_NO_LINK", CISTPL_NO_LINK,
"CISTPL_VERS_1", CISTPL_VERS_1,
"CISTPL_ALTSTR", CISTPL_ALTSTR,
"CISTPL_DEVICE_A", CISTPL_DEVICE_A,
"CISTPL_JEDEC_C", CISTPL_JEDEC_C,
"CISTPL_JEDEC_A", CISTPL_JEDEC_A,
"CISTPL_CONFIG", CISTPL_CONFIG,
"CISTPL_CFTABLE_ENTRY", CISTPL_CFTABLE_ENTRY,
"CISTPL_DEVICE_OC", CISTPL_DEVICE_OC,
"CISTPL_DEVICE_OA", CISTPL_DEVICE_OA,
"CISTPL_GEODEVICE", CISTPL_GEODEVICE,
"CISTPL_GEODEVICE_A", CISTPL_GEODEVICE_A,
"CISTPL_MANFID", CISTPL_MANFID,
"CISTPL_FUNCID", CISTPL_FUNCID,
"CISTPL_FUNCE", CISTPL_FUNCE,
"CISTPL_VERS_2", CISTPL_VERS_2,
"CISTPL_FORMAT", CISTPL_FORMAT,
"CISTPL_GEOMETRY", CISTPL_GEOMETRY,
"CISTPL_BYTEORDER", CISTPL_BYTEORDER,
"CISTPL_DATE", CISTPL_DATE,
"CISTPL_BATTERY", CISTPL_BATTERY,
"CISTPL_ORG", CISTPL_ORG,
//
// CISTPL_END must be the last one in the table.
//
"CISTPL_END", CISTPL_END
};
//
// Procedures
//
NTSTATUS
ReadTuple(
IN HANDLE Handle,
IN LONG SlotNumber,
IN PUCHAR Buffer,
IN LONG BufferSize
)
/*++
Routine Description:
Perform the NT function to get the tuple data from the
pcmcia support driver.
Arguments:
Handle - an open handle to the driver.
SlotNumber - The socket offset
Buffer - return buffer for the data.
BufferSize - the size of the return buffer area.
Return Value:
The results of the NT call.
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK statusBlock;
TUPLE_REQUEST commandBlock;
commandBlock.Socket = (USHORT) SlotNumber;
status = NtDeviceIoControlFile(Handle,
NULL,
NULL,
NULL,
&statusBlock,
IOCTL_GET_TUPLE_DATA,
&commandBlock,
sizeof(commandBlock),
Buffer,
BufferSize);
return status;
}
PUCHAR
FindTupleCodeName(
UCHAR TupleCode
)
/*++
Routine Description:
Return an ascii string that describes the tuple code provided.
Arguments:
TupleCode - what code to look up.
Return Value:
A string pointer - always.
--*/
{
ULONG index;
for (index = 0; CommandCodes[index].CommandCode != CISTPL_END; index++) {
if (CommandCodes[index].CommandCode == TupleCode) {
return CommandCodes[index].CommandName;
}
}
return "Command Unknown";
}
PUCHAR DeviceTypeString[] = {
"DTYPE_NULL",
"DTYPE_ROM",
"DTYPE_OTPROM",
"DTYPE_EPROM",
"DTYPE_EEPROM",
"DTYPE_FLASH",
"DTYPE_SRAM",
"DTYPE_DRAM",
"Reserved8",
"Reserved9",
"Reserveda",
"Reservedb",
"Reservedc",
"DTYPE_FUNCSPEC",
"DTYPE_EXTEND"
"Reservedf",
};
PUCHAR DeviceSpeedString[] = {
"DSPEED_NULL",
"DSPEED_250NS",
"DSPEED_200NS",
"DSPEED_150NS",
"DSPEED_100NS",
"DSPEED_RES1",
"DSPEED_RES2",
"DSPEED_EXT"
};
VOID
DisplayDeviceTuple(
PUCHAR TupleBuffer,
UCHAR TupleSize
)
/*++
Routine Description:
Display the data at the given pointer as a CISTPL_DEVICE structure.
Arguments:
TupleBuffer - the CISTPL_DEVICE to display.
TupleSize - the link value for the tuple.
Return Value:
None
--*/
{
UCHAR mantissa = MANTISSA_RES1;
UCHAR exponent;
UCHAR deviceTypeCode;
UCHAR wps;
UCHAR deviceSpeed;
UCHAR temp;
temp = *TupleBuffer;
deviceTypeCode = DeviceTypeCode(temp);
wps = DeviceWPS(temp);
deviceSpeed = DeviceSpeedField(temp);
temp = *(TupleBuffer + 1);
if (deviceSpeed == DSPEED_EXT) {
exponent = SpeedExponent(temp);
mantissa = SpeedMantissa(temp);
}
printf("DeviceType: %s DeviceSpeed: ", DeviceTypeString[deviceTypeCode]);
if (mantissa != MANTISSA_RES1) {
printf("Mantissa %.2x, Exponent %.2x\n", mantissa, exponent);
} else {
printf("%s\n", DeviceSpeedString[deviceSpeed]);
}
}
VOID
DisplayVers1(
PUCHAR TupleBuffer,
UCHAR TupleSize,
USHORT Crc
)
/*++
Routine Description:
Display the data as a Version tuple
Arguments:
TupleBuffer - the CISTPL_DEVICE to display.
TupleSize - the link value for the tuple.
Return Value:
None
--*/
{
PUCHAR string;
PUCHAR cp;
//
// Step around the MAJOR and MINOR codes of 4/1 at
// the beginning of the tuple to get to the strings.
//
string = TupleBuffer;
string++;
string++;
printf("Manufacturer:\t%s\n", string);
while (*string++) {
}
printf("Product Name:\t%s\n", string);
printf("CRC: \t%.4x\n", Crc);
while (*string++) {
}
printf("Product Info:\t");
if (isprint(*string)) {
printf("%s", string);
} else {
while (*string) {
printf("%.2x ", *string);
string++;
}
}
printf("\n");
}
VOID
DisplayConfigTuple(
PUCHAR TupleBuffer,
UCHAR TupleSize
)
/*++
Routine Description:
Display the data at the given pointer as a CISTPL_CONFIG tuple.
Arguments:
TupleBuffer - the CISTPL_DEVICE to display.
TupleSize - the link value for the tuple.
Return Value:
None
--*/
{
UCHAR sizeField;
UCHAR tpccRfsz;
UCHAR tpccRmsz;
UCHAR tpccRasz;
UCHAR last;
ULONG baseAddress;
PUCHAR ptr;
sizeField = *TupleBuffer;
last = *(TupleBuffer + 1);
tpccRfsz = TpccRfsz(sizeField);
tpccRmsz = TpccRmsz(sizeField);
tpccRasz = TpccRasz(sizeField);
printf("TPCC_SZ %.2x (%.2x/%.2x/%.2x) - Last %.2x\n",
sizeField,
tpccRasz,
tpccRmsz,
tpccRfsz,
last);
baseAddress = 0;
ptr = TupleBuffer + 2;
switch (tpccRasz) {
case 3:
baseAddress = *(ptr + 3) << 24;
case 2:
baseAddress |= *(ptr + 2) << 16;
case 1:
baseAddress |= *(ptr + 1) << 8;
default:
baseAddress |= *ptr;
}
printf("Base Address: %8x - ", baseAddress);
ptr += tpccRasz + 1;
baseAddress = 0;
switch (tpccRmsz) {
case 3:
baseAddress = *(ptr + 3) << 24;
case 2:
baseAddress |= *(ptr + 2) << 16;
case 1:
baseAddress |= *(ptr + 1) << 8;
default:
baseAddress |= *ptr;
}
printf("Register Presence Mask: %8x\n", baseAddress);
}
PUCHAR
ProcessMemSpace(
PUCHAR Buffer,
UCHAR MemSpace
)
/*++
Routine Description:
Display and process memspace information
Arguments:
Buffer - start of memspace information
MemSpace - the memspace value from the feature byte.
Return Value:
location of byte after all memory space information
--*/
{
PUCHAR ptr = Buffer;
UCHAR item = *ptr++;
UCHAR lengthSize;
UCHAR addrSize;
UCHAR number;
UCHAR hasHostAddress;
ULONG cardAddress;
ULONG length;
ULONG hostAddress;
if (MemSpace == 3) {
lengthSize = (item & 0x18) >> 3;
addrSize = (item & 0x60) >> 5;
number = (item & 0x07) + 1;
hasHostAddress = item & 0x80;
printf("(0x%.2x) %s - %d entries - LengthSize %d - AddrSize %d\n",
item,
hasHostAddress ? "Host address" : "no host",
number,
lengthSize,
addrSize);
while (number) {
cardAddress = length = hostAddress = 0;
switch (lengthSize) {
case 3:
length |= (*(ptr + 2)) << 16;
case 2:
length |= (*(ptr + 1)) << 8;
case 1:
length |= *ptr;
}
ptr += lengthSize;
switch (addrSize) {
case 3:
cardAddress |= (*(ptr + 2)) << 16;
case 2:
cardAddress |= (*(ptr + 1)) << 8;
case 1:
cardAddress |= *ptr;
}
ptr += addrSize;
if (hasHostAddress) {
switch (addrSize) {
case 3:
hostAddress |= (*(ptr + 2)) << 16;
case 2:
hostAddress |= (*(ptr + 1)) << 8;
case 1:
hostAddress |= *ptr;
}
printf("\tHost 0x%.8x ", hostAddress * 256);
ptr += addrSize;
} else {
printf("\t");
}
printf("Card 0x%.8x Size 0x%.8x\n",
cardAddress * 256,
length * 256);
number--;
}
}
return ptr;
}
USHORT VoltageConversionTable[16] = {
10, 12, 13, 14, 20, 25, 30, 35,
40, 45, 50, 55, 60, 70, 80, 90
};
UCHAR
ConvertVoltage(
UCHAR MantissaExponentByte,
UCHAR ExtensionByte
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
USHORT power;
USHORT value;
value = VoltageConversionTable[(MantissaExponentByte >> 3) & 0x0f];
power = 1;
if ((MantissaExponentByte & EXTENSION_BYTE_FOLLOWS) &&
(ExtensionByte < 100)) {
value = (100 * value + (ExtensionByte & 0x7f));
power += 2;
}
power = (MantissaExponentByte & 0x07) - 4 - power;
while (power > 0) {
value *= 10;
power--;
}
while (power < 0) {
value /= 10;
power++;
}
return (UCHAR) value;
}
PUCHAR PowerTypeTable[] = {
"Nominal",
"Minimum",
"Maximum",
"Static",
"Average",
"Peak",
"PwrDown"
};
PUCHAR VoltagePinTable[] = {
"Vcc",
"Vpp1",
"Vpp2"
};
PUCHAR
ProcessPower(
PUCHAR Buffer,
UCHAR FeatureByte
)
/*++
Routine Description:
Display and process power information
Arguments:
Power - start of power information
Return Value:
location of byte after all power information
--*/
{
UCHAR powerSelect;
UCHAR bit;
UCHAR item;
UCHAR entries;
PUCHAR ptr = Buffer;
UCHAR count = FeatureByte;
powerSelect = *ptr;
printf("Parameter Selection Byte = 0x%.2x\n", powerSelect);
entries = 0;
while (entries < count) {
powerSelect = *ptr++;
printf("\t%s \"%d%d%d%d%d%d%d%d\"\n",
VoltagePinTable[entries],
powerSelect & 0x80 ? 1 : 0,
powerSelect & 0x40 ? 1 : 0,
powerSelect & 0x20 ? 1 : 0,
powerSelect & 0x10 ? 1 : 0,
powerSelect & 0x08 ? 1 : 0,
powerSelect & 0x04 ? 1 : 0,
powerSelect & 0x02 ? 1 : 0,
powerSelect & 0x01 ? 1 : 0);
for (bit = 0; bit < 7; bit++) {
if (powerSelect & (1 << bit)) {
if (!bit) {
//
// Convert nominal power for output.
//
item = ConvertVoltage(*ptr,
(UCHAR) (*ptr & EXTENSION_BYTE_FOLLOWS ?
*(ptr + 1) :
(UCHAR) 0));
}
printf("\t\t%s power =\t%d/10 volts\n", PowerTypeTable[bit], item);
while (*ptr++ & EXTENSION_BYTE_FOLLOWS) {
}
}
}
entries++;
}
return ptr;
}
PUCHAR
ProcessTiming(
PUCHAR Buffer
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PUCHAR ptr = Buffer;
UCHAR item = *ptr++;
UCHAR reservedScale = (item & 0xe0) >> 5;
UCHAR readyBusyScale = (item & 0x1c) >> 2;
UCHAR waitScale = (item & 0x03);
printf("Timing (0x%.2x): reservedScale 0x%.2x, readyBusyScale 0x%.2x, waitScale 0x%.2x\n",
item,
reservedScale,
readyBusyScale,
waitScale);
if (waitScale != 3) {
printf("\tWaitSpeed 0x%.2x\n", *ptr);
ptr++;
while (*ptr & EXTENSION_BYTE_FOLLOWS) {
ptr++;
}
}
if (readyBusyScale != 7) {
printf("\tReadyBusySpeed 0x%.2x\n", *ptr);
ptr++;
while (*ptr & EXTENSION_BYTE_FOLLOWS) {
ptr++;
}
}
if (reservedScale != 7) {
printf("\tReservedSpeed 0x%.2x\n", *ptr);
ptr++;
while (*ptr & EXTENSION_BYTE_FOLLOWS) {
ptr++;
}
}
return ptr;
}
PUCHAR
ProcessIoSpace(
PUCHAR Buffer
)
/*++
Routine Description:
Display and process iospace information
Arguments:
Buffer - start of IoSpace information
Return Value:
location of byte after all power information
--*/
{
UCHAR item;
UCHAR ioAddrLines;
UCHAR bus8;
UCHAR bus16;
UCHAR ranges;
UCHAR lengthSize;
UCHAR addressSize;
ULONG address;
PUCHAR ptr = Buffer;
item = *ptr++;
ioAddrLines = item & IO_ADDRESS_LINES_MASK;
bus8 = Is8BitAccess(item);
bus16 = Is16BitAccess(item);
ranges = HasRanges(item);
printf("IoSpace (%.2x): IoAddressLines %.2d - %s/%s\n",
item,
ioAddrLines,
bus8 ? "8bit" : "",
bus16 ? "16bit" : "");
//
// This is what it looks like the IBM token ring card
// does. It is unclear in the specification if this
// is correct or not.
//
if ((!ranges) && (!ioAddrLines)) {
ranges = 0xFF;
}
if (ranges) {
if (ranges == 0xff) {
//
// This is based on the tuple data as given by
// the IBM token ring card. This is not the
// way I would interpret the specification.
//
addressSize = 2;
lengthSize = 1;
ranges = 1;
} else {
item = *ptr++;
ranges = item & 0x0f;
ranges++;
addressSize = GetAddressSize(item);
lengthSize = GetLengthSize(item);
}
while (ranges) {
address = 0;
switch (addressSize) {
case 4:
address |= (*(ptr + 3)) << 24;
case 3:
address |= (*(ptr + 2)) << 16;
case 2:
address |= (*(ptr + 1)) << 8;
case 1:
address |= *ptr;
}
ptr += addressSize;
printf("\tStart %.8x - Length ", address);
address = 0;
switch (lengthSize) {
case 4:
address |= (*(ptr + 3)) << 24;
case 3:
address |= (*(ptr + 2)) << 16;
case 2:
address |= (*(ptr + 1)) << 8;
case 1:
address |= *ptr;
}
ptr += lengthSize;
printf("%.8x\n", address);
ranges--;
}
} else {
printf("\tResponds to all ranges.\n");
}
return ptr;
}
PUCHAR
ProcessIrq(
PUCHAR Buffer
)
/*++
Routine Description:
Display and process irq information
Arguments:
Buffer - start of irq information
Return Value:
location of byte after all irq information
--*/
{
PUCHAR ptr = Buffer;
UCHAR level;
USHORT mask;
ULONG irqNumber;
level = *ptr++;
if (!level) {
//
// NOTE: It looks like Future Domain messed up on this
// and puts an extra zero byte into the structure.
// skip it for now.
//
level = *ptr++;
}
if (level & 0x80) {
printf("Share ");
}
if (level & 0x40) {
printf("Pulse ");
}
if (level & 0x20) {
printf("Level ");
}
if (level & 0x10) {
mask = *ptr | (*(ptr + 1) << 8);
ptr += 2;
printf("mask = %.4x - ", mask);
for (irqNumber = 0; mask; irqNumber++, mask = mask >> 1) {
if (mask & 0x0001) {
printf("IRQ%d ", irqNumber);
}
}
printf("- ");
if (level & 0x08) {
printf("Vend ");
}
if (level & 0x04) {
printf("Berr ");
}
if (level & 0x02) {
printf("IOCK ");
}
if (level & 0x01) {
printf("NMI");
}
printf("\n");
} else {
printf("irq = %d\n", level & 0x0f);
}
return ptr;
}
PUCHAR InterfaceTypeStrings[] = {
"Memory",
"I/O",
"Reserved 2",
"Reserved 3",
"Custom 0",
"Custom 1",
"Custom 2",
"Custom 3",
"Reserved 8",
"Reserved 9",
"Reserved a",
"Reserved b",
"Reserved c",
"Reserved d",
"Reserved e",
"Reserved f",
};
VOID
DisplayCftableEntryTuple(
PUCHAR TupleBuffer,
UCHAR TupleSize
)
/*++
Routine Description:
Display the data at the given pointer as a CISTPL_CFTABLE_ENTRY tuple.
Arguments:
TupleBuffer - the CISTPL_DEVICE to display.
TupleSize - the link value for the tuple.
Return Value:
None
--*/
{
UCHAR temp;
UCHAR item;
UCHAR defaultbit;
UCHAR memSpace;
UCHAR power;
PUCHAR ptr;
temp = *TupleBuffer;
item = IntFace(temp);
defaultbit = Default(temp);
temp = ConfigEntryNumber(temp);
printf("ConfigurationEntryNumber %.2x (%s/%s)\n",
temp,
item ? "intface" : "",
defaultbit ? "default" : "");
ptr = TupleBuffer + 1;
if (item) {
temp = *ptr++;
item = temp & 0x0F;
printf("InterfaceDescription (%.2x) %s (%s/%s/%s/%s)\n",
temp,
InterfaceTypeStrings[item],
temp & 0x80 ? "WaitReq" : "",
temp & 0x40 ? "RdyBsy" : "",
temp & 0x20 ? "WP" : "",
temp & 0x10 ? "BVD" : "");
}
item = *ptr++;
memSpace = MemSpaceInformation(item);
power = PowerInformation(item);
printf("The following structures are present:\n");
switch (power) {
case 3:
printf("Vcc, Vpp1, Vpp2; ");
break;
case 2:
printf("Vcc and Vpp; ");
break;
case 1:
printf("Vcc; ");
break;
case 0:
break;
}
if (power) {
ptr = ProcessPower(ptr, power);
}
if (TimingInformation(item)) {
ptr = ProcessTiming(ptr);
}
if (IoSpaceInformation(item)) {
ptr = ProcessIoSpace(ptr);
}
if (IRQInformation(item)) {
printf("IRQ: ");
ptr = ProcessIrq(ptr);
}
switch (memSpace) {
case 3:
printf("Memory selection: ");
break;
case 2:
printf("Length and Card Address: ");
break;
case 1:
printf("2-byte length: ");
break;
case 0:
break;
}
if (memSpace) {
ptr = ProcessMemSpace(ptr, memSpace);
}
if (MiscInformation(item)) {
printf("Misc fields present");
}
printf("\n");
}
UCHAR TplList[] = {
CISTPL_DEVICE,
CISTPL_VERS_1,
CISTPL_CONFIG,
CISTPL_CFTABLE_ENTRY,
CISTPL_MANFID,
CISTPL_END
};
static unsigned short crc16a[] = {
0000000, 0140301, 0140601, 0000500,
0141401, 0001700, 0001200, 0141101,
0143001, 0003300, 0003600, 0143501,
0002400, 0142701, 0142201, 0002100,
};
static unsigned short crc16b[] = {
0000000, 0146001, 0154001, 0012000,
0170001, 0036000, 0024000, 0162001,
0120001, 0066000, 0074000, 0132001,
0050000, 0116001, 0104001, 0043000,
};
USHORT
GetCRC(
PUCHAR TupleBuffer
)
/*++
Routine Description:
Using the same algorithm as Windows 95, calculate the CRC value
to be appended with the manufacturer name and device name to
obtain the unique identifier for the PCCARD.
Arguments:
TupleBuffer - the tuple data
Return Value:
A USHORT CRC value.
--*/
{
USHORT crc = 0;
USHORT index;
USHORT length;
PUCHAR tupleData;
PUCHAR cp;
PUCHAR tplBuffer;
UCHAR tupleCode;
UCHAR linkValue;
UCHAR tmp;
//
// Calculate CRC
//
tplBuffer = TupleBuffer;
printf("Calculating CRC ");
while (1) {
tupleData = tplBuffer + 2;
tupleCode = *tplBuffer++;
if (tupleCode == CISTPL_END) {
break;
}
linkValue = (tupleCode) ? *tplBuffer++ : 0;
length = linkValue;
printf("%x", tupleCode);
for (index = 0; TplList[index] != CISTPL_END; index++) {
if (tupleCode == TplList[index]) {
//
// This one is included in the CRC calculation
//
printf("*", tupleCode);
if (tupleCode == CISTPL_VERS_1) {
cp = tupleData + 2;
//
// Include all of the manufacturer name.
//
while (*cp) {
cp++;
}
//
// Include the product string
//
cp++;
while (*cp) {
cp++;
}
cp++;
length = (USHORT)(cp - tupleData);
}
for (cp = tupleData; length; length--, cp++) {
tmp = *cp ^ (UCHAR)crc;
crc = (crc >> 8) ^ crc16a[tmp & 0x0f] ^ crc16b[tmp >> 4];
}
break;
}
}
printf(" ");
tplBuffer = tplBuffer + linkValue;
}
printf("++\n");
return crc;
}
VOID
DumpTuple(
PUCHAR Buffer
)
/*++
Routine Description:
Control routine to process the tuple data.
Arguments:
Buffer - the tuple data.
Return Value:
None
--*/
{
PUCHAR tupleBuffer = Buffer;
PUCHAR tupleCodeName;
USHORT crc;
UCHAR index;
UCHAR tupleCode;
UCHAR linkValue;
crc = GetCRC(tupleBuffer);
while (1) {
tupleCode = *tupleBuffer++;
linkValue = (tupleCode) ? *tupleBuffer : 0;
if (tupleCode == CISTPL_END) {
break;
}
tupleCodeName = FindTupleCodeName(tupleCode);
printf("Tuple Code\t%s\t%.2x - Link %.2x:", tupleCodeName, tupleCode, linkValue);
if (linkValue) {
for (index = 0; index < linkValue; index++) {
if ((index & 0x0F) == 0) {
printf("\n");
}
printf(" %.2x", *(tupleBuffer + index + 1));
}
}
printf("\n");
tupleBuffer++;
switch (tupleCode) {
case CISTPL_DEVICE:
DisplayDeviceTuple(tupleBuffer, linkValue);
break;
case CISTPL_VERS_1:
DisplayVers1(tupleBuffer, linkValue, crc);
break;
case CISTPL_CONFIG:
DisplayConfigTuple(tupleBuffer, linkValue);
break;
case CISTPL_CFTABLE_ENTRY:
DisplayCftableEntryTuple(tupleBuffer, linkValue);
break;
case CISTPL_LONGLINK_MFC:
case CISTPL_LONGLINK_A:
case CISTPL_LONGLINK_C:
case CISTPL_LINKTARGET:
case CISTPL_NO_LINK:
default:
break;
}
tupleBuffer = tupleBuffer + linkValue;
printf("\n");
}
}
VOID
DumpCIS(
HANDLE Handle,
ULONG Slot,
PUCHAR Buffer,
ULONG BufferSize
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS status;
PULONG longBuffer;
PUCHAR currentBufferPointer;
UCHAR hexBuffer[260];
UCHAR ascii[100];
ULONG i;
UCHAR c;
longBuffer = (PULONG) Buffer;
for (i = 0; i < (BufferSize / sizeof(ULONG)); i++) {
*longBuffer = 0;
longBuffer++;
}
status = ReadTuple(Handle, Slot, Buffer, BufferSize);
//
// Don't bother dumping tuples for cards that aren't there.
//
if (!NT_SUCCESS(status)) {
return;
}
printf("\nCIS Tuples for Socket Number %d:\n\n", Slot);
hexBuffer[0] = '\0';
ascii[0] = '\0';
currentBufferPointer = Buffer;
for (i = 0; i < 512; i++) {
c = *currentBufferPointer;
sprintf(hexBuffer, "%s %.2x", hexBuffer, c);
c = isprint(c) ? c : '.';
sprintf(ascii, "%s%c", ascii, c);
currentBufferPointer++;
//
// Display the line every 16 bytes.
//
if ((i & 0x0f) == 0x0f) {
printf("%s", hexBuffer);
printf(" *%s*\n", ascii);
hexBuffer[0] = '\0';
ascii[0] = '\0';
}
}
printf("%s", hexBuffer);
printf("\t\t*%s*\n\n", ascii);
DumpTuple(Buffer);
}