windows-nt/Source/XPSP1/NT/base/busdrv/pccard/memcard/io.c
2020-09-26 16:20:57 +08:00

238 lines
6.3 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}