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