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.
237 lines
6.5 KiB
237 lines
6.5 KiB
/*++
|
|
|
|
Copyright (c) 1991-1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
io.c
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Neil Sandlin (neilsa) 26-Apr-99
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
--*/
|
|
#include "pch.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,MemCardIrpReadWrite)
|
|
#pragma alloc_text(PAGE,MemCardReadWrite)
|
|
#endif
|
|
|
|
|
|
|
|
NTSTATUS
|
|
MemCardIrpReadWrite(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles read/write irps for the memory card. It validates
|
|
parameters and calls MemCardReadWrite to do the real work.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the object that represents the device
|
|
that I/O is to be done on.
|
|
|
|
Irp - a pointer to the I/O Request Packet for this request.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if the packet was successfully read or written; the
|
|
appropriate error is propogated otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PMEMCARD_EXTENSION memcardExtension = DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
BOOLEAN writeOperation;
|
|
|
|
//
|
|
// If the device is not active (not started yet or removed) we will
|
|
// just fail this request outright.
|
|
//
|
|
if ( memcardExtension->IsRemoved || !memcardExtension->IsStarted) {
|
|
|
|
if ( memcardExtension->IsRemoved) {
|
|
status = STATUS_DELETE_PENDING;
|
|
} else {
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
goto ReadWriteComplete;
|
|
}
|
|
|
|
if (((irpSp->Parameters.Read.ByteOffset.LowPart +
|
|
irpSp->Parameters.Read.Length) > memcardExtension->ByteCapacity) ||
|
|
(irpSp->Parameters.Read.ByteOffset.HighPart != 0)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto ReadWriteComplete;
|
|
}
|
|
|
|
//
|
|
// verify that user is really expecting some I/O operation to
|
|
// occur.
|
|
//
|
|
if (!irpSp->Parameters.Read.Length) {
|
|
//
|
|
// Complete this zero length request with no boost.
|
|
//
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
goto ReadWriteComplete;
|
|
}
|
|
|
|
if ((DeviceObject->Flags & DO_VERIFY_VOLUME) && !(irpSp->Flags & SL_OVERRIDE_VERIFY_VOLUME)) {
|
|
//
|
|
// The disk changed, and we set this bit. Fail
|
|
// all current IRPs for this device; when all are
|
|
// returned, the file system will clear
|
|
// DO_VERIFY_VOLUME.
|
|
//
|
|
status = STATUS_VERIFY_REQUIRED;
|
|
goto ReadWriteComplete;
|
|
}
|
|
|
|
writeOperation = (irpSp->MajorFunction == IRP_MJ_WRITE) ? TRUE : FALSE;
|
|
|
|
//
|
|
// Do the operation
|
|
//
|
|
status = MemCardReadWrite(memcardExtension,
|
|
irpSp->Parameters.Read.ByteOffset.LowPart,
|
|
MmGetSystemAddressForMdl(Irp->MdlAddress),
|
|
irpSp->Parameters.Read.Length,
|
|
writeOperation);
|
|
|
|
ReadWriteComplete:
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
Irp->IoStatus.Information = irpSp->Parameters.Read.Length;
|
|
} else {
|
|
Irp->IoStatus.Information = 0;
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
MemCardReadWrite(
|
|
IN PMEMCARD_EXTENSION memcardExtension,
|
|
IN ULONG startOffset,
|
|
IN PVOID UserBuffer,
|
|
IN ULONG lengthToCopy,
|
|
IN BOOLEAN writeOperation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to read/write data to/from the memory card.
|
|
It breaks the request into pieces based on the size of our memory
|
|
window.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the object that represents the device
|
|
that I/O is to be done on.
|
|
|
|
Irp - a pointer to the I/O Request Packet for this request.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if the packet was successfully read or written; the
|
|
appropriate error is propogated otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PCHAR userBuffer = UserBuffer;
|
|
ULONG windowOffset;
|
|
ULONG singleCopyLength;
|
|
BOOLEAN bSuccess;
|
|
ULONGLONG CardBase;
|
|
|
|
if (writeOperation && (memcardExtension->PcmciaInterface.IsWriteProtected)(memcardExtension->UnderlyingPDO)) {
|
|
return STATUS_MEDIA_WRITE_PROTECTED;
|
|
}
|
|
|
|
MemCardDump(MEMCARDRW,("MemCard: DO %.8x %s offset %.8x, buffer %.8x, len %x\n",
|
|
memcardExtension->DeviceObject,
|
|
writeOperation?"WRITE":"READ",
|
|
startOffset, UserBuffer, lengthToCopy));
|
|
|
|
// pcmcia controller is 4k page granular
|
|
windowOffset = startOffset % 4096;
|
|
CardBase = startOffset - windowOffset;
|
|
|
|
while(lengthToCopy) {
|
|
|
|
bSuccess = (memcardExtension->PcmciaInterface.ModifyMemoryWindow) (
|
|
memcardExtension->UnderlyingPDO,
|
|
memcardExtension->HostBase,
|
|
CardBase,
|
|
TRUE,
|
|
memcardExtension->MemoryWindowSize,
|
|
0, 0, FALSE);
|
|
|
|
if (!bSuccess) {
|
|
status = STATUS_DEVICE_NOT_READY;
|
|
break;
|
|
}
|
|
|
|
singleCopyLength = (lengthToCopy <= (memcardExtension->MemoryWindowSize - windowOffset)) ?
|
|
lengthToCopy :
|
|
(memcardExtension->MemoryWindowSize - windowOffset);
|
|
|
|
|
|
MemCardDump(MEMCARDRW,("MemCard: COPY %.8x (devbase %.8x) %s buffer %.8x, len %x\n",
|
|
memcardExtension->MemoryWindowBase+windowOffset,
|
|
(ULONG)(CardBase+windowOffset),
|
|
(writeOperation ? "<=" : "=>"),
|
|
userBuffer,
|
|
singleCopyLength));
|
|
|
|
if (writeOperation) {
|
|
|
|
MemCardMtdWrite(memcardExtension,
|
|
userBuffer,
|
|
memcardExtension->MemoryWindowBase+windowOffset,
|
|
singleCopyLength);
|
|
|
|
} else {
|
|
|
|
MemCardMtdRead(memcardExtension,
|
|
userBuffer,
|
|
memcardExtension->MemoryWindowBase+windowOffset,
|
|
singleCopyLength);
|
|
|
|
}
|
|
|
|
lengthToCopy -= singleCopyLength;
|
|
userBuffer += singleCopyLength;
|
|
|
|
CardBase += memcardExtension->MemoryWindowSize;
|
|
windowOffset = 0;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|