OpenCBM
readwrite.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2004 Spiro Trikaliotis
8  *
9  */
10 
19 #include <wdm.h>
20 #include "cbm_driver.h"
21 #include "iec.h"
22 
34 static NTSTATUS
35 cbm_checkbuffer(IN PIO_STACK_LOCATION IrpSp)
36 {
37  NTSTATUS ntStatus;
38 
39  FUNC_ENTER();
40 
41  // The following code assumes that the read and write structure are exactly
42  // the same (despite the name). This ASSERT() makes sure that we are informed
43  // if this is not the case.
44 
45  DBG_ASSERT(&IrpSp->Parameters.Read.ByteOffset == &IrpSp->Parameters.Write.ByteOffset);
46 
47  if ((IrpSp->Parameters.Write.ByteOffset.HighPart != 0) ||
48  (IrpSp->Parameters.Write.ByteOffset.LowPart != 0))
49  {
50  ntStatus = STATUS_INVALID_PARAMETER;
51  }
52  else
53  {
54  ntStatus = STATUS_SUCCESS;
55  }
56  FUNC_LEAVE_NTSTATUS(ntStatus);
57 }
58 
59 
83 NTSTATUS
84 cbm_readwrite(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
85 {
86  PIO_STACK_LOCATION irpSp;
87  PDEVICE_EXTENSION pdx;
88  NTSTATUS ntStatus;
89  ULONG readWriteBytesProcessed;
90  ULONG readWriteLength;
91  PUCHAR readWriteBuffer;
92 
93  FUNC_ENTER();
94 
95  // get the device extension
96 
97  pdx = Fdo->DeviceExtension;
98 
99  // get the current IRP stack location
100 
101  irpSp = IoGetCurrentIrpStackLocation(Irp);
102 
103  // Check if the buffer is valid
104 
105  ntStatus = cbm_checkbuffer(irpSp);
106 
107  DBG_IRPPATH_PROCESS("read/write");
108 
109  // Number of read (or written) bytes are 0 until now.
110  // This is needed for finding out if we had success, or if something went wrong
111 
112  readWriteLength = 0;
113 
114 
115  if (NT_SUCCESS(ntStatus))
116  {
117  // The following code assumes that the read and write structure are exactly
118  // the same (despite the name). This ASSERT() makes sure that we are informed
119  // if this is not the case.
120 
121  DBG_ASSERT(&irpSp->Parameters.Read.Length == &irpSp->Parameters.Write.Length);
122 
123  // Get the number of bytes to be read or written
124 
125  readWriteLength = irpSp->Parameters.Read.Length;
126 
127  // If we do performance measurements, log the appropriate event
128 
129  if (irpSp->MajorFunction == IRP_MJ_READ)
130  {
131  PERF_EVENT_READ_QUEUE(irpSp->Parameters.Read.Length);
132  }
133  else
134  {
135  PERF_EVENT_WRITE_QUEUE(irpSp->Parameters.Write.Length);
136  }
137 
138  // If the read or write request has another length than 0,
139  // then queue the IRP for being processed later.
140 
141  if (readWriteLength != 0)
142  {
143  // now, queue the IRP to be processed
144 
145  ntStatus = QueueStartPacket(&pdx->IrpQueue, Irp, FALSE, Fdo);
146  }
147  }
148 
149  if (!NT_SUCCESS(ntStatus) || readWriteLength == 0)
150  {
151  // there was an error, or a read/write request with length 0:
152  // Thus, complete the request
153 
154  QueueCompleteIrp(NULL, Irp, ntStatus, 0);
155  }
156 
157  FUNC_LEAVE_NTSTATUS(ntStatus);
158 }
159 
177 NTSTATUS
178 cbm_execute_readwrite(IN PDEVICE_EXTENSION Pdx, IN PIRP Irp)
179 {
180  PIO_STACK_LOCATION irpSp;
181  NTSTATUS ntStatus;
182  ULONG readWriteBytesProcessed;
183  ULONG readWriteLength;
184  PUCHAR readWriteBuffer;
185 
186  FUNC_ENTER();
187 
188  // get the current IRP stack location
189 
190  irpSp = IoGetCurrentIrpStackLocation(Irp);
191 
192  // The following code assumes that the read and write structure are exactly
193  // the same (despite the name). This ASSERT() makes sure that we are informed
194  // if this is not the case.
195 
196  DBG_ASSERT(&irpSp->Parameters.Read.Length == &irpSp->Parameters.Write.Length);
197 
198  // Find out how much bytes are to be read/written
199 
200  readWriteLength = irpSp->Parameters.Read.Length;
201 
202  // get the buffer where the bytes to be written are / where the bytes to be read
203  // should be placed
204 
205  readWriteBuffer = Irp->AssociatedIrp.SystemBuffer;
206 
207  // If we do performance measurements, log the appropriate event
208 
209  if (irpSp->MajorFunction == IRP_MJ_READ)
210  {
211  PERF_EVENT_READ_EXECUTE(irpSp->Parameters.Read.Length);
212  }
213  else
214  {
215  PERF_EVENT_WRITE_EXECUTE(irpSp->Parameters.Write.Length);
216  }
217 
218  DBG_IRPPATH_EXECUTE("read/write");
219 
220  // As this has been tested in cbm_readwrite() already, we should not get
221  // any zero length here. Anyway, be sure that this does not happen with the
222  // help of this ASSERT()
223 
224  DBG_ASSERT(readWriteLength != 0);
225 
226  if (readWriteLength != 0)
227  {
228  // Execute the appropriate function (read or write)
229 
230  switch (irpSp->MajorFunction)
231  {
232  case IRP_MJ_READ:
233  ntStatus = cbmiec_raw_read(Pdx, readWriteBuffer, readWriteLength,
234  &readWriteBytesProcessed);
235  break;
236 
237  case IRP_MJ_WRITE:
238  ntStatus = cbmiec_raw_write(Pdx, readWriteBuffer, readWriteLength,
239  &readWriteBytesProcessed);
240  break;
241 
242  default:
243  DBG_ERROR((DBG_PREFIX "UNKNOWN IRP_MJ code in cbm_readwrite!"));
244  ntStatus = STATUS_INTERNAL_ERROR;
245  readWriteBytesProcessed = 0;
246  break;
247  }
248  }
249 
250  // It would not make sense to pend the IRP here. Thus, make sure this does
251  // not happen at all
252 
253  DBG_ASSERT(ntStatus != STATUS_PENDING);
254 
255  // If the read or write has not been pended, we are ready the complete this
256  // IRP
258 
259  if (ntStatus != STATUS_PENDING)
260  {
261  QueueCompleteIrp(&Pdx->IrpQueue, Irp, ntStatus, readWriteBytesProcessed);
262  }
263 
264  FUNC_LEAVE_NTSTATUS(ntStatus);
265 }
NTSTATUS cbm_readwrite(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
Services reads from or writes to the driver.
Definition: readwrite.c:84
#define DBG_IRPPATH_PROCESS(_Where_)
Debug IRPPATH: Processing of the IRP.
Definition: debug.h:571
Definitions for the libiec library.
NTSTATUS QueueStartPacket(PQUEUE Queue, PIRP Irp, BOOLEAN FastStart, PDEVICE_OBJECT Fdo)
Insert an IRP into a QUEUE object.
Definition: queue.c:467
#define PERF_EVENT_WRITE_QUEUE(_x_)
Definition: cbm_driver.h:63
NTSTATUS cbmiec_raw_write(IN PDEVICE_EXTENSION Pdx, IN const PUCHAR Buffer, IN ULONG BufferLength, OUT ULONG *Written)
Write some bytes to the IEC bus.
Definition: rawwrite.c:47
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
#define DBG_ERROR(_xxx)
Definition: debug.h:397
NTSTATUS cbmiec_raw_read(IN PDEVICE_EXTENSION Pdx, OUT PUCHAR Buffer, IN ULONG BufferLength, OUT ULONG *Read)
Read some bytes from the IEC bus.
Definition: rawread.c:48
#define PERF_EVENT_WRITE_EXECUTE(_x_)
Definition: cbm_driver.h:65
NTSTATUS cbm_execute_readwrite(IN PDEVICE_EXTENSION Pdx, IN PIRP Irp)
Executes reads from or writes to the driver.
Definition: readwrite.c:178
#define FUNC_ENTER()
Definition: debug.h:347
Definitions for the opencbm driver.
#define DBG_IRPPATH_EXECUTE(_Where_)
Debug IRPPATH: Executing of the IRP.
Definition: debug.h:580
#define DBG_PREFIX
Definition: debug.h:320
#define PERF_EVENT_READ_EXECUTE(_x_)
Definition: cbm_driver.h:61
#define PERF_EVENT_READ_QUEUE(_x_)
Definition: cbm_driver.h:59
NTSTATUS QueueCompleteIrp(PQUEUE Queue, PIRP Irp, NTSTATUS StatusCode, ULONG_PTR Information)
Complete an IRP which is on a QUEUE.
Definition: queue.c:756