[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 = NULL, PreviousDescriptor = NULL, CurrentDescriptor = NULL;
658 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
659 ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset, Page;
660 NTSTATUS Status;
661 PVOID Buffer;
662 PIO_STACK_LOCATION IoStack;
663 PURB Urb;
664 PHYSICAL_ADDRESS Address;
665
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 ASSERT(FALSE);
694 return Status;
695 }
696
697 //
698 // get buffer
699 //
700 Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
701 ASSERT(Buffer);
702
703 //
704 // FIXME: support requests which spans serveral pages
705 //
706 ASSERT(ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(m_TransferBufferMDL), MmGetMdlByteCount(m_TransferBufferMDL)) <= 2);
707
708 Status = m_DmaManager->Allocate(m_TransferBufferLength, &Buffer, &Address);
709 ASSERT(Status == STATUS_SUCCESS);
710
711
712 while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets)
713 {
714 //
715 // get number of packets remaining
716 //
717 NumberOfPackets = min(Urb->UrbIsochronousTransfer.NumberOfPackets - Index, OHCI_ITD_NOFFSET);
718 //
719 // allocate iso descriptor
720 //
721 Status = CreateIsochronousTransferDescriptor(&CurrentDescriptor, NumberOfPackets);
722 if (!NT_SUCCESS(Status))
723 {
724 //
725 // FIXME: cleanup
726 // failed to allocate descriptor
727 //
728 ASSERT(FALSE);
729 return Status;
730 }
731
732 //
733 // get physical page
734 //
735 Page = MmGetPhysicalAddress(Buffer).LowPart;
736
737 //
738 // get page offset
739 //
740 PageOffset = BYTE_OFFSET(Page);
741
742 //
743 // initialize descriptor
744 //
745 CurrentDescriptor->BufferPhysical = Page - PageOffset;
746
747 for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++)
748 {
749 //
750 // store buffer offset
751 //
752 CurrentDescriptor->Offset[SubIndex] = Urb->UrbIsochronousTransfer.IsoPacket[Index+SubIndex].Offset + PageOffset;
753 DPRINT1("Index %lu PacketOffset %lu FinalOffset %lu\n", SubIndex+Index, Urb->UrbIsochronousTransfer.IsoPacket[Index+SubIndex].Offset, CurrentDescriptor->Offset[SubIndex]);
754 }
755
756 //
757 // increment packet offset
758 //
759 Index += NumberOfPackets;
760
761 //
762 // check if this is the last descriptor
763 //
764 if (Index == Urb->UrbIsochronousTransfer.NumberOfPackets)
765 {
766 //
767 // end of transfer
768 //
769 CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + m_TransferBufferLength - 1;
770 }
771 else
772 {
773 //
774 // use start address of next packet - 1
775 //
776 CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset - 1;
777 }
778
779 //
780 // is there a previous descriptor
781 //
782 if (PreviousDescriptor)
783 {
784 //
785 // link descriptors
786 //
787 PreviousDescriptor->NextLogicalDescriptor = CurrentDescriptor;
788 PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
789 }
790 else
791 {
792 //
793 // first descriptor
794 //
795 FirstDescriptor = CurrentDescriptor;
796 }
797
798 //
799 // store as previous descriptor
800 //
801 PreviousDescriptor = CurrentDescriptor;
802 DPRINT1("Current Descriptor %p Logical %lx StartAddress %x EndAddress %x\n", CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress);
803
804 //
805 // fire interrupt as soon transfer is finished
806 //
807 CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
808 }
809
810 //
811 // clear interrupt mask for last transfer descriptor
812 //
813 CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
814
815 //
816 // fire interrupt as soon transfer is finished
817 //
818 CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
819
820 //
821 // set isochronous type
822 //
823 EndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
824
825 //
826 // now link descriptor to endpoint
827 //
828 EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
829 EndpointDescriptor->TailPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
830 EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
831
832 //
833 // store result
834 //
835 *OutEndpointDescriptor = EndpointDescriptor;
836
837 //
838 // done
839 //
840 return STATUS_SUCCESS;
841 }
842
843 //----------------------------------------------------------------------------------------
844 NTSTATUS
845 CUSBRequest::CreateGeneralTransferDescriptor(
846 POHCI_GENERAL_TD* OutDescriptor,
847 ULONG BufferSize)
848 {
849 POHCI_GENERAL_TD Descriptor;
850 PHYSICAL_ADDRESS DescriptorAddress;
851 NTSTATUS Status;
852
853 //
854 // allocate transfer descriptor
855 //
856 Status = m_DmaManager->Allocate(sizeof(OHCI_GENERAL_TD), (PVOID*)&Descriptor, &DescriptorAddress);
857 if (!NT_SUCCESS(Status))
858 {
859 //
860 // no memory
861 //
862 return Status;
863 }
864
865 //
866 // initialize descriptor, hardware part
867 //
868 Descriptor->Flags = 0;
869 Descriptor->BufferPhysical = 0;
870 Descriptor->NextPhysicalDescriptor = 0;
871 Descriptor->LastPhysicalByteAddress = 0;
872
873 //
874 // software part
875 //
876 Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
877 Descriptor->BufferSize = BufferSize;
878
879 if (BufferSize > 0)
880 {
881 //
882 // allocate buffer from dma
883 //
884 Status = m_DmaManager->Allocate(BufferSize, &Descriptor->BufferLogical, &DescriptorAddress);
885 if (!NT_SUCCESS(Status))
886 {
887 //
888 // no memory
889 //
890 m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
891 return Status;
892 }
893
894 //
895 // set physical address of buffer
896 //
897 Descriptor->BufferPhysical = DescriptorAddress.LowPart;
898 Descriptor->LastPhysicalByteAddress = Descriptor->BufferPhysical + BufferSize - 1;
899 }
900
901 //
902 // store result
903 //
904 *OutDescriptor = Descriptor;
905
906 //
907 // done
908 //
909 return STATUS_SUCCESS;
910 }
911
912 NTSTATUS
913 CUSBRequest::AllocateEndpointDescriptor(
914 OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
915 {
916 POHCI_ENDPOINT_DESCRIPTOR Descriptor;
917 PHYSICAL_ADDRESS DescriptorAddress;
918 NTSTATUS Status;
919
920 //
921 // allocate descriptor
922 //
923 Status = m_DmaManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR), (PVOID*)&Descriptor, &DescriptorAddress);
924 if (!NT_SUCCESS(Status))
925 {
926 //
927 // failed to allocate descriptor
928 //
929 return Status;
930 }
931
932 //
933 // intialize descriptor
934 //
935 Descriptor->Flags = OHCI_ENDPOINT_SKIP;
936
937 //
938 // append device address and endpoint number
939 //
940 Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress());
941 Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
942 Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
943
944 DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %x\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
945
946 //
947 // is there an endpoint descriptor
948 //
949 if (m_EndpointDescriptor)
950 {
951 //
952 // check direction
953 //
954 if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->bEndpointAddress))
955 {
956 //
957 // direction out
958 //
959 Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_OUT;
960 }
961 else
962 {
963 //
964 // direction in
965 //
966 Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_IN;
967 }
968
969 }
970
971
972 //
973 // FIXME: detect type
974 //
975 Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED;
976
977 Descriptor->HeadPhysicalDescriptor = 0;
978 Descriptor->NextPhysicalEndpoint = 0;
979 Descriptor->TailPhysicalDescriptor = 0;
980 Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
981
982 //
983 // store result
984 //
985 *OutDescriptor = Descriptor;
986
987 //
988 // done
989 //
990 return STATUS_SUCCESS;
991 }
992
993 NTSTATUS
994 CUSBRequest::BuildBulkInterruptEndpoint(
995 POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
996 {
997 POHCI_GENERAL_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor, LastDescriptor;
998 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
999 ULONG BufferSize, CurrentSize, Direction, MaxLengthInPage;
1000 NTSTATUS Status;
1001 PVOID Buffer;
1002
1003 //
1004 // allocate endpoint descriptor
1005 //
1006 Status = AllocateEndpointDescriptor(&EndpointDescriptor);
1007 if (!NT_SUCCESS(Status))
1008 {
1009 //
1010 // failed to create setup descriptor
1011 //
1012 return Status;
1013 }
1014
1015 //
1016 // allocate transfer descriptor for last descriptor
1017 //
1018 Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0);
1019 if (!NT_SUCCESS(Status))
1020 {
1021 //
1022 // failed to create transfer descriptor
1023 //
1024 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1025 return Status;
1026 }
1027
1028 //
1029 // get buffer size
1030 //
1031 BufferSize = m_TransferBufferLength;
1032 ASSERT(BufferSize);
1033 ASSERT(m_TransferBufferMDL);
1034
1035 //
1036 // get buffer
1037 //
1038 Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
1039 ASSERT(Buffer);
1040
1041 if (InternalGetPidDirection())
1042 {
1043 //
1044 // input direction
1045 //
1046 Direction = OHCI_TD_DIRECTION_PID_IN;
1047 }
1048 else
1049 {
1050 //
1051 // output direction
1052 //
1053 Direction = OHCI_TD_DIRECTION_PID_OUT;
1054 }
1055
1056 do
1057 {
1058 //
1059 // get current buffersize
1060 //
1061 CurrentSize = min(8192, BufferSize);
1062
1063 //
1064 // get page offset
1065 //
1066 MaxLengthInPage = PAGE_SIZE - BYTE_OFFSET(Buffer);
1067
1068 //
1069 // get minimum from current page size
1070 //
1071 CurrentSize = min(CurrentSize, MaxLengthInPage);
1072 ASSERT(CurrentSize);
1073
1074 //
1075 // allocate transfer descriptor
1076 //
1077 Status = CreateGeneralTransferDescriptor(&CurrentDescriptor, 0);
1078 if (!NT_SUCCESS(Status))
1079 {
1080 //
1081 // failed to create transfer descriptor
1082 // TODO: cleanup
1083 //
1084 ASSERT(FALSE);
1085 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1086 FreeDescriptor(LastDescriptor);
1087 return Status;
1088 }
1089
1090 //
1091 // initialize descriptor
1092 //
1093 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;
1094
1095 //
1096 // store physical address of buffer
1097 //
1098 CurrentDescriptor->BufferPhysical = MmGetPhysicalAddress(Buffer).LowPart;
1099 CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + CurrentSize - 1;
1100
1101 //
1102 // is there a previous descriptor
1103 //
1104 if (PreviousDescriptor)
1105 {
1106 //
1107 // link descriptors
1108 //
1109 PreviousDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
1110 PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
1111 }
1112 else
1113 {
1114 //
1115 // it is the first descriptor
1116 //
1117 FirstDescriptor = CurrentDescriptor;
1118 }
1119
1120 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);
1121
1122 //
1123 // set previous descriptor
1124 //
1125 PreviousDescriptor = CurrentDescriptor;
1126
1127 //
1128 // subtract buffer size
1129 //
1130 BufferSize -= CurrentSize;
1131
1132 //
1133 // increment buffer offset
1134 //
1135 Buffer = (PVOID)((ULONG_PTR)Buffer + CurrentSize);
1136
1137 }while(BufferSize);
1138
1139 //
1140 // first descriptor has no carry bit
1141 //
1142 FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY;
1143
1144 //
1145 // fixme: toggle
1146 //
1147 FirstDescriptor->Flags |= OHCI_TD_TOGGLE_0;
1148
1149 //
1150 // clear interrupt mask for last transfer descriptor
1151 //
1152 CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
1153
1154 //
1155 // fire interrupt as soon transfer is finished
1156 //
1157 CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1158
1159 //
1160 // link last data descriptor to last descriptor
1161 //
1162 CurrentDescriptor->NextLogicalDescriptor = LastDescriptor;
1163 CurrentDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1164
1165 //
1166 // now link descriptor to endpoint
1167 //
1168 EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
1169 EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1170 EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
1171
1172 //
1173 // store result
1174 //
1175 *OutEndpointDescriptor = EndpointDescriptor;
1176
1177 //
1178 // done
1179 //
1180 return STATUS_SUCCESS;
1181 }
1182
1183
1184 NTSTATUS
1185 CUSBRequest::BuildControlTransferDescriptor(
1186 POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
1187 {
1188 POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL, LastDescriptor;
1189 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1190 NTSTATUS Status;
1191
1192 //
1193 // allocate endpoint descriptor
1194 //
1195 Status = AllocateEndpointDescriptor(&EndpointDescriptor);
1196 if (!NT_SUCCESS(Status))
1197 {
1198 //
1199 // failed to create setup descriptor
1200 //
1201 return Status;
1202 }
1203
1204 //
1205 // first allocate setup descriptor
1206 //
1207 Status = CreateGeneralTransferDescriptor(&SetupDescriptor, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1208 if (!NT_SUCCESS(Status))
1209 {
1210 //
1211 // failed to create setup descriptor
1212 //
1213 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1214 return Status;
1215 }
1216
1217 //
1218 // now create the status descriptor
1219 //
1220 Status = CreateGeneralTransferDescriptor(&StatusDescriptor, 0);
1221 if (!NT_SUCCESS(Status))
1222 {
1223 //
1224 // failed to create status descriptor
1225 //
1226 FreeDescriptor(SetupDescriptor);
1227 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1228 return Status;
1229 }
1230
1231 //
1232 // finally create the last descriptor
1233 //
1234 Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0);
1235 if (!NT_SUCCESS(Status))
1236 {
1237 //
1238 // failed to create status descriptor
1239 //
1240 FreeDescriptor(SetupDescriptor);
1241 FreeDescriptor(StatusDescriptor);
1242 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1243 return Status;
1244 }
1245
1246 if (m_TransferBufferLength)
1247 {
1248 //
1249 // FIXME: support more than one data descriptor
1250 //
1251 ASSERT(m_TransferBufferLength < 8192);
1252
1253 //
1254 // now create the data descriptor
1255 //
1256 Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
1257 if (!NT_SUCCESS(Status))
1258 {
1259 //
1260 // failed to create status descriptor
1261 //
1262 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1263 FreeDescriptor(SetupDescriptor);
1264 FreeDescriptor(StatusDescriptor);
1265 FreeDescriptor(LastDescriptor);
1266 return Status;
1267 }
1268
1269 //
1270 // initialize data descriptor
1271 //
1272 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;
1273
1274 //
1275 // store physical address of buffer
1276 //
1277 DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
1278 DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
1279
1280 }
1281
1282 //
1283 // initialize setup descriptor
1284 //
1285 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);
1286
1287 if (m_SetupPacket)
1288 {
1289 //
1290 // copy setup packet
1291 //
1292 RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1293 }
1294 else
1295 {
1296 //
1297 // generate setup packet from urb
1298 //
1299 ASSERT(FALSE);
1300 }
1301
1302 //
1303 // initialize status descriptor
1304 //
1305 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);
1306 if (m_TransferBufferLength == 0)
1307 {
1308 //
1309 // input direction is flipped for the status descriptor
1310 //
1311 StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
1312 }
1313 else
1314 {
1315 //
1316 // output direction is flipped for the status descriptor
1317 //
1318 StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
1319 }
1320
1321 //
1322 // now link the descriptors
1323 //
1324 if (m_TransferBufferLength)
1325 {
1326 //
1327 // link setup descriptor to data descriptor
1328 //
1329 SetupDescriptor->NextPhysicalDescriptor = DataDescriptor->PhysicalAddress.LowPart;
1330 SetupDescriptor->NextLogicalDescriptor = DataDescriptor;
1331
1332 //
1333 // link data descriptor to status descriptor
1334 // FIXME: check if there are more data descriptors
1335 //
1336 DataDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
1337 DataDescriptor->NextLogicalDescriptor = StatusDescriptor;
1338
1339 //
1340 // link status descriptor to last descriptor
1341 //
1342 StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1343 StatusDescriptor->NextLogicalDescriptor = LastDescriptor;
1344 }
1345 else
1346 {
1347 //
1348 // link setup descriptor to status descriptor
1349 //
1350 SetupDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
1351 SetupDescriptor->NextLogicalDescriptor = StatusDescriptor;
1352
1353 //
1354 // link status descriptor to last descriptor
1355 //
1356 StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1357 StatusDescriptor->NextLogicalDescriptor = LastDescriptor;
1358 }
1359
1360 //
1361 // now link descriptor to endpoint
1362 //
1363 EndpointDescriptor->HeadPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
1364 EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1365 EndpointDescriptor->HeadLogicalDescriptor = SetupDescriptor;
1366
1367 //
1368 // store result
1369 //
1370 *OutEndpointDescriptor = EndpointDescriptor;
1371
1372 //
1373 // done
1374 //
1375 return STATUS_SUCCESS;
1376 }
1377
1378 //----------------------------------------------------------------------------------------
1379 NTSTATUS
1380 CUSBRequest::GetEndpointDescriptor(
1381 struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
1382 {
1383 ULONG TransferType;
1384 NTSTATUS Status;
1385
1386 //
1387 // get transfer type
1388 //
1389 TransferType = InternalGetTransferType();
1390
1391 //
1392 // build request depending on type
1393 //
1394 switch(TransferType)
1395 {
1396 case USB_ENDPOINT_TYPE_CONTROL:
1397 Status = BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
1398 break;
1399 case USB_ENDPOINT_TYPE_BULK:
1400 case USB_ENDPOINT_TYPE_INTERRUPT:
1401 Status = BuildBulkInterruptEndpoint(OutDescriptor);
1402 break;
1403 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
1404 Status = BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
1405 break;
1406 default:
1407 PC_ASSERT(FALSE);
1408 Status = STATUS_NOT_IMPLEMENTED;
1409 break;
1410 }
1411
1412 if (NT_SUCCESS(Status))
1413 {
1414 //
1415 // store queue head
1416 //
1417 //m_QueueHead = *OutDescriptor;
1418
1419 //
1420 // store request object
1421 //
1422 (*OutDescriptor)->Request = PVOID(this);
1423 }
1424
1425 //
1426 // done
1427 //
1428 return Status;
1429 }
1430
1431 //----------------------------------------------------------------------------------------
1432 VOID
1433 CUSBRequest::GetResultStatus(
1434 OUT OPTIONAL NTSTATUS * NtStatusCode,
1435 OUT OPTIONAL PULONG UrbStatusCode)
1436 {
1437 //
1438 // sanity check
1439 //
1440 PC_ASSERT(m_CompletionEvent);
1441
1442 //
1443 // wait for the operation to complete
1444 //
1445 KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL);
1446
1447 //
1448 // copy status
1449 //
1450 if (NtStatusCode)
1451 {
1452 *NtStatusCode = m_NtStatusCode;
1453 }
1454
1455 //
1456 // copy urb status
1457 //
1458 if (UrbStatusCode)
1459 {
1460 *UrbStatusCode = m_UrbStatusCode;
1461 }
1462
1463 }
1464
1465 VOID
1466 CUSBRequest::FreeEndpointDescriptor(
1467 struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
1468 {
1469 POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
1470 POHCI_ISO_TD IsoTransferDescriptor, IsoNextTransferDescriptor;
1471 ULONG Index, PacketCount;
1472
1473 DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
1474
1475 if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT)
1476 {
1477 //
1478 // get first iso transfer descriptor
1479 //
1480 IsoTransferDescriptor = (POHCI_ISO_TD)OutDescriptor->HeadLogicalDescriptor;
1481
1482 //
1483 // release endpoint descriptor
1484 //
1485 m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1486
1487 while(IsoTransferDescriptor)
1488 {
1489 //
1490 // get next
1491 //
1492 IsoNextTransferDescriptor = IsoTransferDescriptor->NextLogicalDescriptor;
1493
1494 //
1495 // get packet count
1496 //
1497 PacketCount = OHCI_ITD_GET_FRAME_COUNT(IsoTransferDescriptor->Flags);
1498
1499 DPRINT1("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x PacketCount %lu\n", IsoTransferDescriptor, IsoTransferDescriptor->PhysicalAddress.LowPart, IsoTransferDescriptor->BufferPhysical, IsoTransferDescriptor->LastPhysicalByteAddress, PacketCount);
1500
1501 for(Index = 0; Index < PacketCount; Index++)
1502 {
1503 DPRINT1("PSW Index %lu Value %x\n", Index, IsoTransferDescriptor->Offset[Index]);
1504 }
1505
1506 //
1507 // release descriptor
1508 //
1509 m_DmaManager->Release(IsoTransferDescriptor, sizeof(OHCI_ISO_TD));
1510
1511 //
1512 // move to next
1513 //
1514 IsoTransferDescriptor = IsoNextTransferDescriptor;
1515 }
1516 }
1517 else
1518 {
1519 //
1520 // get first general transfer descriptor
1521 //
1522 TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
1523
1524 //
1525 // release endpoint descriptor
1526 //
1527 m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1528
1529 while(TransferDescriptor)
1530 {
1531 //
1532 // get next
1533 //
1534 NextTransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
1535
1536 //
1537 // is there a buffer associated
1538 //
1539 if (TransferDescriptor->BufferSize)
1540 {
1541 //
1542 // release buffer
1543 //
1544 m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize);
1545 }
1546
1547 DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor, TransferDescriptor->PhysicalAddress.LowPart, TransferDescriptor->BufferPhysical, TransferDescriptor->LastPhysicalByteAddress);
1548
1549 //
1550 // release descriptor
1551 //
1552 m_DmaManager->Release(TransferDescriptor, sizeof(OHCI_GENERAL_TD));
1553
1554 //
1555 // move to next
1556 //
1557 TransferDescriptor = NextTransferDescriptor;
1558 }
1559 }
1560
1561 }
1562
1563 VOID
1564 CUSBRequest::CompletionCallback(
1565 struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
1566 {
1567 PIO_STACK_LOCATION IoStack;
1568 PURB Urb;
1569
1570 DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
1571
1572 //
1573 // set status code
1574 //
1575 m_NtStatusCode = STATUS_SUCCESS;
1576 m_UrbStatusCode = USBD_STATUS_SUCCESS;
1577
1578 if (m_Irp)
1579 {
1580 //
1581 // set irp completion status
1582 //
1583 m_Irp->IoStatus.Status = STATUS_SUCCESS; //FIXME
1584
1585 //
1586 // get current irp stack location
1587 //
1588 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
1589
1590 //
1591 // get urb
1592 //
1593 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1594
1595 //
1596 // store urb status
1597 //
1598 Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; //FIXME
1599
1600 //
1601 // Check if the MDL was created
1602 //
1603 if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
1604 {
1605 //
1606 // Free Mdl
1607 //
1608 IoFreeMdl(m_TransferBufferMDL);
1609 }
1610
1611 //
1612 // FIXME: support status and calculate length
1613 //
1614
1615 //
1616 // FIXME: check if the transfer was split
1617 // if yes dont complete irp yet
1618 //
1619 IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
1620 }
1621 else
1622 {
1623 //
1624 // signal completion event
1625 //
1626 PC_ASSERT(m_CompletionEvent);
1627 KeSetEvent(m_CompletionEvent, 0, FALSE);
1628 }
1629 }
1630
1631
1632 //-----------------------------------------------------------------------------------------
1633 BOOLEAN
1634 CUSBRequest::IsRequestInitialized()
1635 {
1636 if (m_Irp || m_SetupPacket)
1637 {
1638 //
1639 // request is initialized
1640 //
1641 return TRUE;
1642 }
1643
1644 //
1645 // request is not initialized
1646 //
1647 return FALSE;
1648 }
1649
1650 //-----------------------------------------------------------------------------------------
1651 BOOLEAN
1652 CUSBRequest::IsQueueHeadComplete(
1653 struct _QUEUE_HEAD * QueueHead)
1654 {
1655 UNIMPLEMENTED
1656 return TRUE;
1657 }
1658
1659
1660
1661 //-----------------------------------------------------------------------------------------
1662 NTSTATUS
1663 InternalCreateUSBRequest(
1664 PUSBREQUEST *OutRequest)
1665 {
1666 PUSBREQUEST This;
1667
1668 //
1669 // allocate requests
1670 //
1671 This = new(NonPagedPool, TAG_USBOHCI) CUSBRequest(0);
1672 if (!This)
1673 {
1674 //
1675 // failed to allocate
1676 //
1677 return STATUS_INSUFFICIENT_RESOURCES;
1678 }
1679
1680 //
1681 // add reference count
1682 //
1683 This->AddRef();
1684
1685 //
1686 // return result
1687 //
1688 *OutRequest = (PUSBREQUEST)This;
1689
1690 //
1691 // done
1692 //
1693 return STATUS_SUCCESS;
1694 }