[USBOHCI]
[reactos.git] / drivers / usb / usbohci / usb_request.cpp
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/usbohci/usb_request.cpp
5 * PURPOSE: USB OHCI device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #define INITGUID
12
13 #include "usbohci.h"
14 #include "hardware.h"
15
16 class CUSBRequest : public IUSBRequest
17 {
18 public:
19 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
20
21 STDMETHODIMP_(ULONG) AddRef()
22 {
23 InterlockedIncrement(&m_Ref);
24 return m_Ref;
25 }
26 STDMETHODIMP_(ULONG) Release()
27 {
28 InterlockedDecrement(&m_Ref);
29
30 if (!m_Ref)
31 {
32 delete this;
33 return 0;
34 }
35 return m_Ref;
36 }
37
38 // IUSBRequest interface functions
39 virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
40 virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp);
41 virtual BOOLEAN IsRequestComplete();
42 virtual ULONG GetTransferType();
43 virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutEndpointDescriptor);
44 virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
45 virtual BOOLEAN IsRequestInitialized();
46 virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
47 virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
48 virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
49 virtual UCHAR GetInterval();
50
51
52 // local functions
53 ULONG InternalGetTransferType();
54 UCHAR InternalGetPidDirection();
55 UCHAR GetDeviceAddress();
56 NTSTATUS BuildSetupPacket();
57 NTSTATUS BuildSetupPacketFromURB();
58 NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
59 NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
60 NTSTATUS BuildIsochronousEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
61 NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG BufferSize);
62 VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
63 NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
64 NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount);
65 UCHAR GetEndpointAddress();
66 USHORT GetMaxPacketSize();
67
68 // constructor / destructor
69 CUSBRequest(IUnknown *OuterUnknown){}
70 virtual ~CUSBRequest(){}
71
72 protected:
73 LONG m_Ref;
74
75 //
76 // memory manager for allocating setup packet / queue head / transfer descriptors
77 //
78 PDMAMEMORYMANAGER m_DmaManager;
79
80 //
81 // caller provided irp packet containing URB request
82 //
83 PIRP m_Irp;
84
85 //
86 // transfer buffer length
87 //
88 ULONG m_TransferBufferLength;
89
90 //
91 // current transfer length
92 //
93 ULONG m_TransferBufferLengthCompleted;
94
95 //
96 // Total Transfer Length
97 //
98 ULONG m_TotalBytesTransferred;
99
100 //
101 // transfer buffer MDL
102 //
103 PMDL m_TransferBufferMDL;
104
105 //
106 // caller provided setup packet
107 //
108 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket;
109
110 //
111 // completion event for callers who initialized request with setup packet
112 //
113 PKEVENT m_CompletionEvent;
114
115 //
116 // device address for callers who initialized it with device address
117 //
118 UCHAR m_DeviceAddress;
119
120 //
121 // store end point address
122 //
123 PUSB_ENDPOINT_DESCRIPTOR m_EndpointDescriptor;
124
125 //
126 // allocated setup packet from the DMA pool
127 //
128 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
129 PHYSICAL_ADDRESS m_DescriptorSetupPacket;
130
131 //
132 // stores the result of the operation
133 //
134 NTSTATUS m_NtStatusCode;
135 ULONG m_UrbStatusCode;
136
137 };
138
139 //----------------------------------------------------------------------------------------
140 NTSTATUS
141 STDMETHODCALLTYPE
142 CUSBRequest::QueryInterface(
143 IN REFIID refiid,
144 OUT PVOID* Output)
145 {
146 return STATUS_UNSUCCESSFUL;
147 }
148
149 //----------------------------------------------------------------------------------------
150 NTSTATUS
151 CUSBRequest::InitializeWithSetupPacket(
152 IN PDMAMEMORYMANAGER DmaManager,
153 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
154 IN UCHAR DeviceAddress,
155 IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
156 IN OUT ULONG TransferBufferLength,
157 IN OUT PMDL TransferBuffer)
158 {
159 //
160 // sanity checks
161 //
162 PC_ASSERT(DmaManager);
163 PC_ASSERT(SetupPacket);
164
165 //
166 // initialize packet
167 //
168 m_DmaManager = DmaManager;
169 m_SetupPacket = SetupPacket;
170 m_TransferBufferLength = TransferBufferLength;
171 m_TransferBufferMDL = TransferBuffer;
172 m_DeviceAddress = DeviceAddress;
173 m_EndpointDescriptor = EndpointDescriptor;
174 m_TotalBytesTransferred = 0;
175
176 //
177 // Set Length Completed to 0
178 //
179 m_TransferBufferLengthCompleted = 0;
180
181 //
182 // allocate completion event
183 //
184 m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_USBOHCI);
185 if (!m_CompletionEvent)
186 {
187 //
188 // failed to allocate completion event
189 //
190 return STATUS_INSUFFICIENT_RESOURCES;
191 }
192
193 //
194 // initialize completion event
195 //
196 KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE);
197
198 //
199 // done
200 //
201 return STATUS_SUCCESS;
202 }
203 //----------------------------------------------------------------------------------------
204 NTSTATUS
205 CUSBRequest::InitializeWithIrp(
206 IN PDMAMEMORYMANAGER DmaManager,
207 IN OUT PIRP Irp)
208 {
209 PIO_STACK_LOCATION IoStack;
210 PURB Urb;
211
212 //
213 // sanity checks
214 //
215 PC_ASSERT(DmaManager);
216 PC_ASSERT(Irp);
217
218 m_DmaManager = DmaManager;
219 m_TotalBytesTransferred = 0;
220
221 //
222 // get current irp stack location
223 //
224 IoStack = IoGetCurrentIrpStackLocation(Irp);
225
226 //
227 // sanity check
228 //
229 PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
230 PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
231 PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
232
233 //
234 // get urb
235 //
236 Urb = (PURB)IoStack->Parameters.Others.Argument1;
237
238 //
239 // store irp
240 //
241 m_Irp = Irp;
242
243 //
244 // check function type
245 //
246 switch (Urb->UrbHeader.Function)
247 {
248 case URB_FUNCTION_ISOCH_TRANSFER:
249 {
250 //
251 // there must be at least one packet
252 //
253 ASSERT(Urb->UrbIsochronousTransfer.NumberOfPackets);
254
255 //
256 // is there data to be transferred
257 //
258 if (Urb->UrbIsochronousTransfer.TransferBufferLength)
259 {
260 //
261 // Check if there is a MDL
262 //
263 if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
264 {
265 //
266 // sanity check
267 //
268 PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
269
270 //
271 // Create one using TransferBuffer
272 //
273 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
274 m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
275 Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
276 FALSE,
277 FALSE,
278 NULL);
279
280 if (!m_TransferBufferMDL)
281 {
282 //
283 // failed to allocate mdl
284 //
285 return STATUS_INSUFFICIENT_RESOURCES;
286 }
287
288 //
289 // build mdl for non paged pool
290 // FIXME: Does hub driver already do this when passing MDL?
291 //
292 MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
293 }
294 else
295 {
296 //
297 // use provided mdl
298 //
299 m_TransferBufferMDL = Urb->UrbIsochronousTransfer.TransferBufferMDL;
300 }
301 }
302
303 //
304 // save buffer length
305 //
306 m_TransferBufferLength = Urb->UrbIsochronousTransfer.TransferBufferLength;
307
308 //
309 // Set Length Completed to 0
310 //
311 m_TransferBufferLengthCompleted = 0;
312
313 //
314 // get endpoint descriptor
315 //
316 m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle;
317
318 //
319 // completed initialization
320 //
321 break;
322 }
323 //
324 // luckily those request have the same structure layout
325 //
326 case URB_FUNCTION_CLASS_INTERFACE:
327 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
328 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
329 {
330 //
331 // bulk interrupt transfer
332 //
333 if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
334 {
335 //
336 // Check if there is a MDL
337 //
338 if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
339 {
340 //
341 // sanity check
342 //
343 PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
344
345 //
346 // Create one using TransferBuffer
347 //
348 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
349 m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
350 Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
351 FALSE,
352 FALSE,
353 NULL);
354
355 if (!m_TransferBufferMDL)
356 {
357 //
358 // failed to allocate mdl
359 //
360 return STATUS_INSUFFICIENT_RESOURCES;
361 }
362
363 //
364 // build mdl for non paged pool
365 // FIXME: Does hub driver already do this when passing MDL?
366 //
367 MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
368
369 //
370 // Keep that ehci created the MDL and needs to free it.
371 //
372 }
373 else
374 {
375 m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
376 }
377
378 //
379 // save buffer length
380 //
381 m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
382
383 //
384 // Set Length Completed to 0
385 //
386 m_TransferBufferLengthCompleted = 0;
387
388 //
389 // get endpoint descriptor
390 //
391 m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
392
393 }
394 break;
395 }
396 default:
397 DPRINT1("URB Function: not supported %x\n", Urb->UrbHeader.Function);
398 PC_ASSERT(FALSE);
399 }
400
401 //
402 // done
403 //
404 return STATUS_SUCCESS;
405
406 }
407
408 //----------------------------------------------------------------------------------------
409 BOOLEAN
410 CUSBRequest::IsRequestComplete()
411 {
412 //
413 // FIXME: check if request was split
414 //
415
416 //
417 // Check if the transfer was completed, only valid for Bulk Transfers
418 //
419 if ((m_TransferBufferLengthCompleted < m_TransferBufferLength)
420 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK))
421 {
422 //
423 // Transfer not completed
424 //
425 return FALSE;
426 }
427 return TRUE;
428 }
429 //----------------------------------------------------------------------------------------
430 ULONG
431 CUSBRequest::GetTransferType()
432 {
433 //
434 // call internal implementation
435 //
436 return InternalGetTransferType();
437 }
438
439 USHORT
440 CUSBRequest::GetMaxPacketSize()
441 {
442 if (!m_EndpointDescriptor)
443 {
444 //
445 // control request
446 //
447 return 0;
448 }
449
450 ASSERT(m_Irp);
451 ASSERT(m_EndpointDescriptor);
452
453 //
454 // return max packet size
455 //
456 return m_EndpointDescriptor->wMaxPacketSize;
457 }
458
459 UCHAR
460 CUSBRequest::GetInterval()
461 {
462 ASSERT(m_EndpointDescriptor);
463 ASSERT((m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT);
464
465 //
466 // return interrupt interval
467 //
468 return m_EndpointDescriptor->bInterval;
469 }
470
471 UCHAR
472 CUSBRequest::GetEndpointAddress()
473 {
474 if (!m_EndpointDescriptor)
475 {
476 //
477 // control request
478 //
479 return 0;
480 }
481
482 ASSERT(m_Irp);
483 ASSERT(m_EndpointDescriptor);
484
485 //
486 // endpoint number is between 1-15
487 //
488 return (m_EndpointDescriptor->bEndpointAddress & 0xF);
489 }
490
491 //----------------------------------------------------------------------------------------
492 ULONG
493 CUSBRequest::InternalGetTransferType()
494 {
495 ULONG TransferType;
496
497 //
498 // check if an irp is provided
499 //
500 if (m_Irp)
501 {
502 ASSERT(m_EndpointDescriptor);
503
504 //
505 // end point is defined in the low byte of bmAttributes
506 //
507 TransferType = (m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
508 }
509 else
510 {
511 //
512 // initialized with setup packet, must be a control transfer
513 //
514 TransferType = USB_ENDPOINT_TYPE_CONTROL;
515 }
516
517 //
518 // done
519 //
520 return TransferType;
521 }
522
523 UCHAR
524 CUSBRequest::InternalGetPidDirection()
525 {
526 ASSERT(m_Irp);
527 ASSERT(m_EndpointDescriptor);
528
529 //
530 // end point is defined in the low byte of bEndpointAddress
531 //
532 return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
533 }
534
535
536 //----------------------------------------------------------------------------------------
537 UCHAR
538 CUSBRequest::GetDeviceAddress()
539 {
540 PIO_STACK_LOCATION IoStack;
541 PURB Urb;
542 PUSBDEVICE UsbDevice;
543
544 //
545 // check if there is an irp provided
546 //
547 if (!m_Irp)
548 {
549 //
550 // used provided address
551 //
552 return m_DeviceAddress;
553 }
554
555 //
556 // get current stack location
557 //
558 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
559
560 //
561 // get contained urb
562 //
563 Urb = (PURB)IoStack->Parameters.Others.Argument1;
564
565 //
566 // check if there is a pipe handle provided
567 //
568 if (Urb->UrbHeader.UsbdDeviceHandle)
569 {
570 //
571 // there is a device handle provided
572 //
573 UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle;
574
575 //
576 // return device address
577 //
578 return UsbDevice->GetDeviceAddress();
579 }
580
581 //
582 // no device handle provided, it is the host root bus
583 //
584 return 0;
585 }
586
587 VOID
588 CUSBRequest::FreeDescriptor(
589 POHCI_GENERAL_TD Descriptor)
590 {
591 if (Descriptor->BufferSize)
592 {
593 //
594 // free buffer
595 //
596 m_DmaManager->Release(Descriptor->BufferLogical, Descriptor->BufferSize);
597 }
598
599 //
600 // release descriptor
601 //
602 m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
603
604 }
605
606 //----------------------------------------------------------------------------------------
607 NTSTATUS
608 CUSBRequest::CreateIsochronousTransferDescriptor(
609 POHCI_ISO_TD* OutDescriptor,
610 ULONG FrameCount)
611 {
612 POHCI_ISO_TD Descriptor;
613 PHYSICAL_ADDRESS DescriptorAddress;
614 NTSTATUS Status;
615
616 //
617 // allocate transfer descriptor
618 //
619 Status = m_DmaManager->Allocate(sizeof(OHCI_ISO_TD), (PVOID*)&Descriptor, &DescriptorAddress);
620 if (!NT_SUCCESS(Status))
621 {
622 //
623 // no memory
624 //
625 return Status;
626 }
627
628 //
629 // initialize descriptor, hardware part
630 //
631 Descriptor->Flags = OHCI_ITD_SET_FRAME_COUNT(FrameCount) | OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED);
632 Descriptor->BufferPhysical = 0;
633 Descriptor->NextPhysicalDescriptor = 0;
634 Descriptor->LastPhysicalByteAddress = 0;
635
636 //
637 // software part
638 //
639 Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
640 Descriptor->NextLogicalDescriptor = 0;
641
642 //
643 // store result
644 //
645 *OutDescriptor = Descriptor;
646
647 //
648 // done
649 //
650 return STATUS_SUCCESS;
651 }
652
653 NTSTATUS
654 CUSBRequest::BuildIsochronousEndpoint(
655 POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
656 {
657 POHCI_ISO_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor;
658 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
659 ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset;
660 NTSTATUS Status;
661 PVOID Buffer;
662 PIO_STACK_LOCATION IoStack;
663 PURB Urb;
664
665 DPRINT1("cp\n");
666 //
667 // get current irp stack location
668 //
669 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
670
671 //
672 // sanity check
673 //
674 PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
675 PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
676 PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
677
678 //
679 // get urb
680 //
681 Urb = (PURB)IoStack->Parameters.Others.Argument1;
682 ASSERT(Urb);
683
684 //
685 // allocate endpoint descriptor
686 //
687 Status = AllocateEndpointDescriptor(&EndpointDescriptor);
688 if (!NT_SUCCESS(Status))
689 {
690 //
691 // failed to create setup descriptor
692 //
693 return Status;
694 }
695 DPRINT1("cp\n");
696 //
697 // get buffer
698 //
699 Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
700 ASSERT(Buffer);
701
702 DPRINT1("cp\n");
703 while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets)
704 {
705 //
706 // get number of packets remaining
707 //
708 NumberOfPackets = min(Urb->UrbIsochronousTransfer.NumberOfPackets - Index, OHCI_ITD_NOFFSET);
709 DPRINT1("cp Number Packets %lu\n", NumberOfPackets);
710 //
711 // allocate iso descriptor
712 //
713 Status = CreateIsochronousTransferDescriptor(&CurrentDescriptor, NumberOfPackets);
714 if (!NT_SUCCESS(Status))
715 {
716 //
717 // FIXME: cleanup
718 // failed to allocate descriptor
719 //
720 ASSERT(FALSE);
721 return Status;
722 }
723 DPRINT1("cp\n");
724 //
725 // initialize descriptor
726 //
727 CurrentDescriptor->BufferPhysical = (MmGetPhysicalAddress(Buffer).LowPart & ~ (PAGE_SIZE - 1));
728
729 //
730 // get page offset
731 //
732 PageOffset = BYTE_OFFSET(MmGetPhysicalAddress(Buffer).LowPart);
733 DPRINT1("cp\n");
734 for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++)
735 {
736 //
737 // store buffer offset
738 //
739 CurrentDescriptor->Offset[SubIndex] = Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset + PageOffset;
740 }
741
742 //
743 // increment packet offset
744 //
745 Index += NumberOfPackets;
746
747 //
748 // check if this is the last descriptor
749 //
750 if (Index == Urb->UrbIsochronousTransfer.NumberOfPackets)
751 {
752 //
753 // end of transfer
754 //
755 CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + m_TransferBufferLength - 1;
756 }
757 else
758 {
759 //
760 // use start address of next packet - 1
761 //
762 CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset - 1;
763
764 //
765 // move buffer to next address
766 //
767 Buffer = (PVOID)((ULONG_PTR)Buffer + Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset);
768 }
769
770 //
771 // is there a previous descriptor
772 //
773 if (PreviousDescriptor)
774 {
775 //
776 // link descriptors
777 //
778 PreviousDescriptor->NextLogicalDescriptor = CurrentDescriptor;
779 PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
780 }
781 else
782 {
783 //
784 // first descriptor
785 //
786 FirstDescriptor = CurrentDescriptor;
787 }
788
789 //
790 // store as previous descriptor
791 //
792 PreviousDescriptor = CurrentDescriptor;
793 }
794 DPRINT1("cp\n");
795
796 //
797 // clear interrupt mask for last transfer descriptor
798 //
799 CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
800
801 //
802 // fire interrupt as soon transfer is finished
803 //
804 CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
805
806 //
807 // set isochronous type
808 //
809 EndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
810
811 //
812 // now link descriptor to endpoint
813 //
814 EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
815 EndpointDescriptor->TailPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
816 EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
817 DPRINT1("cp\n");
818 //
819 // store result
820 //
821 *OutEndpointDescriptor = EndpointDescriptor;
822
823 //
824 // done
825 //
826 return STATUS_SUCCESS;
827 }
828
829 //----------------------------------------------------------------------------------------
830 NTSTATUS
831 CUSBRequest::CreateGeneralTransferDescriptor(
832 POHCI_GENERAL_TD* OutDescriptor,
833 ULONG BufferSize)
834 {
835 POHCI_GENERAL_TD Descriptor;
836 PHYSICAL_ADDRESS DescriptorAddress;
837 NTSTATUS Status;
838
839 //
840 // allocate transfer descriptor
841 //
842 Status = m_DmaManager->Allocate(sizeof(OHCI_GENERAL_TD), (PVOID*)&Descriptor, &DescriptorAddress);
843 if (!NT_SUCCESS(Status))
844 {
845 //
846 // no memory
847 //
848 return Status;
849 }
850
851 //
852 // initialize descriptor, hardware part
853 //
854 Descriptor->Flags = 0;
855 Descriptor->BufferPhysical = 0;
856 Descriptor->NextPhysicalDescriptor = 0;
857 Descriptor->LastPhysicalByteAddress = 0;
858
859 //
860 // software part
861 //
862 Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
863 Descriptor->BufferSize = BufferSize;
864
865 if (BufferSize > 0)
866 {
867 //
868 // allocate buffer from dma
869 //
870 Status = m_DmaManager->Allocate(BufferSize, &Descriptor->BufferLogical, &DescriptorAddress);
871 if (!NT_SUCCESS(Status))
872 {
873 //
874 // no memory
875 //
876 m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
877 return Status;
878 }
879
880 //
881 // set physical address of buffer
882 //
883 Descriptor->BufferPhysical = DescriptorAddress.LowPart;
884 Descriptor->LastPhysicalByteAddress = Descriptor->BufferPhysical + BufferSize - 1;
885 }
886
887 //
888 // store result
889 //
890 *OutDescriptor = Descriptor;
891
892 //
893 // done
894 //
895 return STATUS_SUCCESS;
896 }
897
898 NTSTATUS
899 CUSBRequest::AllocateEndpointDescriptor(
900 OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
901 {
902 POHCI_ENDPOINT_DESCRIPTOR Descriptor;
903 PHYSICAL_ADDRESS DescriptorAddress;
904 NTSTATUS Status;
905
906 //
907 // allocate descriptor
908 //
909 Status = m_DmaManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR), (PVOID*)&Descriptor, &DescriptorAddress);
910 if (!NT_SUCCESS(Status))
911 {
912 //
913 // failed to allocate descriptor
914 //
915 return Status;
916 }
917
918 //
919 // intialize descriptor
920 //
921 Descriptor->Flags = OHCI_ENDPOINT_SKIP;
922
923 //
924 // append device address and endpoint number
925 //
926 Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress());
927 Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
928 Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
929
930 //
931 // is there an endpoint descriptor
932 //
933 if (m_EndpointDescriptor)
934 {
935 //
936 // check direction
937 //
938 if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->bEndpointAddress))
939 {
940 //
941 // direction out
942 //
943 Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_OUT;
944 }
945 else
946 {
947 //
948 // direction in
949 //
950 Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_IN;
951 }
952
953 }
954
955
956 //
957 // FIXME: detect type
958 //
959 Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED;
960
961 Descriptor->HeadPhysicalDescriptor = 0;
962 Descriptor->NextPhysicalEndpoint = 0;
963 Descriptor->TailPhysicalDescriptor = 0;
964 Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
965
966 //
967 // store result
968 //
969 *OutDescriptor = Descriptor;
970
971 //
972 // done
973 //
974 return STATUS_SUCCESS;
975 }
976
977 NTSTATUS
978 CUSBRequest::BuildBulkInterruptEndpoint(
979 POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
980 {
981 POHCI_GENERAL_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor, LastDescriptor;
982 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
983 ULONG BufferSize, CurrentSize, Direction, MaxLengthInPage;
984 NTSTATUS Status;
985 PVOID Buffer;
986
987 //
988 // allocate endpoint descriptor
989 //
990 Status = AllocateEndpointDescriptor(&EndpointDescriptor);
991 if (!NT_SUCCESS(Status))
992 {
993 //
994 // failed to create setup descriptor
995 //
996 return Status;
997 }
998
999 //
1000 // allocate transfer descriptor for last descriptor
1001 //
1002 Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0);
1003 if (!NT_SUCCESS(Status))
1004 {
1005 //
1006 // failed to create transfer descriptor
1007 //
1008 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1009 return Status;
1010 }
1011
1012 //
1013 // get buffer size
1014 //
1015 BufferSize = m_TransferBufferLength;
1016 ASSERT(BufferSize);
1017 ASSERT(m_TransferBufferMDL);
1018
1019 //
1020 // get buffer
1021 //
1022 Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
1023 ASSERT(Buffer);
1024
1025 if (InternalGetPidDirection())
1026 {
1027 //
1028 // input direction
1029 //
1030 Direction = OHCI_TD_DIRECTION_PID_IN;
1031 }
1032 else
1033 {
1034 //
1035 // output direction
1036 //
1037 Direction = OHCI_TD_DIRECTION_PID_OUT;
1038 }
1039
1040 do
1041 {
1042 //
1043 // get current buffersize
1044 //
1045 CurrentSize = min(8192, BufferSize);
1046
1047 //
1048 // get page offset
1049 //
1050 MaxLengthInPage = PAGE_SIZE - BYTE_OFFSET(Buffer);
1051
1052 //
1053 // get minimum from current page size
1054 //
1055 CurrentSize = min(CurrentSize, MaxLengthInPage);
1056 ASSERT(CurrentSize);
1057
1058 //
1059 // allocate transfer descriptor
1060 //
1061 Status = CreateGeneralTransferDescriptor(&CurrentDescriptor, 0);
1062 if (!NT_SUCCESS(Status))
1063 {
1064 //
1065 // failed to create transfer descriptor
1066 // TODO: cleanup
1067 //
1068 ASSERT(FALSE);
1069 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1070 FreeDescriptor(LastDescriptor);
1071 return Status;
1072 }
1073
1074 //
1075 // initialize descriptor
1076 //
1077 CurrentDescriptor->Flags = Direction | OHCI_TD_BUFFER_ROUNDING | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY;
1078
1079 //
1080 // store physical address of buffer
1081 //
1082 CurrentDescriptor->BufferPhysical = MmGetPhysicalAddress(Buffer).LowPart;
1083 CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + CurrentSize - 1;
1084
1085 //
1086 // is there a previous descriptor
1087 //
1088 if (PreviousDescriptor)
1089 {
1090 //
1091 // link descriptors
1092 //
1093 PreviousDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
1094 PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
1095 }
1096 else
1097 {
1098 //
1099 // it is the first descriptor
1100 //
1101 FirstDescriptor = CurrentDescriptor;
1102 }
1103
1104 DPRINT("PreviousDescriptor %p CurrentDescriptor %p Logical %x Buffer Logical %p Physical %x Last Physical %x CurrentSize %lu\n", PreviousDescriptor, CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, CurrentDescriptor->BufferLogical, CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress, CurrentSize);
1105
1106 //
1107 // set previous descriptor
1108 //
1109 PreviousDescriptor = CurrentDescriptor;
1110
1111 //
1112 // subtract buffer size
1113 //
1114 BufferSize -= CurrentSize;
1115
1116 //
1117 // increment buffer offset
1118 //
1119 Buffer = (PVOID)((ULONG_PTR)Buffer + CurrentSize);
1120
1121 }while(BufferSize);
1122
1123 //
1124 // first descriptor has no carry bit
1125 //
1126 FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY;
1127
1128 //
1129 // fixme: toggle
1130 //
1131 FirstDescriptor->Flags |= OHCI_TD_TOGGLE_0;
1132
1133 //
1134 // clear interrupt mask for last transfer descriptor
1135 //
1136 CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
1137
1138 //
1139 // fire interrupt as soon transfer is finished
1140 //
1141 CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1142
1143 //
1144 // link last data descriptor to last descriptor
1145 //
1146 CurrentDescriptor->NextLogicalDescriptor = LastDescriptor;
1147 CurrentDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1148
1149 //
1150 // now link descriptor to endpoint
1151 //
1152 EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
1153 EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1154 EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
1155
1156 //
1157 // store result
1158 //
1159 *OutEndpointDescriptor = EndpointDescriptor;
1160
1161 //
1162 // done
1163 //
1164 return STATUS_SUCCESS;
1165 }
1166
1167
1168 NTSTATUS
1169 CUSBRequest::BuildControlTransferDescriptor(
1170 POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
1171 {
1172 POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL, LastDescriptor;
1173 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1174 NTSTATUS Status;
1175
1176 //
1177 // allocate endpoint descriptor
1178 //
1179 Status = AllocateEndpointDescriptor(&EndpointDescriptor);
1180 if (!NT_SUCCESS(Status))
1181 {
1182 //
1183 // failed to create setup descriptor
1184 //
1185 return Status;
1186 }
1187
1188 //
1189 // first allocate setup descriptor
1190 //
1191 Status = CreateGeneralTransferDescriptor(&SetupDescriptor, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1192 if (!NT_SUCCESS(Status))
1193 {
1194 //
1195 // failed to create setup descriptor
1196 //
1197 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1198 return Status;
1199 }
1200
1201 //
1202 // now create the status descriptor
1203 //
1204 Status = CreateGeneralTransferDescriptor(&StatusDescriptor, 0);
1205 if (!NT_SUCCESS(Status))
1206 {
1207 //
1208 // failed to create status descriptor
1209 //
1210 FreeDescriptor(SetupDescriptor);
1211 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1212 return Status;
1213 }
1214
1215 //
1216 // finally create the last descriptor
1217 //
1218 Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0);
1219 if (!NT_SUCCESS(Status))
1220 {
1221 //
1222 // failed to create status descriptor
1223 //
1224 FreeDescriptor(SetupDescriptor);
1225 FreeDescriptor(StatusDescriptor);
1226 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1227 return Status;
1228 }
1229
1230 if (m_TransferBufferLength)
1231 {
1232 //
1233 // FIXME: support more than one data descriptor
1234 //
1235 ASSERT(m_TransferBufferLength < 8192);
1236
1237 //
1238 // now create the data descriptor
1239 //
1240 Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
1241 if (!NT_SUCCESS(Status))
1242 {
1243 //
1244 // failed to create status descriptor
1245 //
1246 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1247 FreeDescriptor(SetupDescriptor);
1248 FreeDescriptor(StatusDescriptor);
1249 FreeDescriptor(LastDescriptor);
1250 return Status;
1251 }
1252
1253 //
1254 // initialize data descriptor
1255 //
1256 DataDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY | OHCI_TD_DIRECTION_PID_IN;
1257
1258 //
1259 // store physical address of buffer
1260 //
1261 DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
1262 DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
1263
1264 }
1265
1266 //
1267 // initialize setup descriptor
1268 //
1269 SetupDescriptor->Flags = OHCI_TD_DIRECTION_PID_SETUP | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
1270
1271 if (m_SetupPacket)
1272 {
1273 //
1274 // copy setup packet
1275 //
1276 RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1277 }
1278 else
1279 {
1280 //
1281 // generate setup packet from urb
1282 //
1283 ASSERT(FALSE);
1284 }
1285
1286 //
1287 // initialize status descriptor
1288 //
1289 StatusDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1290 if (m_TransferBufferLength == 0)
1291 {
1292 //
1293 // input direction is flipped for the status descriptor
1294 //
1295 StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
1296 }
1297 else
1298 {
1299 //
1300 // output direction is flipped for the status descriptor
1301 //
1302 StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
1303 }
1304
1305 //
1306 // now link the descriptors
1307 //
1308 if (m_TransferBufferLength)
1309 {
1310 //
1311 // link setup descriptor to data descriptor
1312 //
1313 SetupDescriptor->NextPhysicalDescriptor = DataDescriptor->PhysicalAddress.LowPart;
1314 SetupDescriptor->NextLogicalDescriptor = DataDescriptor;
1315
1316 //
1317 // link data descriptor to status descriptor
1318 // FIXME: check if there are more data descriptors
1319 //
1320 DataDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
1321 DataDescriptor->NextLogicalDescriptor = StatusDescriptor;
1322
1323 //
1324 // link status descriptor to last descriptor
1325 //
1326 StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1327 StatusDescriptor->NextLogicalDescriptor = LastDescriptor;
1328 }
1329 else
1330 {
1331 //
1332 // link setup descriptor to status descriptor
1333 //
1334 SetupDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
1335 SetupDescriptor->NextLogicalDescriptor = StatusDescriptor;
1336
1337 //
1338 // link status descriptor to last descriptor
1339 //
1340 StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1341 StatusDescriptor->NextLogicalDescriptor = LastDescriptor;
1342 }
1343
1344 //
1345 // now link descriptor to endpoint
1346 //
1347 EndpointDescriptor->HeadPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
1348 EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1349 EndpointDescriptor->HeadLogicalDescriptor = SetupDescriptor;
1350
1351 //
1352 // store result
1353 //
1354 *OutEndpointDescriptor = EndpointDescriptor;
1355
1356 //
1357 // done
1358 //
1359 return STATUS_SUCCESS;
1360 }
1361
1362 //----------------------------------------------------------------------------------------
1363 NTSTATUS
1364 CUSBRequest::GetEndpointDescriptor(
1365 struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
1366 {
1367 ULONG TransferType;
1368 NTSTATUS Status;
1369
1370 //
1371 // get transfer type
1372 //
1373 TransferType = InternalGetTransferType();
1374
1375 //
1376 // build request depending on type
1377 //
1378 switch(TransferType)
1379 {
1380 case USB_ENDPOINT_TYPE_CONTROL:
1381 Status = BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
1382 break;
1383 case USB_ENDPOINT_TYPE_BULK:
1384 case USB_ENDPOINT_TYPE_INTERRUPT:
1385 Status = BuildBulkInterruptEndpoint(OutDescriptor);
1386 break;
1387 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
1388 Status = BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
1389 break;
1390 default:
1391 PC_ASSERT(FALSE);
1392 Status = STATUS_NOT_IMPLEMENTED;
1393 break;
1394 }
1395
1396 if (NT_SUCCESS(Status))
1397 {
1398 //
1399 // store queue head
1400 //
1401 //m_QueueHead = *OutDescriptor;
1402
1403 //
1404 // store request object
1405 //
1406 (*OutDescriptor)->Request = PVOID(this);
1407 }
1408
1409 //
1410 // done
1411 //
1412 return Status;
1413 }
1414
1415 //----------------------------------------------------------------------------------------
1416 VOID
1417 CUSBRequest::GetResultStatus(
1418 OUT OPTIONAL NTSTATUS * NtStatusCode,
1419 OUT OPTIONAL PULONG UrbStatusCode)
1420 {
1421 //
1422 // sanity check
1423 //
1424 PC_ASSERT(m_CompletionEvent);
1425
1426 //
1427 // wait for the operation to complete
1428 //
1429 KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL);
1430
1431 //
1432 // copy status
1433 //
1434 if (NtStatusCode)
1435 {
1436 *NtStatusCode = m_NtStatusCode;
1437 }
1438
1439 //
1440 // copy urb status
1441 //
1442 if (UrbStatusCode)
1443 {
1444 *UrbStatusCode = m_UrbStatusCode;
1445 }
1446
1447 }
1448
1449 VOID
1450 CUSBRequest::FreeEndpointDescriptor(
1451 struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
1452 {
1453 POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
1454
1455 DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
1456
1457 //
1458 // get first general transfer descriptor
1459 //
1460 TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
1461
1462 //
1463 // release endpoint descriptor
1464 //
1465 m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1466
1467 while(TransferDescriptor)
1468 {
1469 //
1470 // get next
1471 //
1472 NextTransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
1473
1474 //
1475 // is there a buffer associated
1476 //
1477 if (TransferDescriptor->BufferSize)
1478 {
1479 //
1480 // release buffer
1481 //
1482 m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize);
1483 }
1484
1485 DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor, TransferDescriptor->PhysicalAddress.LowPart, TransferDescriptor->BufferPhysical, TransferDescriptor->LastPhysicalByteAddress);
1486
1487 //
1488 // release descriptor
1489 //
1490 m_DmaManager->Release(TransferDescriptor, sizeof(OHCI_GENERAL_TD));
1491
1492 //
1493 // move to next
1494 //
1495 TransferDescriptor = NextTransferDescriptor;
1496 }
1497
1498 }
1499
1500 VOID
1501 CUSBRequest::CompletionCallback(
1502 struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
1503 {
1504 PIO_STACK_LOCATION IoStack;
1505 PURB Urb;
1506
1507 DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
1508
1509 //
1510 // set status code
1511 //
1512 m_NtStatusCode = STATUS_SUCCESS;
1513 m_UrbStatusCode = USBD_STATUS_SUCCESS;
1514
1515 if (m_Irp)
1516 {
1517 //
1518 // set irp completion status
1519 //
1520 m_Irp->IoStatus.Status = STATUS_SUCCESS; //FIXME
1521
1522 //
1523 // get current irp stack location
1524 //
1525 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
1526
1527 //
1528 // get urb
1529 //
1530 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1531
1532 //
1533 // store urb status
1534 //
1535 Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; //FIXME
1536
1537 //
1538 // Check if the MDL was created
1539 //
1540 if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
1541 {
1542 //
1543 // Free Mdl
1544 //
1545 IoFreeMdl(m_TransferBufferMDL);
1546 }
1547
1548 //
1549 // FIXME: support status and calculate length
1550 //
1551
1552 //
1553 // FIXME: check if the transfer was split
1554 // if yes dont complete irp yet
1555 //
1556 IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
1557 }
1558 else
1559 {
1560 //
1561 // signal completion event
1562 //
1563 PC_ASSERT(m_CompletionEvent);
1564 KeSetEvent(m_CompletionEvent, 0, FALSE);
1565 }
1566 }
1567
1568
1569 //-----------------------------------------------------------------------------------------
1570 BOOLEAN
1571 CUSBRequest::IsRequestInitialized()
1572 {
1573 if (m_Irp || m_SetupPacket)
1574 {
1575 //
1576 // request is initialized
1577 //
1578 return TRUE;
1579 }
1580
1581 //
1582 // request is not initialized
1583 //
1584 return FALSE;
1585 }
1586
1587 //-----------------------------------------------------------------------------------------
1588 BOOLEAN
1589 CUSBRequest::IsQueueHeadComplete(
1590 struct _QUEUE_HEAD * QueueHead)
1591 {
1592 UNIMPLEMENTED
1593 return TRUE;
1594 }
1595
1596
1597
1598 //-----------------------------------------------------------------------------------------
1599 NTSTATUS
1600 InternalCreateUSBRequest(
1601 PUSBREQUEST *OutRequest)
1602 {
1603 PUSBREQUEST This;
1604
1605 //
1606 // allocate requests
1607 //
1608 This = new(NonPagedPool, TAG_USBOHCI) CUSBRequest(0);
1609 if (!This)
1610 {
1611 //
1612 // failed to allocate
1613 //
1614 return STATUS_INSUFFICIENT_RESOURCES;
1615 }
1616
1617 //
1618 // add reference count
1619 //
1620 This->AddRef();
1621
1622 //
1623 // return result
1624 //
1625 *OutRequest = (PUSBREQUEST)This;
1626
1627 //
1628 // done
1629 //
1630 return STATUS_SUCCESS;
1631 }