303 lines
6.3 KiB
C
303 lines
6.3 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991-1998 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
utils.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Neil Sandlin (neilsa) 26-Apr-99
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode only.
|
|||
|
|
|||
|
--*/
|
|||
|
#include "pch.h"
|
|||
|
|
|||
|
//
|
|||
|
// Internal References
|
|||
|
//
|
|||
|
|
|||
|
ULONG
|
|||
|
MemCardGetCapacityFromCIS(
|
|||
|
IN PMEMCARD_EXTENSION memcardExtension
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
MemCardGetCapacityFromBootSector(
|
|||
|
IN PMEMCARD_EXTENSION memcardExtension
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
MemCardProbeForCapacity(
|
|||
|
IN PMEMCARD_EXTENSION memcardExtension
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE,MemCardGetCapacityFromCIS)
|
|||
|
#pragma alloc_text(PAGE,MemCardGetCapacityFromBootSector)
|
|||
|
#pragma alloc_text(PAGE,MemCardProbeForCapacity)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
MemCardGetCapacity(
|
|||
|
IN PMEMCARD_EXTENSION memcardExtension
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
device extension for the card
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG capacity;
|
|||
|
|
|||
|
capacity = MemCardGetCapacityFromCIS(memcardExtension);
|
|||
|
|
|||
|
if (capacity) {
|
|||
|
return capacity;
|
|||
|
}
|
|||
|
|
|||
|
capacity = MemCardGetCapacityFromBootSector(memcardExtension);
|
|||
|
|
|||
|
if (capacity) {
|
|||
|
return capacity;
|
|||
|
}
|
|||
|
|
|||
|
return MemCardProbeForCapacity(memcardExtension);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
MemCardGetCapacityFromBootSector(
|
|||
|
IN PMEMCARD_EXTENSION memcardExtension
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
device extension for the card
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
BOOT_SECTOR_INFO BootSector;
|
|||
|
ULONG capacity = 0;
|
|||
|
|
|||
|
status = MEMCARD_READ(memcardExtension, 0, &BootSector, sizeof(BootSector));
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
|
|||
|
#define BYTES_PER_SECTOR 512
|
|||
|
//
|
|||
|
// see if this really looks like a boot sector
|
|||
|
// These are the same tests done in the win9x sram support
|
|||
|
//
|
|||
|
if ((BootSector.JumpByte == 0xE9 || BootSector.JumpByte == 0xEB) &&
|
|||
|
|
|||
|
BootSector.BytesPerSector == BYTES_PER_SECTOR &&
|
|||
|
|
|||
|
BootSector.SectorsPerCluster != 0 &&
|
|||
|
|
|||
|
BootSector.ReservedSectors == 1 &&
|
|||
|
|
|||
|
(BootSector.NumberOfFATs == 1 || BootSector.NumberOfFATs == 2) &&
|
|||
|
|
|||
|
BootSector.RootEntries != 0 && (BootSector.RootEntries & 15) == 0 &&
|
|||
|
|
|||
|
(BootSector.TotalSectors != 0 || BootSector.BigTotalSectors != 0) &&
|
|||
|
|
|||
|
BootSector.SectorsPerFAT != 0 &&
|
|||
|
|
|||
|
BootSector.SectorsPerTrack != 0 &&
|
|||
|
|
|||
|
BootSector.Heads != 0 &&
|
|||
|
|
|||
|
BootSector.MediaDescriptor >= 0xF0) {
|
|||
|
|
|||
|
//
|
|||
|
// Finally it appears valid, return total size of region.
|
|||
|
//
|
|||
|
capacity = BootSector.TotalSectors * BYTES_PER_SECTOR;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
return capacity;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
MemCardGetCapacityFromCIS(
|
|||
|
IN PMEMCARD_EXTENSION memcardExtension
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is a quick and dirty routine to read the tuples of the card, if they
|
|||
|
exist, to get the capacity.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
device extension for the card
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The # of bytes of memory on the device
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UCHAR tupleData[16];
|
|||
|
ULONG bytesRead;
|
|||
|
ULONG dataCount;
|
|||
|
ULONG unitSize;
|
|||
|
ULONG unitCount;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
//
|
|||
|
// get device capacity
|
|||
|
// all this stuff should really be in the bus driver
|
|||
|
//
|
|||
|
|
|||
|
bytesRead = (memcardExtension->PcmciaBusInterface.ReadConfig)(memcardExtension->UnderlyingPDO,
|
|||
|
PCCARD_ATTRIBUTE_MEMORY,
|
|||
|
tupleData,
|
|||
|
0,
|
|||
|
16);
|
|||
|
|
|||
|
if ((bytesRead != 16) || (tupleData[0] != 1)){
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
dataCount = (ULONG)tupleData[1];
|
|||
|
|
|||
|
if ((dataCount < 2) || (dataCount>14)){
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
i = 3;
|
|||
|
if ((tupleData[2] & 7) == 7) {
|
|||
|
while(tupleData[i] & 0x80) {
|
|||
|
if ((i-2) > dataCount) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
i++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ((tupleData[i]&7) == 7) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
unitSize = 512 << ((tupleData[i]&7)*2);
|
|||
|
unitCount = (tupleData[i]>>3)+1;
|
|||
|
|
|||
|
return(unitCount * unitSize);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
MemCardProbeForCapacity(
|
|||
|
IN PMEMCARD_EXTENSION memcardExtension
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Since we were unable to determine the card capacity through other means,
|
|||
|
here we actually write stuff out on the card to check how big it is.
|
|||
|
This algorithm for testing the card capacity was ported from win9x.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
device extension for the card
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
byte capacity of device
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
ULONG capacity = 0;
|
|||
|
USHORT origValue, ChkValue, StartValue;
|
|||
|
USHORT mcSig = 'Mc';
|
|||
|
USHORT zeroes = 0;
|
|||
|
#define SRAM_BLK_SIZE (16*1024)
|
|||
|
ULONG CardOff = SRAM_BLK_SIZE;
|
|||
|
USHORT CurValue;
|
|||
|
|
|||
|
if ((memcardExtension->PcmciaInterface.IsWriteProtected)(memcardExtension->UnderlyingPDO)) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
if (!NT_SUCCESS(MEMCARD_READ (memcardExtension, 0, &origValue, sizeof(origValue))) ||
|
|||
|
!NT_SUCCESS(MEMCARD_WRITE(memcardExtension, 0, &mcSig, sizeof(mcSig))) ||
|
|||
|
!NT_SUCCESS(MEMCARD_READ (memcardExtension, 0, &ChkValue, sizeof(ChkValue)))) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
if (ChkValue != mcSig) {
|
|||
|
//
|
|||
|
// not sram
|
|||
|
//
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
for (;;) {
|
|||
|
if (!NT_SUCCESS(MEMCARD_READ (memcardExtension, CardOff, &CurValue, sizeof(CurValue))) ||
|
|||
|
!NT_SUCCESS(MEMCARD_WRITE(memcardExtension, CardOff, &zeroes, sizeof(zeroes))) ||
|
|||
|
!NT_SUCCESS(MEMCARD_READ (memcardExtension, CardOff, &ChkValue, sizeof(ChkValue))) ||
|
|||
|
!NT_SUCCESS(MEMCARD_READ (memcardExtension, 0, &StartValue, sizeof(StartValue)))) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// We stop when either we can't write 0 anymore or the 0
|
|||
|
// has wrapped over the 0x9090 at card offset 0
|
|||
|
|
|||
|
if (ChkValue != zeroes || StartValue == zeroes) {
|
|||
|
capacity = CardOff;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// Restore the saved value from the start of the block.
|
|||
|
|
|||
|
if (!NT_SUCCESS(MEMCARD_WRITE(memcardExtension, CardOff, &CurValue, sizeof(CurValue)))) {
|
|||
|
break;
|
|||
|
}
|
|||
|
CardOff += SRAM_BLK_SIZE; // increment to the next block
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// try to restore original value
|
|||
|
//
|
|||
|
MEMCARD_WRITE(memcardExtension, 0, &origValue, sizeof(origValue));
|
|||
|
|
|||
|
return capacity;
|
|||
|
}
|