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