Bring back ext2 code from branch
[reactos.git] / reactos / drivers / filesystems / ext2 / src / DiskIO.c
1 /*************************************************************************
2 *
3 * File: DiskIO.c
4 *
5 * Module: Ext2 File System Driver (Kernel mode execution only)
6 *
7 * Description:
8 * Should contain code to handle Disk IO.
9 *
10 *
11 * Author: Manoj Paul Joseph
12 *
13 *
14 *************************************************************************/
15
16 #include "ext2fsd.h"
17
18 #define EXT2_BUG_CHECK_ID EXT2_FILE_DISK_IO
19
20 #define DEBUG_LEVEL ( DEBUG_TRACE_DISKIO )
21
22
23 /*************************************************************************
24 *
25 * Function: Ext2ReadLogicalBlocks()
26 *
27 * Description:
28 * The higherlevel functions will use this to read in logical blocks
29 * This function deals with the logical to physical block translation
30 *
31 * LogicalBlock - This is a 1 based index.
32 * That is, the first block is Block 1
33 *
34 * Expected Interrupt Level (for execution) :
35 *
36 * IRQL_PASSIVE_LEVEL
37 *
38 * Return Value: The Status of the Read IO
39 *
40 *************************************************************************/
41 NTSTATUS Ext2ReadLogicalBlocks (
42 PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
43 VOID *Buffer, // The Buffer that takes the data read in
44 LARGE_INTEGER StartLogicalBlock, // The logical block from which reading is to start
45 unsigned int NoOfLogicalBlocks // The no. of logical blocks to be read
46 )
47 {
48 // The Status to be returned...
49 NTSTATUS Status = STATUS_SUCCESS;
50
51 // The Device Object representing the mounted volume
52 PDEVICE_OBJECT PtrVolumeDeviceObject = NULL;
53
54 // Volume Control Block
55 PtrExt2VCB PtrVCB = NULL;
56
57 // Logical Block Size
58 ULONG LogicalBlockSize;
59
60 // Physical Block Size
61 ULONG PhysicalBlockSize;
62
63 // The starting Physical Block No...
64 LARGE_INTEGER StartPhysicalBlock;
65
66 unsigned int NoOfPhysicalBlocks;
67
68
69
70 // Done with declerations...
71 // Now for some code ;)
72
73 // Getting the Logical and Physical Sector sizes
74 PtrVolumeDeviceObject = PtrTargetDeviceObject->Vpb->DeviceObject;
75 ASSERT( PtrVolumeDeviceObject );
76 PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension);
77 ASSERT(PtrVCB);
78 ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
79
80 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
81 PhysicalBlockSize = PtrTargetDeviceObject->SectorSize;
82
83 NoOfPhysicalBlocks = NoOfLogicalBlocks * LogicalBlockSize / PhysicalBlockSize;
84
85 StartPhysicalBlock.QuadPart = ( StartLogicalBlock.QuadPart ) *
86 ( LogicalBlockSize / PhysicalBlockSize );
87
88 Status = Ext2ReadPhysicalBlocks( PtrTargetDeviceObject,
89 Buffer, StartPhysicalBlock, NoOfPhysicalBlocks );
90
91 return Status;
92 }
93
94 /*************************************************************************
95 *
96 * Function: Ext2ReadPhysicalBlocks()
97 *
98 * Description:
99 * The higherlevel functions will use this to read in physical blocks
100 *
101 * PhysicalBlock - This is a 0 based number.
102 * That is, the first block is Block 0
103 *
104 * Expected Interrupt Level (for execution) :
105 *
106 * IRQL_PASSIVE_LEVEL
107 *
108 * Return Value: The Status of the Read IO
109 *
110 *************************************************************************/
111 NTSTATUS Ext2ReadPhysicalBlocks (
112 PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
113 VOID *Buffer, // The Buffer that takes the data read in
114 LARGE_INTEGER StartPhysicalBlock, // The block from which reading is to start
115 unsigned int NoOfBlocks // The no. of blocks to be read
116 )
117 {
118 // The Status to be returned...
119 NTSTATUS Status = STATUS_SUCCESS;
120
121 // Physical Block Size
122 ULONG PhysicalBlockSize;
123
124 // No of bytes to read
125 ULONG NumberOfBytesToRead;
126
127 // Synchronisation Event
128 KEVENT Event;
129
130 // IRP
131 PIRP Irp;
132
133 // Status Block
134 IO_STATUS_BLOCK Iosb;
135
136 // Byte Offset
137 LARGE_INTEGER ByteOffset;
138
139 // Done with declerations...
140 // Now for some code ;)
141
142 // Getting the Physical Sector size
143 PhysicalBlockSize = PtrTargetDeviceObject->SectorSize;
144
145 NumberOfBytesToRead = PhysicalBlockSize * NoOfBlocks;
146
147 ByteOffset.QuadPart = StartPhysicalBlock.QuadPart * PhysicalBlockSize;
148
149 try
150 {
151 //
152 // Initialize the event we're going to use
153 //
154 KeInitializeEvent( &Event, NotificationEvent, FALSE );
155
156 //
157 // Build the irp for the operation and also set the overrride flag
158 //
159 Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
160 PtrTargetDeviceObject,
161 Buffer,
162 NumberOfBytesToRead,
163 &ByteOffset ,
164 &Event,
165 &Iosb );
166
167 if ( Irp == NULL )
168 {
169 DebugTrace(DEBUG_TRACE_MISC, " !!!! Unable to create an IRP", 0 );
170 Status = STATUS_INSUFFICIENT_RESOURCES;
171 try_return( Status );
172 }
173
174 //
175 // Call the device to do the read and wait for it to finish.
176 //
177 Status = IoCallDriver( PtrTargetDeviceObject, Irp );
178
179 //
180 // Check if it is done already!!!!
181 //
182 if (Status == STATUS_PENDING)
183 {
184 //
185 // Read not done yet...
186 // Wait till it is...
187 //
188 (VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
189 Status = Iosb.Status;
190 }
191
192 try_exit: NOTHING;
193 }
194 finally
195 {
196 if (!NT_SUCCESS(Status))
197 {
198 if( Status == STATUS_VERIFY_REQUIRED )
199 {
200 DebugTrace(DEBUG_TRACE_MISC, " !!!! Verify Required! Failed to read disk",0 );
201 }
202 else if (Status == STATUS_INVALID_PARAMETER)
203 {
204 DebugTrace(DEBUG_TRACE_MISC, " !!!! Invalid Parameter! Failed to read disk",0 );
205 }
206 else
207 {
208 DebugTrace(DEBUG_TRACE_MISC, " !!!! Failed to read disk! Status returned = %d", Status );
209 }
210 }
211 }
212 return Status;
213 }
214
215