[LIBUSB][USBCCGP]
[reactos.git] / reactos / drivers / usb / usbehci / transfer.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbehci/transfer.c
5 * PURPOSE: Transfers to EHCI.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 */
9
10 /* All QueueHeads, Descriptors and pipe setup packets used by control transfers are allocated from common buffer.
11 The routines in physmem manages this buffer. Each allocation is aligned to 32bits, which is requirement of USB 2.0. */
12
13 #include "transfer.h"
14 #include <debug.h>
15
16
17 typedef struct _MAPREGISTERCALLBACKINFO
18 {
19 PVOID MapRegisterBase;
20 KEVENT Event;
21 }MAPREGISTERCALLBACKINFO, *PMAPREGISTERCALLBACKINFO;
22
23 /* Fills CtrlSetup parameter with values based on Urb */
24 VOID
25 BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup)
26 {
27 switch (Urb->UrbHeader.Function)
28 {
29 /* CLEAR FEATURE */
30 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
31 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
32 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
33 DPRINT1("Not implemented!\n");
34 break;
35
36 /* GET CONFIG */
37 case URB_FUNCTION_GET_CONFIGURATION:
38 CtrlSetup->bRequest = USB_REQUEST_GET_CONFIGURATION;
39 CtrlSetup->bmRequestType.B = 0x80;
40 CtrlSetup->wLength = 1;
41 break;
42
43 /* GET DESCRIPTOR */
44 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
45 CtrlSetup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
46 CtrlSetup->wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
47 CtrlSetup->wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
48 CtrlSetup->wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
49 CtrlSetup->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
50 CtrlSetup->bmRequestType.B = 0x80;
51 break;
52
53 /* GET INTERFACE */
54 case URB_FUNCTION_GET_INTERFACE:
55 CtrlSetup->bRequest = USB_REQUEST_GET_CONFIGURATION;
56 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
57 CtrlSetup->bmRequestType.B = 0x80;
58 CtrlSetup->wLength = 1;
59 break;
60
61 /* GET STATUS */
62 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
63 CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
64 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
65 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
66 CtrlSetup->bmRequestType.B = 0x80;
67 CtrlSetup->wLength = 2;
68 break;
69
70 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
71 CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
72 ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
73 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
74 CtrlSetup->bmRequestType.B = 0x81;
75 CtrlSetup->wLength = 2;
76 break;
77
78 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
79 CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
80 ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
81 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
82 CtrlSetup->bmRequestType.B = 0x82;
83 CtrlSetup->wLength = 2;
84 break;
85
86 /* SET ADDRESS */
87
88 /* SET CONFIG */
89 case URB_FUNCTION_SELECT_CONFIGURATION:
90 DPRINT1("Bulding data for Select Config\n");
91 CtrlSetup->bRequest = USB_REQUEST_SET_CONFIGURATION;
92 CtrlSetup->wValue.W = Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue;
93 CtrlSetup->wIndex.W = 0;
94 CtrlSetup->wLength = 0;
95 CtrlSetup->bmRequestType.B = 0x00;
96 break;
97
98 /* SET DESCRIPTOR */
99 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
100 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
101 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
102 DPRINT1("Not implemented\n");
103 break;
104
105 /* SET FEATURE */
106 case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
107 CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
108 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
109 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
110 CtrlSetup->bmRequestType.B = 0x80;
111 break;
112
113 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
114 CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
115 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
116 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
117 CtrlSetup->bmRequestType.B = 0x81;
118 break;
119
120 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
121 CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
122 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
123 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
124 CtrlSetup->bmRequestType.B = 0x82;
125 break;
126
127 /* SET INTERFACE*/
128 case URB_FUNCTION_SELECT_INTERFACE:
129 CtrlSetup->bRequest = USB_REQUEST_SET_INTERFACE;
130 CtrlSetup->wValue.W = Urb->UrbSelectInterface.Interface.AlternateSetting;
131 CtrlSetup->wIndex.W = Urb->UrbSelectInterface.Interface.InterfaceNumber;
132 CtrlSetup->wLength = 0;
133 CtrlSetup->bmRequestType.B = 0x01;
134 break;
135
136 /* SYNC FRAME */
137 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
138 DPRINT1("Not implemented\n");
139 break;
140 default:
141 DPRINT1("Unknown USB Request!\n");
142 break;
143 }
144 }
145
146 /* Build a Bulk Transfer with a max transfer of 3 descriptors which each has 5 pointers to one page of memory, paged align of course */
147 PQUEUE_HEAD
148 BuildBulkTransfer(PEHCI_HOST_CONTROLLER hcd,
149 ULONG DeviceAddress,
150 USBD_PIPE_HANDLE PipeHandle,
151 UCHAR PidDirection,
152 PMDL pMdl,
153 BOOLEAN FreeMdl)
154 {
155 PQUEUE_HEAD QueueHead;
156 PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
157 ULONG MdlByteCount = MmGetMdlByteCount(pMdl);
158 ULONG NeededDescriptorCount = 1;
159 int i;
160
161 QueueHead = CreateQueueHead(hcd);
162 QueueHead->EndPointCharacteristics.DeviceAddress = DeviceAddress;
163
164 if (PipeHandle)
165 {
166 QueueHead->EndPointCharacteristics.EndPointNumber = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
167 QueueHead->EndPointCharacteristics.MaximumPacketLength = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->wMaxPacketSize;
168 }
169
170 QueueHead->FreeMdl = FreeMdl;
171 QueueHead->Mdl = pMdl;
172
173 /* FIXME: This is totally screwed */
174 /* Calculate how many descriptors would be needed to transfer this buffer */
175 if (pMdl)
176 {
177 if (MdlByteCount < (PAGE_SIZE * 5))
178 NeededDescriptorCount = 1;
179 else if (MdlByteCount < (PAGE_SIZE * 10))
180 NeededDescriptorCount = 2;
181 else if (MdlByteCount < (PAGE_SIZE * 15))
182 NeededDescriptorCount = 3;
183 else
184 ASSERT(FALSE);
185 }
186 /* Limiter Transfers to PAGE_SIZE * 5 * 3, Three Descriptors */
187
188 QueueHead->NumberOfTransferDescriptors = NeededDescriptorCount;
189 for (i=0; i< NeededDescriptorCount;i++)
190 {
191 Descriptor[i] = CreateDescriptor(hcd,
192 PidDirection,
193 0);
194 Descriptor[i]->AlternateNextPointer = QueueHead->DeadDescriptor->PhysicalAddr;
195
196 if (i > 0)
197 {
198 Descriptor[i-1]->NextDescriptor = Descriptor[i];
199 Descriptor[i]->PreviousDescriptor = Descriptor[i-1];
200 Descriptor[i-1]->NextPointer = Descriptor[i]->PhysicalAddr;
201 }
202 }
203
204 Descriptor[0]->Token.Bits.InterruptOnComplete = TRUE;
205
206 /* Save the first descriptor in the QueueHead */
207 QueueHead->FirstTransferDescriptor = Descriptor[0];
208 QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
209
210 return QueueHead;
211 }
212
213
214 /* Builds a QueueHead with 2 to 3 descriptors needed for control transfer
215 2 descriptors used for and control request that doesnt return data, such as SetAddress */
216 PQUEUE_HEAD
217 BuildControlTransfer(PEHCI_HOST_CONTROLLER hcd,
218 ULONG DeviceAddress,
219 USBD_PIPE_HANDLE PipeHandle,
220 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
221 PMDL pMdl,
222 BOOLEAN FreeMdl)
223 {
224 PQUEUE_HEAD QueueHead;
225 PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
226 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA, CtrlPhysicalPA;
227
228 CtrlSetupVA = (PUSB_DEFAULT_PIPE_SETUP_PACKET)AllocateMemory(hcd,
229 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET),
230 (ULONG*)&CtrlPhysicalPA);
231
232 RtlCopyMemory(CtrlSetupVA, CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
233
234 QueueHead = CreateQueueHead(hcd);
235 QueueHead->EndPointCharacteristics.DeviceAddress = DeviceAddress;
236 if (PipeHandle)
237 QueueHead->EndPointCharacteristics.EndPointNumber = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
238
239 QueueHead->Token.Bits.DataToggle = TRUE;
240 QueueHead->FreeMdl = FreeMdl;
241 QueueHead->Mdl = pMdl;
242
243 Descriptor[0] = CreateDescriptor(hcd,
244 PID_CODE_SETUP_TOKEN,
245 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
246
247 Descriptor[0]->Token.Bits.DataToggle = FALSE;
248 /* Save the first descriptor */
249 QueueHead->FirstTransferDescriptor = Descriptor[0];
250
251 if (pMdl)
252 {
253 Descriptor[1] = CreateDescriptor(hcd,
254 PID_CODE_IN_TOKEN,
255 MmGetMdlByteCount(pMdl));
256
257 Descriptor[2] = CreateDescriptor(hcd,
258 PID_CODE_OUT_TOKEN,
259 0);
260 }
261 else
262 {
263 Descriptor[2] = CreateDescriptor(hcd,
264 PID_CODE_IN_TOKEN,
265 0);
266 }
267
268 Descriptor[2]->Token.Bits.InterruptOnComplete = TRUE;
269
270 /* Link the descriptors */
271 if (pMdl)
272 {
273 Descriptor[0]->NextDescriptor = Descriptor[1];
274 Descriptor[1]->NextDescriptor = Descriptor[2];
275 Descriptor[1]->PreviousDescriptor = Descriptor[0];
276 Descriptor[2]->PreviousDescriptor = Descriptor[1];
277 }
278 else
279 {
280 Descriptor[0]->NextDescriptor = Descriptor[2];
281 Descriptor[2]->PreviousDescriptor = Descriptor[0];
282 }
283
284 /* Assign the descriptor buffers */
285 Descriptor[0]->BufferPointer[0] = (ULONG)CtrlPhysicalPA;
286 Descriptor[0]->BufferPointerVA[0] = (ULONG)CtrlSetupVA;
287
288 if (pMdl)
289 {
290 Descriptor[0]->NextPointer = Descriptor[1]->PhysicalAddr;
291 Descriptor[0]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
292 Descriptor[1]->NextPointer = Descriptor[2]->PhysicalAddr;
293 Descriptor[1]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
294 }
295 else
296 {
297 Descriptor[0]->NextPointer = Descriptor[2]->PhysicalAddr;
298 Descriptor[0]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
299 }
300
301 QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
302 if (pMdl)
303 QueueHead->NumberOfTransferDescriptors = 3;
304 else
305 QueueHead->NumberOfTransferDescriptors = 2;
306 return QueueHead;
307 }
308
309
310 IO_ALLOCATION_ACTION NTAPI MapRegisterCallBack(PDEVICE_OBJECT DeviceObject,
311 PIRP Irp,
312 PVOID MapRegisterBase,
313 PVOID Context)
314 {
315 PMAPREGISTERCALLBACKINFO CallBackInfo = (PMAPREGISTERCALLBACKINFO)Context;
316
317 CallBackInfo->MapRegisterBase = MapRegisterBase;
318
319 KeSetEvent(&CallBackInfo->Event, IO_NO_INCREMENT, FALSE);
320 return KeepObject;
321 }
322
323
324 NTSTATUS
325 ExecuteTransfer(PDEVICE_OBJECT DeviceObject,
326 PUSB_DEVICE UsbDevice,
327 USBD_PIPE_HANDLE PipeHandle,
328 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
329 ULONG TransferFlags,
330 PVOID TransferBufferOrMdl,
331 ULONG TransferBufferLength,
332 PIRP IrpToComplete)
333 {
334 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
335 PEHCI_HOST_CONTROLLER hcd;
336 PQUEUE_HEAD QueueHead;
337 PKEVENT CompleteEvent = NULL;
338 PMAPREGISTERCALLBACKINFO CallBackInfo;
339 LARGE_INTEGER TimeOut;
340 PMDL pMdl = NULL;
341 BOOLEAN FreeMdl = FALSE;
342 PVOID VirtualAddressOfMdl;
343 ULONG NumberOfMapRegisters;
344 KIRQL OldIrql;
345 NTSTATUS Status = STATUS_SUCCESS;
346 UCHAR EndPointType, PidDirection;
347 BOOLEAN IsReadOp = TRUE;
348 ULONG TransferBtyesOffset, CurrentTransferBytes;
349 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
350 PHYSICAL_ADDRESS PhysicalAddr;
351 int i,j;
352
353 hcd = &((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->hcd;
354
355 /* If no Irp then we will need to wait on completion */
356 if (IrpToComplete == NULL)
357 {
358 CompleteEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
359 KeInitializeEvent(CompleteEvent, NotificationEvent, FALSE);
360 }
361
362 CallBackInfo = ExAllocatePool(NonPagedPool, sizeof(MAPREGISTERCALLBACKINFO));
363 CallBackInfo->MapRegisterBase = 0;
364
365 KeInitializeEvent(&CallBackInfo->Event, NotificationEvent, FALSE);
366
367 /* Determine EndPoint Type */
368 if (!PipeHandle)
369 {
370 EndPointType = USB_ENDPOINT_TYPE_CONTROL;
371 }
372 else
373 {
374 EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)PipeHandle;
375 EndPointType = EndPointDesc->bmAttributes & 0x0F;
376 }
377
378 if (TransferBufferOrMdl)
379 {
380 /* Create MDL for Buffer */
381 if (TransferBufferLength)
382 {
383 pMdl = IoAllocateMdl(TransferBufferOrMdl,
384 TransferBufferLength,
385 FALSE,
386 FALSE,
387 NULL);
388 /* UEHCI created the MDL so it needs to free it */
389 FreeMdl = TRUE;
390 }
391 else
392 {
393 pMdl = TransferBufferOrMdl;
394 }
395 MmBuildMdlForNonPagedPool(pMdl);
396 }
397
398 switch (EndPointType)
399 {
400 case USB_ENDPOINT_TYPE_CONTROL:
401 {
402 QueueHead = BuildControlTransfer(hcd,
403 UsbDevice->Address,
404 PipeHandle,
405 CtrlSetup,
406 pMdl,
407 FreeMdl);
408 IsReadOp = TRUE;
409 break;
410 }
411 case USB_ENDPOINT_TYPE_BULK:
412 {
413 PidDirection = EndPointDesc->bEndpointAddress >> 7;
414 if (PidDirection)
415 IsReadOp = FALSE;
416
417 QueueHead = BuildBulkTransfer(hcd,
418 UsbDevice->Address,
419 PipeHandle,
420 PidDirection,
421 pMdl,
422 FreeMdl);
423
424 break;
425 }
426 case USB_ENDPOINT_TYPE_INTERRUPT:
427 {
428 DPRINT1("Interrupt Endpoints not implemented yet!\n");
429 break;
430 }
431 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
432 {
433 DPRINT1("Isochronous Endpoints not implemented yet!\n");
434 break;
435 }
436 default:
437 {
438 DPRINT1("Unknown Endpoint type!!\n");
439 break;
440 }
441 }
442
443 QueueHead->IrpToComplete = IrpToComplete;
444 QueueHead->Event = CompleteEvent;
445
446 if (!pMdl)
447 {
448 ASSERT(QueueHead->NumberOfTransferDescriptors == 2);
449 LinkQueueHead(hcd, QueueHead);
450 if (IrpToComplete == NULL)
451 {
452 DPRINT1("Waiting For Completion %x!\n", CompleteEvent);
453 TimeOut.QuadPart = -10000000;
454 KeWaitForSingleObject(CompleteEvent, Suspended, KernelMode, FALSE, NULL);//&TimeOut);
455 DPRINT1("Request Completed\n");
456 ExFreePool(CompleteEvent);
457 }
458 return Status;
459 }
460 //ASSERT(FALSE);
461
462 KeFlushIoBuffers(pMdl, IsReadOp, TRUE);
463 NumberOfMapRegisters = 15;
464
465 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
466 hcd->pDmaAdapter->DmaOperations->AllocateAdapterChannel(hcd->pDmaAdapter,
467 ((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ControllerFdo,
468 NumberOfMapRegisters,
469 MapRegisterCallBack,
470 (PVOID)CallBackInfo);
471 KeLowerIrql(OldIrql);
472 DPRINT1("Waiting for AdapterChannel\n");
473 KeWaitForSingleObject(&CallBackInfo->Event, Suspended, KernelMode, FALSE, NULL);
474 DPRINT1("Dma controller ready!\n");
475 DPRINT1("Getting address for MDL %x\n", pMdl);
476
477 VirtualAddressOfMdl = MmGetMdlVirtualAddress(pMdl);
478
479 TransferBtyesOffset = 0;
480 while (TransferBtyesOffset < MmGetMdlByteCount(pMdl))
481 {
482 CurrentTransferBytes = MmGetMdlByteCount(pMdl);
483 Descriptor = QueueHead->FirstTransferDescriptor;
484 if ((Descriptor->Token.Bits.PIDCode == PID_CODE_SETUP_TOKEN) && (QueueHead->NumberOfTransferDescriptors == 3))
485 {
486 DPRINT1("QueueHead is for endpoint 0\n");
487 DPRINT1("MapRegisterBase %x\n", CallBackInfo->MapRegisterBase);
488 DPRINT1("VirtualAddressOfMdl %x, TransferBytesOffset %x\n", VirtualAddressOfMdl, TransferBtyesOffset);
489 Descriptor = Descriptor->NextDescriptor;
490 PhysicalAddr = hcd->pDmaAdapter->DmaOperations->MapTransfer(hcd->pDmaAdapter,
491 pMdl,
492 CallBackInfo->MapRegisterBase,
493 (PVOID)((ULONG_PTR)VirtualAddressOfMdl + TransferBtyesOffset),
494 &CurrentTransferBytes,
495 !IsReadOp);
496 DPRINT1("BufferPointer[0] = %x\n", PhysicalAddr.LowPart);
497 Descriptor->BufferPointer[0] = PhysicalAddr.LowPart;
498 DPRINT1("CurrentTransferBytes %x\n", CurrentTransferBytes);
499 TransferBtyesOffset += CurrentTransferBytes;
500 LinkQueueHead(hcd, QueueHead);
501 break;
502 }
503 DPRINT1("PID_CODE_SETUP_TOKEN %x, PidDirection %x, NumDesc %x\n", PID_CODE_SETUP_TOKEN, PidDirection, QueueHead->NumberOfTransferDescriptors);
504 for (i=0; i<QueueHead->NumberOfTransferDescriptors; i++)
505 {
506 if (Descriptor->Token.Bits.PIDCode != PID_CODE_SETUP_TOKEN)
507 {
508 for (j=0; j<5; j++)
509 {
510 PhysicalAddr = hcd->pDmaAdapter->DmaOperations->MapTransfer(hcd->pDmaAdapter,
511 pMdl,
512 CallBackInfo->MapRegisterBase,
513 (PVOID)((ULONG_PTR)VirtualAddressOfMdl + TransferBtyesOffset),
514 &CurrentTransferBytes,
515 !IsReadOp);
516 DPRINT1("BufferPointer[%d] = %x\n", j, PhysicalAddr.LowPart);
517 Descriptor->BufferPointer[j] = PhysicalAddr.LowPart;
518 TransferBtyesOffset += CurrentTransferBytes;
519 if (TransferBtyesOffset >= MmGetMdlByteCount(pMdl))
520 break;
521 }
522 }
523 Descriptor = Descriptor->NextDescriptor;
524 }
525 LinkQueueHead(hcd, QueueHead);
526 break;
527 }
528
529 if (TransferBtyesOffset < MmGetMdlByteCount(pMdl)) ASSERT(FALSE);
530 if (IrpToComplete == NULL)
531 {
532 DPRINT1("Waiting For Completion %x!\n", CompleteEvent);
533 TimeOut.QuadPart = -10000000;
534 KeWaitForSingleObject(CompleteEvent, Suspended, KernelMode, FALSE, NULL);//&TimeOut);
535 DPRINT1("Request Completed\n");
536 ExFreePool(CompleteEvent);
537 }
538
539 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
540 hcd->pDmaAdapter->DmaOperations->FreeMapRegisters(hcd->pDmaAdapter,
541 CallBackInfo->MapRegisterBase,
542 NumberOfMapRegisters);
543
544 hcd->pDmaAdapter->DmaOperations->FreeAdapterChannel (hcd->pDmaAdapter);
545 KeLowerIrql(OldIrql);
546 return Status;
547 }