238 lines
6.3 KiB
C
238 lines
6.3 KiB
C
/*++
|
||
|
||
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;
|
||
}
|
||
|