Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

readwrite.c

Go to the documentation of this file.
00001 /*
00002  *  This program is free software; you can redistribute it and/or
00003  *  modify it under the terms of the GNU General Public License
00004  *  as published by the Free Software Foundation; either version
00005  *  2 of the License, or (at your option) any later version.
00006  *
00007  *  Copyright 2004 Spiro Trikaliotis
00008  *
00009  */
00010 
00020 #include <wdm.h>
00021 #include "cbm_driver.h"
00022 #include "iec.h"
00023 
00035 static NTSTATUS
00036 cbm_checkbuffer(IN PIO_STACK_LOCATION IrpSp)
00037 {
00038     NTSTATUS ntStatus;
00039 
00040     FUNC_ENTER();
00041 
00042     // The following code assumes that the read and write structure are exactly
00043     // the same (despite the name). This ASSERT() makes sure that we are informed
00044     // if this is not the case.
00045 
00046     DBG_ASSERT(&IrpSp->Parameters.Read.ByteOffset == &IrpSp->Parameters.Write.ByteOffset);
00047 
00048     if ((IrpSp->Parameters.Write.ByteOffset.HighPart != 0) ||
00049         (IrpSp->Parameters.Write.ByteOffset.LowPart != 0)) 
00050     {
00051         ntStatus = STATUS_INVALID_PARAMETER;
00052     } 
00053     else 
00054     {
00055         ntStatus = STATUS_SUCCESS;
00056     }
00057     FUNC_LEAVE_NTSTATUS(ntStatus);
00058 }
00059 
00060 
00084 NTSTATUS
00085 cbm_readwrite(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
00086 {
00087     PIO_STACK_LOCATION irpSp;
00088     PDEVICE_EXTENSION pdx;
00089     NTSTATUS ntStatus;
00090     ULONG readWriteBytesProcessed;
00091     ULONG readWriteLength;
00092     PUCHAR readWriteBuffer;
00093 
00094     FUNC_ENTER();
00095 
00096     // get the device extension
00097 
00098     pdx = Fdo->DeviceExtension;
00099 
00100     // get the current IRP stack location
00101 
00102     irpSp = IoGetCurrentIrpStackLocation(Irp);
00103 
00104     // Check if the buffer is valid
00105 
00106     ntStatus = cbm_checkbuffer(irpSp);
00107 
00108     DBG_IRPPATH_PROCESS("read/write");
00109 
00110     // Number of read (or written) bytes are 0 until now.
00111     // This is needed for finding out if we had success, or if something went wrong
00112 
00113     readWriteLength = 0;
00114 
00115 
00116     if (NT_SUCCESS(ntStatus))
00117     {
00118         // The following code assumes that the read and write structure are exactly
00119         // the same (despite the name). This ASSERT() makes sure that we are informed
00120         // if this is not the case.
00121 
00122         DBG_ASSERT(&irpSp->Parameters.Read.Length == &irpSp->Parameters.Write.Length);
00123 
00124         // Get the number of bytes to be read or written
00125 
00126         readWriteLength = irpSp->Parameters.Read.Length;
00127 
00128         // If we do performance measurements, log the appropriate event
00129 
00130         if (irpSp->MajorFunction == IRP_MJ_READ)
00131         {
00132             PERF_EVENT_READ_QUEUE(irpSp->Parameters.Read.Length);
00133         }
00134         else
00135         {
00136             PERF_EVENT_WRITE_QUEUE(irpSp->Parameters.Write.Length);
00137         }
00138 
00139         // If the read or write request has another length than 0,
00140         // then queue the IRP for being processed later.
00141 
00142         if (readWriteLength != 0)
00143         {
00144             // now, queue the IRP to be processed
00145 
00146             ntStatus = QueueStartPacket(&pdx->IrpQueue, Irp, FALSE, Fdo);
00147         }
00148     }
00149 
00150     if (!NT_SUCCESS(ntStatus) || readWriteLength == 0)
00151     {
00152         // there was an error, or a read/write request with length 0:
00153         // Thus, complete the request
00154 
00155         QueueCompleteIrp(NULL, Irp, ntStatus, 0);
00156     }
00157 
00158     FUNC_LEAVE_NTSTATUS(ntStatus);
00159 }
00160 
00178 NTSTATUS
00179 cbm_execute_readwrite(IN PDEVICE_EXTENSION Pdx, IN PIRP Irp)
00180 {
00181     PIO_STACK_LOCATION irpSp;
00182     NTSTATUS ntStatus;
00183     ULONG readWriteBytesProcessed;
00184     ULONG readWriteLength;
00185     PUCHAR readWriteBuffer;
00186 
00187     FUNC_ENTER();
00188 
00189     // get the current IRP stack location
00190 
00191     irpSp = IoGetCurrentIrpStackLocation(Irp);
00192 
00193     // The following code assumes that the read and write structure are exactly
00194     // the same (despite the name). This ASSERT() makes sure that we are informed
00195     // if this is not the case.
00196 
00197     DBG_ASSERT(&irpSp->Parameters.Read.Length == &irpSp->Parameters.Write.Length);
00198 
00199     // Find out how much bytes are to be read/written
00200 
00201     readWriteLength = irpSp->Parameters.Read.Length;
00202 
00203     // get the buffer where the bytes to be written are / where the bytes to be read
00204     // should be placed
00205 
00206     readWriteBuffer = Irp->AssociatedIrp.SystemBuffer;
00207 
00208     // If we do performance measurements, log the appropriate event
00209 
00210     if (irpSp->MajorFunction == IRP_MJ_READ)
00211     {
00212         PERF_EVENT_READ_EXECUTE(irpSp->Parameters.Read.Length);
00213     }
00214     else
00215     {
00216         PERF_EVENT_WRITE_EXECUTE(irpSp->Parameters.Write.Length);
00217     }
00218 
00219     DBG_IRPPATH_EXECUTE("read/write");
00220 
00221     // As this has been tested in cbm_readwrite() already, we should not get
00222     // any zero length here. Anyway, be sure that this does not happen with the
00223     // help of this ASSERT()
00224 
00225     DBG_ASSERT(readWriteLength != 0);
00226 
00227     if (readWriteLength != 0)
00228     {
00229         // Execute the appropriate function (read or write)
00230 
00231         switch (irpSp->MajorFunction)
00232         {
00233         case IRP_MJ_READ: 
00234             ntStatus = cbmiec_raw_read(Pdx, readWriteBuffer, readWriteLength,
00235                 &readWriteBytesProcessed);
00236             break;
00237 
00238         case IRP_MJ_WRITE:
00239             ntStatus = cbmiec_raw_write(Pdx, readWriteBuffer, readWriteLength,
00240                 &readWriteBytesProcessed);
00241             break;
00242 
00243         default:
00244             DBG_ERROR((DBG_PREFIX "UNKNOWN IRP_MJ code in cbm_readwrite!"));
00245             ntStatus = STATUS_INTERNAL_ERROR;
00246             readWriteBytesProcessed = 0;
00247             break;
00248         }
00249     }
00250 
00251     // It would not make sense to pend the IRP here. Thus, make sure this does
00252     // not happen at all
00253 
00254     DBG_ASSERT(ntStatus != STATUS_PENDING);
00255 
00256     // If the read or write has not been pended, we are ready the complete this
00257     // IRP
00259 
00260     if (ntStatus != STATUS_PENDING)
00261     {
00262         QueueCompleteIrp(&Pdx->IrpQueue, Irp, ntStatus, readWriteBytesProcessed);
00263     }
00264 
00265     FUNC_LEAVE_NTSTATUS(ntStatus);
00266 }

Generated on Sun Apr 30 18:45:58 2006 for opencbm by  doxygen 1.4.2