b08306d92021452ae63fe6b88ebc1a8361fca0bd
[reactos.git] / drivers / usb / usbuhci_new / usbuhci.c
1 /*
2 * PROJECT: ReactOS USB UHCI Miniport Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBUHCI main driver functions
5 * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbuhci.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define NDEBUG_UHCI_TRACE
14 #define NDEBUG_UHCI_IMPLEMENT
15 #include "dbg_uhci.h"
16
17 USBPORT_REGISTRATION_PACKET RegPacket;
18
19 VOID
20 NTAPI
21 UhciDumpHcdQH(PUHCI_HCD_QH QH)
22 {
23 DPRINT("QH - %p\n", QH);
24 DPRINT("NextQH - %p\n", QH->HwQH.NextQH);
25 DPRINT("NextElement - %p\n", QH->HwQH.NextElement);
26
27 DPRINT("PhysicalAddress - %p\n", QH->PhysicalAddress);
28 DPRINT("QhFlags - %X\n", QH->QhFlags);
29 DPRINT("NextHcdQH - %X\n", QH->NextHcdQH);
30 DPRINT("PrevHcdQH - %X\n", QH->PrevHcdQH);
31 DPRINT("UhciEndpoint - %X\n", QH->UhciEndpoint);
32 }
33
34 VOID
35 NTAPI
36 UhciDumpHcdTD(PUHCI_HCD_TD TD)
37 {
38 DPRINT("TD - %p\n", TD);
39 DPRINT("NextElement - %p\n", TD->HwTD.NextElement);
40 DPRINT("ControlStatus - %08X\n", TD->HwTD.ControlStatus.AsULONG);
41 DPRINT("Token - %p\n", TD->HwTD.Token.AsULONG);
42 if (TD->HwTD.Buffer)
43 DPRINT("Buffer - %p\n", TD->HwTD.Buffer);
44
45 if (TD->SetupPacket.bmRequestType.B)
46 DPRINT("bmRequestType - %02X\n", TD->SetupPacket.bmRequestType.B);
47 if (TD->SetupPacket.bRequest)
48 DPRINT("bRequest - %02X\n", TD->SetupPacket.bRequest);
49 if (TD->SetupPacket.wValue.W)
50 DPRINT("wValue - %04X\n", TD->SetupPacket.wValue.W);
51 if (TD->SetupPacket.wIndex.W)
52 DPRINT("wIndex - %04X\n", TD->SetupPacket.wIndex.W);
53 if (TD->SetupPacket.wLength)
54 DPRINT("wLength - %04X\n", TD->SetupPacket.wLength);
55
56 DPRINT("PhysicalAddress - %p\n", TD->PhysicalAddress);
57 DPRINT("Flags - %X\n", TD->Flags);
58 DPRINT("NextHcdTD - %p\n", TD->NextHcdTD);
59 DPRINT("UhciTransfer - %p\n", TD->UhciTransfer);
60 }
61
62 VOID
63 NTAPI
64 UhciFixDataToggle(IN PUHCI_EXTENSION UhciExtension,
65 IN PUHCI_ENDPOINT UhciEndpoint,
66 IN PUHCI_HCD_TD TD,
67 IN BOOL DataToggle)
68 {
69 DPRINT_UHCI("UhciFixDataToggle: UhciExtension - %p, UhciEndpoint - %p, DataToggle - %X\n",
70 UhciExtension,
71 UhciEndpoint,
72 DataToggle);
73
74 while (TD)
75 {
76 TD->HwTD.Token.DataToggle = !TD->HwTD.Token.DataToggle;
77 DataToggle = !DataToggle;
78
79 TD = TD->NextHcdTD;
80 }
81
82 UhciEndpoint->DataToggle = DataToggle;
83 }
84
85 VOID
86 NTAPI
87 UhciCleanupFrameListEntry(IN PUHCI_EXTENSION UhciExtension,
88 IN ULONG Index)
89 {
90 PUHCI_HC_RESOURCES UhciResources;
91 ULONG PhysicalAddress;
92 ULONG HeadIdx;
93
94 UhciResources = UhciExtension->HcResourcesVA;
95
96 if (Index == 0)
97 {
98 PhysicalAddress = UhciExtension->StaticTD->PhysicalAddress;
99
100 UhciResources->FrameList[0] = PhysicalAddress |
101 UHCI_FRAME_LIST_POINTER_TD;
102 }
103 else
104 {
105 HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms) +
106 (Index & (ENDPOINT_INTERRUPT_32ms - 1));
107
108 PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress;
109
110 UhciResources->FrameList[Index] = PhysicalAddress |
111 UHCI_FRAME_LIST_POINTER_QH;
112 }
113 }
114
115 VOID
116 NTAPI
117 UhciCleanupFrameList(IN PUHCI_EXTENSION UhciExtension,
118 IN BOOLEAN IsAllEntries)
119 {
120 ULONG NewFrameNumber;
121 ULONG OldFrameNumber;
122 ULONG ix;
123
124 DPRINT_UHCI("UhciCleanupFrameList: [%p] All - %x\n",
125 UhciExtension, IsAllEntries);
126
127 // FIXME: using UhciExtension->LockFrameList after supporting ISOs.
128
129 NewFrameNumber = UhciGet32BitFrameNumber(UhciExtension);
130 OldFrameNumber = UhciExtension->FrameNumber;
131
132 if ((NewFrameNumber - OldFrameNumber) < UHCI_FRAME_LIST_MAX_ENTRIES &&
133 IsAllEntries == FALSE)
134 {
135 for (ix = OldFrameNumber & UHCI_FRAME_LIST_INDEX_MASK;
136 ix != (NewFrameNumber & UHCI_FRAME_LIST_INDEX_MASK);
137 ix = (ix + 1) & UHCI_FRAME_LIST_INDEX_MASK)
138 {
139 UhciCleanupFrameListEntry(UhciExtension, ix);
140 }
141 }
142 else
143 {
144 for (ix = 0; ix < UHCI_FRAME_LIST_MAX_ENTRIES; ++ix)
145 {
146 UhciCleanupFrameListEntry(UhciExtension, ix);
147 }
148 }
149
150 UhciExtension->FrameNumber = NewFrameNumber;
151 }
152
153 VOID
154 NTAPI
155 UhciUpdateCounter(IN PUHCI_EXTENSION UhciExtension)
156 {
157 ULONG FrameNumber;
158
159 FrameNumber = READ_PORT_USHORT(&UhciExtension->BaseRegister->FrameNumber);
160 FrameNumber &= UHCI_FRNUM_FRAME_MASK;
161
162 if ((FrameNumber ^ UhciExtension->FrameHighPart) & UHCI_FRNUM_OVERFLOW_LIST)
163 {
164 UhciExtension->FrameHighPart += UHCI_FRAME_LIST_MAX_ENTRIES;
165
166 DPRINT_UHCI("UhciUpdateCounter: UhciExtension->FrameHighPart - %lX\n",
167 UhciExtension->FrameHighPart);
168 }
169 }
170
171 VOID
172 NTAPI
173 UhciSetNextQH(IN PUHCI_HCD_QH QH,
174 IN PUHCI_HCD_QH NextQH)
175 {
176 DPRINT_UHCI("UhciSetNextQH: QH - %p, NextQH - %p\n", QH, NextQH);
177
178 QH->HwQH.NextQH = NextQH->PhysicalAddress | UHCI_QH_HEAD_LINK_PTR_QH;
179 QH->NextHcdQH = NextQH;
180
181 NextQH->PrevHcdQH = QH;
182 NextQH->QhFlags |= UHCI_HCD_QH_FLAG_ACTIVE;
183 }
184
185 MPSTATUS
186 NTAPI
187 UhciOpenEndpoint(IN PVOID uhciExtension,
188 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
189 IN PVOID uhciEndpoint)
190 {
191 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
192 ULONG TransferType;
193 ULONG_PTR BufferVA;
194 ULONG BufferPA;
195 ULONG ix;
196 ULONG TdCount;
197 PUHCI_HCD_TD TD;
198 SIZE_T BufferLength;
199 PUHCI_HCD_QH QH;
200
201 RtlCopyMemory(&UhciEndpoint->EndpointProperties,
202 EndpointProperties,
203 sizeof(UhciEndpoint->EndpointProperties));
204
205 InitializeListHead(&UhciEndpoint->ListTDs);
206
207 UhciEndpoint->EndpointLock = 0;
208 UhciEndpoint->DataToggle = UHCI_TD_PID_DATA0;
209 UhciEndpoint->Flags = 0;
210
211 TransferType = EndpointProperties->TransferType;
212
213 DPRINT("UhciOpenEndpoint: UhciEndpoint - %p, TransferType - %x\n",
214 UhciEndpoint,
215 TransferType);
216
217 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
218 TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
219 {
220 UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_CONTROL_OR_ISO;
221 }
222
223 BufferVA = EndpointProperties->BufferVA;
224 BufferPA = EndpointProperties->BufferPA;
225
226 BufferLength = EndpointProperties->BufferLength;
227
228 /* For Isochronous transfers not used QHs (only TDs) */
229 if (EndpointProperties->TransferType != USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
230 {
231 /* Initialize HCD Queue Head */
232 UhciEndpoint->QH = (PUHCI_HCD_QH)BufferVA;
233
234 QH = UhciEndpoint->QH;
235
236 QH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
237 QH->PhysicalAddress = BufferPA;
238
239 QH->NextHcdQH = QH;
240 QH->PrevHcdQH = QH;
241 QH->UhciEndpoint = UhciEndpoint;
242
243 BufferVA += sizeof(UHCI_HCD_QH);
244 BufferPA += sizeof(UHCI_HCD_QH);
245
246 BufferLength -= sizeof(UHCI_HCD_QH);
247 }
248
249 /* Initialize HCD Transfer Descriptors */
250 TdCount = BufferLength / sizeof(UHCI_HCD_TD);
251 UhciEndpoint->MaxTDs = TdCount;
252
253 UhciEndpoint->FirstTD = (PUHCI_HCD_TD)BufferVA;
254 UhciEndpoint->AllocatedTDs = 0;
255
256 RtlZeroMemory(UhciEndpoint->FirstTD, TdCount * sizeof(UHCI_HCD_TD));
257
258 for (ix = 0; ix < UhciEndpoint->MaxTDs; ix++)
259 {
260 TD = &UhciEndpoint->FirstTD[ix];
261 TD->PhysicalAddress = BufferPA;
262 BufferPA += sizeof(UHCI_HCD_TD);
263 }
264
265 UhciEndpoint->TailTD = NULL;
266 UhciEndpoint->HeadTD = NULL;
267
268 return MP_STATUS_SUCCESS;
269 }
270
271 MPSTATUS
272 NTAPI
273 UhciReopenEndpoint(IN PVOID uhciExtension,
274 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
275 IN PVOID uhciEndpoint)
276 {
277 DPRINT_IMPL("Uhci: UNIMPLEMENTED. FIXME\n");
278 return MP_STATUS_SUCCESS;
279 }
280
281 VOID
282 NTAPI
283 UhciQueryEndpointRequirements(IN PVOID uhciExtension,
284 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
285 IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements)
286 {
287 ULONG TransferType;
288 ULONG TdCount;
289
290 DPRINT("UhciQueryEndpointRequirements: ... \n");
291
292 TransferType = EndpointProperties->TransferType;
293
294 switch (TransferType)
295 {
296 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
297 DPRINT("UhciQueryEndpointRequirements: IsoTransfer\n");
298 TdCount = 2 * UHCI_MAX_ISO_TD_COUNT;
299
300 EndpointRequirements->HeaderBufferSize = 0 + // Iso queue is have not Queue Heads
301 TdCount * sizeof(UHCI_HCD_TD);
302
303 EndpointRequirements->MaxTransferSize = UHCI_MAX_ISO_TRANSFER_SIZE;
304 break;
305
306 case USBPORT_TRANSFER_TYPE_CONTROL:
307 DPRINT("UhciQueryEndpointRequirements: ControlTransfer\n");
308 TdCount = EndpointProperties->MaxTransferSize /
309 EndpointProperties->TotalMaxPacketSize;
310
311 TdCount += 2; // First + Last TDs
312
313 EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) +
314 TdCount * sizeof(UHCI_HCD_TD);
315
316 EndpointRequirements->MaxTransferSize = EndpointProperties->MaxTransferSize;
317 break;
318
319 case USBPORT_TRANSFER_TYPE_BULK:
320 DPRINT("UhciQueryEndpointRequirements: BulkTransfer\n");
321 TdCount = 2 * UHCI_MAX_BULK_TRANSFER_SIZE /
322 EndpointProperties->TotalMaxPacketSize;
323
324 EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) +
325 TdCount * sizeof(UHCI_HCD_TD);
326
327 EndpointRequirements->MaxTransferSize = UHCI_MAX_BULK_TRANSFER_SIZE;
328 break;
329
330 case USBPORT_TRANSFER_TYPE_INTERRUPT:
331 DPRINT("UhciQueryEndpointRequirements: InterruptTransfer\n");
332 TdCount = 2 * UHCI_MAX_INTERRUPT_TD_COUNT;
333
334 EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) +
335 TdCount * sizeof(UHCI_HCD_TD);
336
337 EndpointRequirements->MaxTransferSize = UHCI_MAX_INTERRUPT_TD_COUNT *
338 EndpointProperties->TotalMaxPacketSize;
339 break;
340
341 default:
342 DPRINT1("UhciQueryEndpointRequirements: Unknown TransferType - %x\n",
343 TransferType);
344 DbgBreakPoint();
345 break;
346 }
347 }
348
349 VOID
350 NTAPI
351 UhciCloseEndpoint(IN PVOID uhciExtension,
352 IN PVOID uhciEndpoint,
353 IN BOOLEAN IsDoDisablePeriodic)
354 {
355 DPRINT_IMPL("UhciCloseEndpoint: UNIMPLEMENTED. FIXME\n");
356 }
357
358 MPSTATUS
359 NTAPI
360 UhciTakeControlHC(IN PUHCI_EXTENSION UhciExtension,
361 IN PUSBPORT_RESOURCES Resources)
362 {
363 LARGE_INTEGER EndTime;
364 LARGE_INTEGER CurrentTime;
365 ULONG ResourcesTypes;
366 PUHCI_HW_REGISTERS BaseRegister;
367 PUSHORT StatusRegister;
368 UHCI_PCI_LEGSUP LegacySupport;
369 UHCI_PCI_LEGSUP LegacyMask;
370 UHCI_USB_COMMAND Command;
371 UHCI_USB_STATUS HcStatus;
372 MPSTATUS MpStatus = MP_STATUS_SUCCESS;
373
374 DPRINT("UhciTakeControlHC: Resources->ResourcesTypes - %x\n",
375 Resources->ResourcesTypes);
376
377 ResourcesTypes = Resources->ResourcesTypes;
378
379 if ((ResourcesTypes & (USBPORT_RESOURCES_PORT | USBPORT_RESOURCES_INTERRUPT)) !=
380 (USBPORT_RESOURCES_PORT | USBPORT_RESOURCES_INTERRUPT))
381 {
382 DPRINT1("UhciTakeControlHC: MP_STATUS_ERROR\n");
383 MpStatus = MP_STATUS_ERROR;
384 }
385
386 BaseRegister = UhciExtension->BaseRegister;
387 StatusRegister = &BaseRegister->HcStatus.AsUSHORT;
388
389 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
390 TRUE,
391 &LegacySupport.AsUSHORT,
392 PCI_LEGSUP,
393 sizeof(USHORT));
394
395 UhciDisableInterrupts(UhciExtension);
396
397 Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT);
398
399 Command.Run = 0;
400 Command.GlobalReset = 0;
401 Command.ConfigureFlag = 0;
402
403 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
404
405 KeQuerySystemTime(&EndTime);
406 EndTime.QuadPart += 100 * 10000; // 100 ms
407
408 HcStatus.AsUSHORT = READ_PORT_USHORT(StatusRegister);
409 DPRINT("UhciTakeControlHC: HcStatus.AsUSHORT - %04X\n", HcStatus.AsUSHORT);
410
411 while (HcStatus.HcHalted == 0)
412 {
413 HcStatus.AsUSHORT = READ_PORT_USHORT(StatusRegister);
414 KeQuerySystemTime(&CurrentTime);
415
416 if (CurrentTime.QuadPart >= EndTime.QuadPart)
417 break;
418 }
419
420 WRITE_PORT_USHORT(StatusRegister, UHCI_USB_STATUS_MASK);
421
422 LegacyMask.AsUSHORT = 0;
423 LegacyMask.Smi60Read = 1;
424 LegacyMask.Smi60Write = 1;
425 LegacyMask.Smi64Read = 1;
426 LegacyMask.Smi64Write = 1;
427 LegacyMask.SmiIrq = 1;
428 LegacyMask.A20Gate = 1;
429 LegacyMask.SmiEndPassThrough = 1;
430
431 if (LegacySupport.AsUSHORT & LegacyMask.AsUSHORT)
432 {
433 DPRINT("UhciTakeControlHC: LegacySupport.AsUSHORT - %04X\n",
434 LegacySupport.AsUSHORT);
435
436 Resources->LegacySupport = 1;
437
438 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
439 TRUE,
440 &LegacySupport.AsUSHORT,
441 PCI_LEGSUP,
442 sizeof(USHORT));
443 LegacySupport.AsUSHORT = 0;
444
445 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
446 FALSE,
447 &LegacySupport.AsUSHORT,
448 PCI_LEGSUP,
449 sizeof(USHORT));
450 }
451
452 return MpStatus;
453 }
454
455 MPSTATUS
456 NTAPI
457 UhciInitializeHardware(IN PUHCI_EXTENSION UhciExtension)
458 {
459 PUHCI_HW_REGISTERS BaseRegister;
460 UHCI_USB_COMMAND Command;
461 UHCI_USB_STATUS StatusMask;
462
463 DPRINT("UhciInitializeHardware: UhciExtension - %p\n", UhciExtension);
464 DPRINT("UhciInitializeHardware: VIA HW FIXME\n"); // after supporting HcFlavor in usbport
465
466 BaseRegister = UhciExtension->BaseRegister;
467
468 /* Save SOF Timing Value */
469 UhciExtension->SOF_Modify = READ_PORT_UCHAR(&BaseRegister->SOF_Modify);
470
471 RegPacket.UsbPortWait(UhciExtension, 20);
472
473 Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT);
474
475 /* Global Reset */
476 Command.AsUSHORT = 0;
477 Command.GlobalReset = 1;
478 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
479
480 RegPacket.UsbPortWait(UhciExtension, 20);
481
482 Command.AsUSHORT = 0;
483 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
484
485 /* Set MaxPacket for full speed bandwidth reclamation */
486 Command.AsUSHORT = 0;
487 Command.MaxPacket = 1; // 64 bytes
488 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
489
490 /* Restore SOF Timing Value */
491 WRITE_PORT_UCHAR(&BaseRegister->SOF_Modify, UhciExtension->SOF_Modify);
492
493 StatusMask = UhciExtension->StatusMask;
494
495 StatusMask.Interrupt = 1;
496 StatusMask.ErrorInterrupt = 1;
497 StatusMask.ResumeDetect = 1;
498 StatusMask.HostSystemError = 1;
499
500 UhciExtension->StatusMask = StatusMask;
501
502 return MP_STATUS_SUCCESS;
503 }
504
505 MPSTATUS
506 NTAPI
507 UhciInitializeSchedule(IN PUHCI_EXTENSION UhciExtension,
508 IN PUHCI_HC_RESOURCES HcResourcesVA,
509 IN ULONG hcResourcesPA)
510 {
511 PUHCI_HCD_QH IntQH;
512 ULONG IntQhPA;
513 PUHCI_HCD_QH StaticControlHead;
514 ULONG StaticControlHeadPA;
515 PUHCI_HCD_QH StaticBulkHead;
516 ULONG StaticBulkHeadPA;
517 PUHCI_HCD_TD StaticBulkTD;
518 ULONG StaticBulkTdPA;
519 PUHCI_HCD_TD StaticTD;
520 ULONG StaticTdPA;
521 PUHCI_HCD_TD StaticSofTD;
522 ULONG StaticSofTdPA;
523 ULONG PhysicalAddress;
524 ULONG Idx;
525 ULONG HeadIdx;
526 UCHAR FrameIdx;
527
528 DPRINT("UhciInitializeSchedule: Ext[%p], VA - %p, PA - %lx\n",
529 UhciExtension,
530 HcResourcesVA,
531 hcResourcesPA);
532
533 /* Build structure (tree) of static QHs
534 for interrupt and isochronous transfers */
535 for (FrameIdx = 0; FrameIdx < INTERRUPT_ENDPOINTs; FrameIdx++)
536 {
537 IntQH = &HcResourcesVA->StaticIntHead[FrameIdx];
538 IntQhPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticIntHead[FrameIdx]);
539
540 RtlZeroMemory(IntQH, sizeof(UHCI_HCD_QH));
541
542 IntQH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
543 IntQH->PhysicalAddress = IntQhPA;
544
545 UhciExtension->IntQH[FrameIdx] = IntQH;
546
547 if (FrameIdx == 0)
548 UhciSetNextQH(IntQH, UhciExtension->IntQH[0]);
549 else
550 UhciSetNextQH(IntQH, UhciExtension->IntQH[(FrameIdx - 1) / 2]);
551 }
552
553 /* Initialize static QH for control transfers */
554 StaticControlHead = &HcResourcesVA->StaticControlHead;
555 StaticControlHeadPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticControlHead);
556
557 RtlZeroMemory(StaticControlHead, sizeof(UHCI_HCD_QH));
558
559 StaticControlHead->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
560 StaticControlHead->PhysicalAddress = StaticControlHeadPA;
561
562 UhciSetNextQH(UhciExtension->IntQH[0],StaticControlHead);
563
564 UhciExtension->ControlQH = StaticControlHead;
565
566 /* Initialize static QH for bulk transfers */
567 StaticBulkHead = &HcResourcesVA->StaticBulkHead;
568 StaticBulkHeadPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticBulkHead);
569
570 RtlZeroMemory(StaticBulkHead, sizeof(UHCI_HCD_QH));
571
572 StaticBulkHead->PhysicalAddress = StaticBulkHeadPA;
573 PhysicalAddress = StaticBulkHeadPA | UHCI_QH_ELEMENT_LINK_PTR_QH;
574 PhysicalAddress |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
575 StaticBulkHead->HwQH.NextQH = PhysicalAddress;
576
577 UhciSetNextQH(StaticControlHead, StaticBulkHead);
578
579 UhciExtension->BulkQH = StaticBulkHead;
580 UhciExtension->BulkTailQH = StaticBulkHead;
581
582 /* Initialize static TD for bulk transfers */
583 StaticBulkTD = &HcResourcesVA->StaticBulkTD;
584 StaticBulkTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticBulkTD);
585
586 StaticBulkTD->HwTD.NextElement = StaticBulkTdPA | UHCI_TD_LINK_PTR_TD;
587
588 StaticBulkTD->HwTD.ControlStatus.AsULONG = 0;
589 StaticBulkTD->HwTD.ControlStatus.IsochronousType = 1;
590
591 StaticBulkTD->HwTD.Token.AsULONG = 0;
592 StaticBulkTD->HwTD.Token.Endpoint = 1;
593 StaticBulkTD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL;
594 StaticBulkTD->HwTD.Token.PIDCode = UHCI_TD_PID_OUT;
595
596 StaticBulkTD->HwTD.Buffer = 0;
597
598 StaticBulkTD->PhysicalAddress = StaticBulkTdPA;
599 StaticBulkTD->NextHcdTD = NULL;
600 StaticBulkTD->Flags = UHCI_HCD_TD_FLAG_PROCESSED;
601
602 PhysicalAddress = StaticBulkTdPA | UHCI_QH_ELEMENT_LINK_PTR_TD;
603 UhciExtension->BulkQH->HwQH.NextElement = PhysicalAddress;
604
605 /* Set Frame List pointers */
606 for (Idx = 0; Idx < UHCI_FRAME_LIST_MAX_ENTRIES; Idx++)
607 {
608 HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms) +
609 (Idx & (ENDPOINT_INTERRUPT_32ms - 1));
610
611 PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress;
612 PhysicalAddress |= UHCI_FRAME_LIST_POINTER_QH;
613 HcResourcesVA->FrameList[Idx] = PhysicalAddress;
614 }
615
616 /* Initialize static TD for first frame */
617 StaticTD = &HcResourcesVA->StaticTD;
618 StaticTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticTD);
619
620 RtlZeroMemory(StaticTD, sizeof(UHCI_HCD_TD));
621
622 StaticTD->PhysicalAddress = StaticTdPA;
623
624 HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms);
625 PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress;
626 StaticTD->HwTD.NextElement = PhysicalAddress | UHCI_TD_LINK_PTR_QH;
627
628 StaticTD->HwTD.ControlStatus.InterruptOnComplete = 1;
629 StaticTD->HwTD.Token.PIDCode = UHCI_TD_PID_IN;
630
631 UhciExtension->StaticTD = StaticTD;
632
633 /* Initialize StaticSofTDs for UhciInterruptNextSOF() */
634 UhciExtension->SOF_HcdTDs = &HcResourcesVA->StaticSofTD[0];
635 StaticSofTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticSofTD[0]);
636
637 for (Idx = 0; Idx < UHCI_MAX_STATIC_SOF_TDS; Idx++)
638 {
639 StaticSofTD = UhciExtension->SOF_HcdTDs + Idx;
640
641 RtlZeroMemory(StaticSofTD, sizeof(UHCI_HCD_TD));
642
643 PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress;
644 StaticSofTD->HwTD.NextElement = PhysicalAddress | UHCI_TD_LINK_PTR_QH;
645
646 StaticSofTD->HwTD.ControlStatus.InterruptOnComplete = 1;
647 StaticSofTD->PhysicalAddress = StaticSofTdPA;
648
649 StaticSofTdPA += sizeof(UHCI_HCD_TD);
650 }
651
652 return MP_STATUS_SUCCESS;
653 }
654
655 MPSTATUS
656 NTAPI
657 UhciStartController(IN PVOID uhciExtension,
658 IN PUSBPORT_RESOURCES Resources)
659 {
660 PUHCI_EXTENSION UhciExtension = uhciExtension;
661 PUHCI_HW_REGISTERS BaseRegister;
662 MPSTATUS MpStatus;
663 PUSHORT PortControlRegister;
664 UHCI_PORT_STATUS_CONTROL PortControl;
665 UHCI_USB_COMMAND Command;
666 USHORT Port;
667
668 UhciExtension->Flags &= ~UHCI_EXTENSION_FLAG_SUSPENDED;
669 UhciExtension->BaseRegister = Resources->ResourceBase;
670 BaseRegister = UhciExtension->BaseRegister;
671 DPRINT("UhciStartController: UhciExtension - %p, BaseRegister - %p\n", UhciExtension, BaseRegister);
672
673 UhciExtension->HcFlavor = Resources->HcFlavor;
674
675 MpStatus = UhciTakeControlHC(UhciExtension, Resources);
676
677 if (MpStatus == MP_STATUS_SUCCESS)
678 {
679 MpStatus = UhciInitializeHardware(UhciExtension);
680
681 if (MpStatus == MP_STATUS_SUCCESS)
682 {
683 UhciExtension->HcResourcesVA = (PUHCI_HC_RESOURCES)Resources->StartVA;
684 UhciExtension->HcResourcesPA = Resources->StartPA;
685
686 MpStatus = UhciInitializeSchedule(UhciExtension,
687 UhciExtension->HcResourcesVA,
688 UhciExtension->HcResourcesPA);
689
690 UhciExtension->LockFrameList = 0;
691 }
692 }
693
694 WRITE_PORT_ULONG(&BaseRegister->FrameAddress,
695 UhciExtension->HcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, FrameList));
696
697 if (MpStatus == MP_STATUS_SUCCESS)
698 {
699 Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT);
700 Command.Run = 1;
701 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
702
703 for (Port = 0; Port < UHCI_NUM_ROOT_HUB_PORTS; Port++)
704 {
705 PortControlRegister = &BaseRegister->PortControl[Port].AsUSHORT;
706 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
707
708 PortControl.ConnectStatusChange = 0;
709 PortControl.Suspend = 0;
710
711 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
712 }
713
714 UhciExtension->HcResourcesVA->FrameList[0] =
715 UhciExtension->StaticTD->PhysicalAddress;
716 }
717
718 return MP_STATUS_SUCCESS;
719 }
720
721 VOID
722 NTAPI
723 UhciStopController(IN PVOID uhciExtension,
724 IN BOOLEAN IsDoDisableInterrupts)
725 {
726 PUHCI_EXTENSION UhciExtension = uhciExtension;
727 PUHCI_HW_REGISTERS BaseRegister;
728 PUSHORT CommandReg;
729 UHCI_USB_COMMAND Command;
730 LARGE_INTEGER EndTime;
731 LARGE_INTEGER CurrentTime;
732
733 DPRINT("UhciStopController: UhciExtension - %p\n", UhciExtension);
734
735 BaseRegister = UhciExtension->BaseRegister;
736 CommandReg = &BaseRegister->HcCommand.AsUSHORT;
737
738 Command.AsUSHORT = READ_PORT_USHORT(CommandReg);
739
740 if (Command.AsUSHORT == 0xFFFF)
741 {
742 DPRINT("UhciStopController: Command == -1\n");
743 return;
744 }
745
746 DPRINT("UhciStopController: Command.AsUSHORT - %p\n", Command.AsUSHORT);
747
748 if (Command.GlobalReset)
749 {
750 Command.GlobalReset = 0;
751 WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT);
752 }
753
754 Command.HcReset = 1;
755
756 WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT);
757
758 KeQuerySystemTime(&EndTime);
759 EndTime.QuadPart += 100 * 1000;
760
761 while (Command.AsUSHORT = READ_PORT_USHORT(CommandReg),
762 Command.HcReset == 1)
763 {
764 KeQuerySystemTime(&CurrentTime);
765
766 if (CurrentTime.QuadPart >= EndTime.QuadPart)
767 {
768 DPRINT1("UhciStopController: Failed to reset\n");
769 DbgBreakPoint();
770 break;
771 }
772 }
773 }
774
775 VOID
776 NTAPI
777 UhciSuspendController(IN PVOID uhciExtension)
778 {
779 DPRINT_IMPL("UhciSuspendController: UNIMPLEMENTED. FIXME\n");
780 }
781
782 MPSTATUS
783 NTAPI
784 UhciResumeController(IN PVOID uhciExtension)
785 {
786 DPRINT_IMPL("UhciResumeController: UNIMPLEMENTED. FIXME\n");
787 return MP_STATUS_SUCCESS;
788 }
789
790 BOOLEAN
791 NTAPI
792 UhciHardwarePresent(IN PUHCI_EXTENSION UhciExtension)
793 {
794 UHCI_USB_STATUS UhciStatus;
795 PUSHORT StatusReg;
796
797 StatusReg = &UhciExtension->BaseRegister->HcStatus.AsUSHORT;
798 UhciStatus.AsUSHORT = READ_PORT_USHORT(StatusReg);
799
800 if (UhciStatus.AsUSHORT == MAXUSHORT)
801 DPRINT_UHCI("UhciHardwarePresent: HW not present\n");
802
803 return UhciStatus.AsUSHORT != MAXUSHORT;
804 }
805
806 BOOLEAN
807 NTAPI
808 UhciInterruptService(IN PVOID uhciExtension)
809 {
810 PUHCI_EXTENSION UhciExtension = uhciExtension;
811 PUHCI_HW_REGISTERS BaseRegister;
812 PUSHORT CommandReg;
813 UHCI_USB_COMMAND Command;
814 PUSHORT StatusReg;
815 UHCI_USB_STATUS HcStatus;
816 PUSHORT InterruptEnableReg;
817 PUHCI_HCD_QH QH;
818 PUHCI_HCD_QH BulkTailQH;
819 ULONG ScheduleError;
820 BOOLEAN Result = FALSE;
821
822 BaseRegister = UhciExtension->BaseRegister;
823 StatusReg = &BaseRegister->HcStatus.AsUSHORT;
824 InterruptEnableReg = &BaseRegister->HcInterruptEnable.AsUSHORT;
825 CommandReg = &BaseRegister->HcCommand.AsUSHORT;
826
827 if (!UhciHardwarePresent(UhciExtension))
828 {
829 DPRINT1("UhciInterruptService: return FALSE\n");
830 return FALSE;
831 }
832
833 HcStatus.AsUSHORT = READ_PORT_USHORT(StatusReg) & UHCI_USB_STATUS_MASK;
834
835 if (HcStatus.HostSystemError || HcStatus.HcProcessError)
836 {
837 DPRINT1("UhciInterruptService: Error [%p] HcStatus %X\n",
838 UhciExtension,
839 HcStatus.AsUSHORT);
840 }
841 else if (HcStatus.AsUSHORT)
842 {
843 UhciExtension->HcScheduleError = 0;
844 }
845
846 if (HcStatus.HcProcessError)
847 {
848 USHORT fn = READ_PORT_USHORT(&BaseRegister->FrameNumber);
849 USHORT intr = READ_PORT_USHORT(InterruptEnableReg);
850 USHORT cmd = READ_PORT_USHORT(CommandReg);
851
852 DPRINT1("UhciInterruptService: HC ProcessError!\n");
853 DPRINT1("UhciExtension %p, frame %X\n", UhciExtension, fn);
854 DPRINT1("HcCommand %X\n", cmd);
855 DPRINT1("HcStatus %X\n", HcStatus.AsUSHORT);
856 DPRINT1("HcInterruptEnable %X\n", intr);
857
858 DbgBreakPoint();
859 }
860
861 if (HcStatus.HcHalted)
862 {
863 DPRINT_UHCI("UhciInterruptService: Hc Halted [%p] HcStatus %X\n",
864 UhciExtension,
865 HcStatus.AsUSHORT);
866 }
867 else if (HcStatus.AsUSHORT)
868 {
869 UhciExtension->HcStatus.AsUSHORT = HcStatus.AsUSHORT;
870
871 WRITE_PORT_USHORT(StatusReg, HcStatus.AsUSHORT);
872 WRITE_PORT_USHORT(InterruptEnableReg, 0);
873
874 if (HcStatus.HostSystemError)
875 {
876 DPRINT1("UhciInterruptService: HostSystemError! HcStatus - %X\n",
877 HcStatus.AsUSHORT);
878
879 DbgBreakPoint();
880 }
881
882 Result = TRUE;
883 }
884
885 if (!HcStatus.Interrupt)
886 goto NextProcess;
887
888 UhciUpdateCounter(UhciExtension);
889
890 BulkTailQH = UhciExtension->BulkTailQH;
891
892 if (BulkTailQH->HwQH.NextQH & UHCI_QH_HEAD_LINK_PTR_TERMINATE)
893 goto NextProcess;
894
895 QH = UhciExtension->BulkQH;
896
897 do
898 {
899 QH = QH->NextHcdQH;
900
901 if (!QH)
902 {
903 BulkTailQH->HwQH.NextQH |= UHCI_QH_HEAD_LINK_PTR_TERMINATE;
904 goto NextProcess;
905 }
906 }
907 while (QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_PTR_TERMINATE);
908
909 NextProcess:
910
911 if (HcStatus.HcProcessError)
912 {
913 UhciCleanupFrameList(UhciExtension, TRUE);
914
915 ScheduleError = UhciExtension->HcScheduleError;
916 UhciExtension->HcScheduleError = ScheduleError + 1;
917
918 DPRINT1("UhciInterruptService: [%p] ScheduleError %X\n",
919 UhciExtension,
920 ScheduleError);
921
922 if (ScheduleError < UHCI_MAX_HC_SCHEDULE_ERRORS)
923 {
924 Command.AsUSHORT = READ_PORT_USHORT(CommandReg);
925 Command.Run = 1;
926 WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT);
927 }
928 }
929 else if (HcStatus.Interrupt && UhciExtension->ExtensionLock)
930 {
931 DPRINT1("UhciInterruptService: [%p] HcStatus %X\n",
932 UhciExtension,
933 HcStatus.AsUSHORT);
934
935 UhciCleanupFrameList(UhciExtension, FALSE);
936 }
937
938 return Result;
939 }
940
941 VOID
942 NTAPI
943 UhciInterruptDpc(IN PVOID uhciExtension,
944 IN BOOLEAN IsDoEnableInterrupts)
945 {
946 PUHCI_EXTENSION UhciExtension = uhciExtension;
947 PUHCI_HW_REGISTERS BaseRegister;
948 UHCI_USB_STATUS HcStatus;
949
950 DPRINT_UHCI("UhciInterruptDpc: [%p] EnableInt %x, HcStatus %X\n",
951 uhciExtension, IsDoEnableInterrupts, UhciExtension->HcStatus);
952
953 BaseRegister = UhciExtension->BaseRegister;
954
955 HcStatus = UhciExtension->HcStatus;
956 UhciExtension->HcStatus.AsUSHORT = 0;
957
958 if ((HcStatus.Interrupt | HcStatus.ErrorInterrupt) != 0)
959 RegPacket.UsbPortInvalidateEndpoint(UhciExtension, 0);
960
961 if (IsDoEnableInterrupts)
962 {
963 WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT,
964 UhciExtension->StatusMask.AsUSHORT);
965 }
966 }
967
968 VOID
969 NTAPI
970 UhciQueueTransfer(IN PUHCI_EXTENSION UhciExtension,
971 IN PUHCI_ENDPOINT UhciEndpoint,
972 IN PUHCI_HCD_TD FirstTD,
973 IN PUHCI_HCD_TD LastTD)
974 {
975 PUHCI_HCD_QH QH;
976 PUHCI_HCD_QH BulkTailQH;
977 PUHCI_HCD_TD TailTD;
978 ULONG PhysicalAddress;
979
980 DPRINT("UhciQueueTransfer: FirstTD - %p, LastTD - %p\n", FirstTD, LastTD);
981
982 TailTD = UhciEndpoint->TailTD;
983 QH = UhciEndpoint->QH;
984
985 if (UhciEndpoint->HeadTD)
986 {
987 TailTD->NextHcdTD = FirstTD;
988
989 TailTD->HwTD.NextElement = FirstTD->PhysicalAddress;
990 TailTD->HwTD.NextElement |= UHCI_TD_LINK_PTR_TD;
991
992 PhysicalAddress = QH->HwQH.NextElement;
993
994 PhysicalAddress &= ~(UHCI_TD_LINK_PTR_TERMINATE |
995 UHCI_TD_LINK_PTR_QH |
996 UHCI_TD_LINK_PTR_DEPTH_FIRST);
997
998 if (FirstTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE)
999 {
1000 if (PhysicalAddress == TailTD->PhysicalAddress &&
1001 !(TailTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE))
1002 {
1003 QH->HwQH.NextElement = FirstTD->PhysicalAddress;
1004
1005 QH->HwQH.NextElement &= ~(UHCI_QH_ELEMENT_LINK_PTR_TERMINATE |
1006 UHCI_QH_ELEMENT_LINK_PTR_QH);
1007 }
1008 }
1009 }
1010 else
1011 {
1012 if (FirstTD)
1013 {
1014 UhciEndpoint->HeadTD = FirstTD;
1015 }
1016 else
1017 {
1018 UhciEndpoint->TailTD = NULL;
1019 UhciEndpoint->HeadTD = NULL;
1020 }
1021
1022 if (FirstTD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
1023 {
1024 PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
1025 }
1026 else
1027 {
1028 PhysicalAddress = FirstTD->PhysicalAddress;
1029 PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
1030 }
1031
1032 QH->HwQH.NextElement = PhysicalAddress & ~UHCI_QH_ELEMENT_LINK_PTR_QH;
1033 }
1034
1035 if (UhciEndpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_BULK)
1036 {
1037 BulkTailQH = UhciExtension->BulkTailQH;
1038 BulkTailQH->HwQH.NextQH &= ~UHCI_QH_HEAD_LINK_PTR_TERMINATE;
1039 }
1040
1041 UhciEndpoint->TailTD = LastTD;
1042 }
1043
1044 PUHCI_HCD_TD
1045 NTAPI
1046 UhciAllocateTD(IN PUHCI_EXTENSION UhciExtension,
1047 IN PUHCI_ENDPOINT UhciEndpoint)
1048 {
1049 PUHCI_HCD_TD TD;
1050 ULONG AllocTdCounter;
1051 ULONG ix;
1052
1053 DPRINT_UHCI("UhciAllocateTD: ...\n");
1054
1055 AllocTdCounter = UhciEndpoint->AllocTdCounter;
1056
1057 for (ix = 0; ix < UhciEndpoint->MaxTDs; ++ix)
1058 {
1059 TD = &UhciEndpoint->FirstTD[AllocTdCounter];
1060
1061 if (!(TD->Flags & UHCI_HCD_TD_FLAG_ALLOCATED))
1062 {
1063 TD->Flags |= UHCI_HCD_TD_FLAG_ALLOCATED;
1064
1065 UhciEndpoint->AllocatedTDs++;
1066 UhciEndpoint->AllocTdCounter = AllocTdCounter;
1067
1068 return TD;
1069 }
1070
1071 if (AllocTdCounter < UhciEndpoint->MaxTDs - 1)
1072 AllocTdCounter++;
1073 else
1074 AllocTdCounter = 0;
1075 }
1076
1077 return NULL;
1078 }
1079
1080 VOID
1081 NTAPI
1082 UhciMapAsyncTransferToTDs(IN PUHCI_EXTENSION UhciExtension,
1083 IN PUHCI_ENDPOINT UhciEndpoint,
1084 IN PUHCI_TRANSFER UhciTransfer,
1085 OUT PUHCI_HCD_TD * OutFirstTD,
1086 OUT PUHCI_HCD_TD * OutLastTD,
1087 IN PUSBPORT_SCATTER_GATHER_LIST SgList)
1088 {
1089 PUHCI_HCD_TD TD;
1090 PUHCI_HCD_TD LastTD = NULL;
1091 ULONG PhysicalAddress;
1092 USHORT TotalMaxPacketSize;
1093 USHORT DeviceSpeed;
1094 USHORT EndpointAddress;
1095 USHORT DeviceAddress;
1096 ULONG TransferType;
1097 SIZE_T TransferLength = 0;
1098 SIZE_T LengthMapped = 0;
1099 SIZE_T BytesRemaining;
1100 SIZE_T LengthThisTD;
1101 ULONG ix;
1102 BOOL DataToggle;
1103 UCHAR PIDCode;
1104 BOOLEAN IsLastTd = TRUE;
1105 BOOLEAN ZeroLengthTransfer = TRUE;
1106
1107 DPRINT_UHCI("UhciMapAsyncTransferToTDs: ...\n");
1108
1109 TotalMaxPacketSize = UhciEndpoint->EndpointProperties.TotalMaxPacketSize;
1110 DeviceSpeed = UhciEndpoint->EndpointProperties.DeviceSpeed;
1111 EndpointAddress = UhciEndpoint->EndpointProperties.EndpointAddress;
1112 DeviceAddress = UhciEndpoint->EndpointProperties.DeviceAddress;
1113 TransferType = UhciEndpoint->EndpointProperties.TransferType;
1114
1115 if (SgList->SgElementCount || TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
1116 ZeroLengthTransfer = FALSE;
1117
1118 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
1119 {
1120 if (UhciTransfer->TransferParameters->TransferFlags &
1121 USBD_TRANSFER_DIRECTION_IN)
1122 {
1123 PIDCode = UHCI_TD_PID_IN;
1124 }
1125 else
1126 {
1127 PIDCode = UHCI_TD_PID_OUT;
1128 }
1129
1130 DataToggle = UHCI_TD_PID_DATA1;
1131 }
1132 else
1133 {
1134 if (USB_ENDPOINT_DIRECTION_OUT(EndpointAddress))
1135 PIDCode = UHCI_TD_PID_OUT;
1136 else
1137 PIDCode = UHCI_TD_PID_IN;
1138
1139 DataToggle = UhciEndpoint->DataToggle;
1140 }
1141
1142 for (ix = 0; ix < SgList->SgElementCount || ZeroLengthTransfer; ix++)
1143 {
1144 BytesRemaining = SgList->SgElement[ix].SgTransferLength;
1145 PhysicalAddress = SgList->SgElement[ix].SgPhysicalAddress.LowPart;
1146
1147 if (!IsLastTd)
1148 {
1149 PhysicalAddress += TransferLength;
1150 BytesRemaining -= TransferLength;
1151 }
1152
1153 IsLastTd = TRUE;
1154 TransferLength = 0;
1155
1156 while (BytesRemaining || ZeroLengthTransfer)
1157 {
1158 ZeroLengthTransfer = FALSE;
1159
1160 if (BytesRemaining >= TotalMaxPacketSize)
1161 {
1162 LengthThisTD = TotalMaxPacketSize;
1163 BytesRemaining -= TotalMaxPacketSize;
1164 }
1165 else
1166 {
1167 if (ix >= SgList->SgElementCount - 1)
1168 {
1169 LengthThisTD = BytesRemaining;
1170 }
1171 else
1172 {
1173 IsLastTd = FALSE;
1174
1175 DPRINT1("UhciMapAsyncTransferToTds: IsLastTd = FALSE. FIXME\n");
1176 ASSERT(FALSE);
1177 }
1178
1179 BytesRemaining = 0;
1180 }
1181
1182 UhciTransfer->PendingTds++;
1183 TD = UhciAllocateTD(UhciExtension, UhciEndpoint);
1184 TD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED;
1185
1186 TD->HwTD.NextElement = 0;
1187 TD->HwTD.Buffer = PhysicalAddress;
1188
1189 TD->HwTD.ControlStatus.AsULONG = 0;
1190 TD->HwTD.ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed);
1191 TD->HwTD.ControlStatus.Status = UHCI_TD_STS_ACTIVE;
1192 TD->HwTD.ControlStatus.ErrorCounter = 3;
1193 TD->HwTD.ControlStatus.ActualLength = UHCI_TD_LENGTH_NULL;
1194 TD->HwTD.ControlStatus.ShortPacketDetect = 1;
1195
1196 TD->HwTD.Token.AsULONG = 0;
1197 TD->HwTD.Token.Endpoint = EndpointAddress;
1198 TD->HwTD.Token.DeviceAddress = DeviceAddress;
1199 TD->HwTD.Token.PIDCode = PIDCode;
1200
1201 if (LengthThisTD == 0)
1202 TD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL;
1203 else
1204 TD->HwTD.Token.MaximumLength = LengthThisTD - 1;
1205
1206 TD->HwTD.Token.DataToggle = (DataToggle == UHCI_TD_PID_DATA1);
1207
1208 TD->NextHcdTD = 0;
1209 TD->UhciTransfer = UhciTransfer;
1210
1211 if (!IsLastTd)
1212 ASSERT(FALSE);
1213
1214 PhysicalAddress += LengthThisTD;
1215 LengthMapped += LengthThisTD;
1216
1217 if (LastTD)
1218 {
1219 LastTD->HwTD.NextElement = TD->PhysicalAddress &
1220 UHCI_TD_LINK_POINTER_MASK;
1221 LastTD->NextHcdTD = TD;
1222 }
1223 else
1224 {
1225 *OutFirstTD = TD;
1226 }
1227
1228 LastTD = TD;
1229 DataToggle = DataToggle == UHCI_TD_PID_DATA0;
1230 }
1231 }
1232
1233 UhciEndpoint->DataToggle = DataToggle;
1234
1235 *OutLastTD = LastTD;
1236 }
1237
1238 MPSTATUS
1239 NTAPI
1240 UhciControlTransfer(IN PUHCI_EXTENSION UhciExtension,
1241 IN PUHCI_ENDPOINT UhciEndpoint,
1242 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
1243 IN PUHCI_TRANSFER UhciTransfer,
1244 IN PUSBPORT_SCATTER_GATHER_LIST SgList)
1245 {
1246 PUHCI_HCD_TD FirstTD;
1247 PUHCI_HCD_TD LastTD;
1248 PUHCI_HCD_TD DataFirstTD;
1249 PUHCI_HCD_TD DataLastTD;
1250 UHCI_CONTROL_STATUS ControlStatus;
1251 USB_DEVICE_SPEED DeviceSpeed;
1252 USHORT EndpointAddress;
1253 USHORT DeviceAddress;
1254 ULONG PhysicalAddress;
1255
1256 DPRINT_UHCI("UhciControlTransfer: UhciTransfer - %p\n", UhciTransfer);
1257
1258 if (UhciEndpoint->EndpointLock > 1)
1259 {
1260 InterlockedDecrement(&UhciEndpoint->EndpointLock);
1261
1262 if (UhciEndpoint->EndpointProperties.TransferType ==
1263 USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1264 {
1265 InterlockedDecrement(&UhciExtension->ExtensionLock);
1266 }
1267
1268 DPRINT("UhciControlTransfer: end MP_STATUS_FAILURE\n");
1269 return MP_STATUS_FAILURE;
1270 }
1271
1272 DeviceSpeed = UhciEndpoint->EndpointProperties.DeviceSpeed;
1273 EndpointAddress = UhciEndpoint->EndpointProperties.EndpointAddress;
1274 DeviceAddress = UhciEndpoint->EndpointProperties.DeviceAddress;
1275
1276 /* Allocate and setup first TD */
1277 UhciTransfer->PendingTds++;
1278 FirstTD = UhciAllocateTD(UhciExtension, UhciEndpoint);
1279 FirstTD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED;
1280 DPRINT_UHCI("UhciControlTransfer: FirstTD - %p\n", FirstTD);
1281
1282 FirstTD->HwTD.NextElement = 0;
1283
1284 ControlStatus.AsULONG = 0;
1285 ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed);
1286 ControlStatus.Status |= UHCI_TD_STS_ACTIVE;
1287 ControlStatus.ErrorCounter = 3;
1288 FirstTD->HwTD.ControlStatus = ControlStatus;
1289
1290 FirstTD->HwTD.Token.AsULONG = 0;
1291 FirstTD->HwTD.Token.Endpoint = EndpointAddress;
1292 FirstTD->HwTD.Token.DeviceAddress = DeviceAddress;
1293
1294 FirstTD->HwTD.Token.MaximumLength = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
1295 FirstTD->HwTD.Token.MaximumLength--;
1296 FirstTD->HwTD.Token.PIDCode = UHCI_TD_PID_SETUP;
1297 FirstTD->HwTD.Token.DataToggle = UHCI_TD_PID_DATA0;
1298
1299 RtlCopyMemory(&FirstTD->SetupPacket,
1300 &TransferParameters->SetupPacket,
1301 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1302
1303 FirstTD->HwTD.Buffer = FirstTD->PhysicalAddress + FIELD_OFFSET(UHCI_HCD_TD, SetupPacket);
1304
1305 FirstTD->NextHcdTD = NULL;
1306 FirstTD->UhciTransfer = UhciTransfer;
1307
1308 /* Allocate and setup last TD */
1309 UhciTransfer->PendingTds++;
1310 LastTD = UhciAllocateTD(UhciExtension, UhciEndpoint);
1311 LastTD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED;
1312 DPRINT_UHCI("UhciControlTransfer: LastTD - %p\n", LastTD);
1313
1314 LastTD->HwTD.NextElement = 0;
1315
1316 LastTD->HwTD.ControlStatus.AsULONG = 0;
1317 LastTD->HwTD.ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed);
1318 LastTD->HwTD.ControlStatus.Status |= UHCI_TD_STS_ACTIVE;
1319 LastTD->HwTD.ControlStatus.ErrorCounter = 3;
1320
1321 LastTD->HwTD.Token.AsULONG = 0;
1322 LastTD->HwTD.Token.Endpoint = EndpointAddress;
1323 LastTD->HwTD.Token.DeviceAddress = DeviceAddress;
1324
1325 LastTD->UhciTransfer = UhciTransfer;
1326 LastTD->NextHcdTD = NULL;
1327
1328 /* Allocate and setup TDs for data */
1329 DataFirstTD = NULL;
1330 DataLastTD = NULL;
1331
1332 UhciMapAsyncTransferToTDs(UhciExtension,
1333 UhciEndpoint,
1334 UhciTransfer,
1335 &DataFirstTD,
1336 &DataLastTD,
1337 SgList);
1338
1339 if (DataFirstTD)
1340 {
1341 PhysicalAddress = DataFirstTD->PhysicalAddress;
1342 PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK;
1343 FirstTD->HwTD.NextElement = PhysicalAddress;
1344 FirstTD->NextHcdTD = DataFirstTD;
1345
1346 PhysicalAddress = LastTD->PhysicalAddress;
1347 PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK;
1348 DataLastTD->HwTD.NextElement = PhysicalAddress;
1349 DataLastTD->NextHcdTD = LastTD;
1350 }
1351 else
1352 {
1353 PhysicalAddress = LastTD->PhysicalAddress;
1354 PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK;
1355 FirstTD->HwTD.NextElement = PhysicalAddress;
1356 FirstTD->NextHcdTD = LastTD;
1357 }
1358
1359 LastTD->HwTD.Buffer = 0;
1360 LastTD->HwTD.ControlStatus.InterruptOnComplete = 1;
1361
1362 LastTD->HwTD.Token.DataToggle = UHCI_TD_PID_DATA1;
1363 LastTD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL;
1364
1365 if (UhciTransfer->TransferParameters->TransferFlags &
1366 USBD_TRANSFER_DIRECTION_IN)
1367 {
1368 LastTD->HwTD.Token.PIDCode = UHCI_TD_PID_OUT;
1369 }
1370 else
1371 {
1372 LastTD->HwTD.Token.PIDCode = UHCI_TD_PID_IN;
1373 }
1374
1375 LastTD->HwTD.NextElement = UHCI_TD_LINK_PTR_TERMINATE;
1376
1377 LastTD->Flags |= UHCI_HCD_TD_FLAG_CONTROLL;
1378 LastTD->NextHcdTD = NULL;
1379
1380 /* Link this transfer to queue */
1381 UhciQueueTransfer(UhciExtension, UhciEndpoint, FirstTD, LastTD);
1382
1383 DPRINT_UHCI("UhciControlTransfer: end MP_STATUS_SUCCESS\n");
1384 return MP_STATUS_SUCCESS;
1385 }
1386
1387 MPSTATUS
1388 NTAPI
1389 UhciBulkOrInterruptTransfer(IN PUHCI_EXTENSION UhciExtension,
1390 IN PUHCI_ENDPOINT UhciEndpoint,
1391 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
1392 IN PUHCI_TRANSFER UhciTransfer,
1393 IN PUSBPORT_SCATTER_GATHER_LIST SgList)
1394 {
1395 PUHCI_HCD_TD DataFirstTD;
1396 PUHCI_HCD_TD DataLastTD;
1397 ULONG TotalMaxPacketSize;
1398 ULONG SgCount;
1399 ULONG TransferLength;
1400 ULONG TDs;
1401 ULONG ix;
1402
1403 DPRINT_UHCI("UhciBulkOrInterruptTransfer: ...\n");
1404
1405 TotalMaxPacketSize = UhciEndpoint->EndpointProperties.TotalMaxPacketSize;
1406
1407 SgCount = SgList->SgElementCount;
1408
1409 if (SgCount == 0)
1410 {
1411 DPRINT("UhciBulkOrInterruptTransfer: SgCount == 0 \n");
1412 TDs = 1;
1413 }
1414 else
1415 {
1416 TransferLength = 0;
1417
1418 for (ix = 0; ix < SgCount; ++ix)
1419 {
1420 TransferLength += SgList->SgElement[ix].SgTransferLength;
1421 }
1422
1423 DPRINT("UhciBulkOrInterruptTransfer: SgCount - %X, TransferLength - %X\n",
1424 SgList->SgElementCount,
1425 TransferLength);
1426
1427 if (TransferLength)
1428 {
1429 TDs = TransferLength + (TotalMaxPacketSize - 1);
1430 TDs /= TotalMaxPacketSize;
1431 }
1432 else
1433 {
1434 TDs = 1;
1435 }
1436 }
1437
1438 if ((UhciEndpoint->MaxTDs - UhciEndpoint->AllocatedTDs) < TDs)
1439 {
1440 DPRINT1("UhciBulkOrInterruptTransfer: Not enough TDs \n");
1441 return MP_STATUS_FAILURE;
1442 }
1443
1444 DataFirstTD = NULL;
1445 DataLastTD = NULL;
1446
1447 UhciMapAsyncTransferToTDs(UhciExtension,
1448 UhciEndpoint,
1449 UhciTransfer,
1450 &DataFirstTD,
1451 &DataLastTD,
1452 SgList);
1453
1454 if (DataLastTD == NULL || DataFirstTD == NULL)
1455 {
1456 DPRINT1("UhciBulkOrInterruptTransfer: !DataLastTD || !DataFirstTD\n");
1457 return MP_STATUS_FAILURE;
1458 }
1459
1460 DataLastTD->HwTD.NextElement = UHCI_TD_LINK_PTR_TERMINATE;
1461 DataLastTD->HwTD.ControlStatus.InterruptOnComplete = 1;
1462 DataLastTD->NextHcdTD = NULL;
1463
1464 UhciQueueTransfer(UhciExtension,
1465 UhciEndpoint,
1466 DataFirstTD,
1467 DataLastTD);
1468
1469 return MP_STATUS_SUCCESS;
1470 }
1471
1472 MPSTATUS
1473 NTAPI
1474 UhciSubmitTransfer(IN PVOID uhciExtension,
1475 IN PVOID uhciEndpoint,
1476 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
1477 IN PVOID uhciTransfer,
1478 IN PUSBPORT_SCATTER_GATHER_LIST SgList)
1479 {
1480 PUHCI_EXTENSION UhciExtension = uhciExtension;
1481 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
1482 PUHCI_TRANSFER UhciTransfer = uhciTransfer;
1483 ULONG TransferType;
1484
1485 DPRINT_UHCI("UhciSubmitTransfer: ...\n");
1486
1487 InterlockedIncrement(&UhciEndpoint->EndpointLock);
1488
1489 TransferType = UhciEndpoint->EndpointProperties.TransferType;
1490
1491 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS &&
1492 InterlockedIncrement(&UhciExtension->ExtensionLock) == 1)
1493 {
1494 UhciExtension->FrameNumber = UhciGet32BitFrameNumber(UhciExtension);
1495 }
1496
1497 RtlZeroMemory(UhciTransfer, sizeof(UHCI_TRANSFER));
1498
1499 UhciTransfer->TransferParameters = TransferParameters;
1500 UhciTransfer->UhciEndpoint = UhciEndpoint;
1501 UhciTransfer->USBDStatus = USBD_STATUS_SUCCESS;
1502
1503 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
1504 {
1505 return UhciControlTransfer(UhciExtension,
1506 UhciEndpoint,
1507 TransferParameters,
1508 UhciTransfer,
1509 SgList);
1510 }
1511
1512 if (TransferType == USBPORT_TRANSFER_TYPE_BULK ||
1513 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1514 {
1515 return UhciBulkOrInterruptTransfer(UhciExtension,
1516 UhciEndpoint,
1517 TransferParameters,
1518 UhciTransfer,
1519 SgList);
1520 }
1521
1522 DPRINT1("UhciSubmitTransfer: Error TransferType - %x\n", TransferType);
1523
1524 return MP_STATUS_SUCCESS;
1525 }
1526
1527 USBD_STATUS
1528 NTAPI
1529 UhciGetErrorFromTD(IN PUHCI_EXTENSION UhciExtension,
1530 IN PUHCI_HCD_TD TD)
1531 {
1532 USBD_STATUS USBDStatus;
1533 UCHAR TdStatus;
1534
1535 //DPRINT("UhciGetErrorFromTD: ...\n");
1536
1537 TdStatus = TD->HwTD.ControlStatus.Status;
1538
1539 if (TdStatus == UHCI_TD_STS_ACTIVE)
1540 {
1541 if (TD->HwTD.Token.MaximumLength == UHCI_TD_LENGTH_NULL)
1542 return USBD_STATUS_SUCCESS;
1543
1544 if (TD->HwTD.ControlStatus.ActualLength + 1 >=
1545 TD->HwTD.Token.MaximumLength + 1)
1546 {
1547 return USBD_STATUS_SUCCESS;
1548 }
1549
1550 if (TD->HwTD.ControlStatus.InterruptOnComplete == 1)
1551 return USBD_STATUS_SUCCESS;
1552
1553 return USBD_STATUS_ERROR_SHORT_TRANSFER;
1554 }
1555
1556 if (TdStatus & UHCI_TD_STS_BABBLE_DETECTED &&
1557 TdStatus & UHCI_TD_STS_STALLED)
1558 {
1559 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_BUFFER_OVERRUN, TD - %p\n", TD);
1560 return USBD_STATUS_BUFFER_OVERRUN;
1561 }
1562
1563 if (TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR &&
1564 TdStatus & UHCI_TD_STS_STALLED)
1565 {
1566 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DEV_NOT_RESPONDING, TD - %p\n", TD);
1567 return USBD_STATUS_DEV_NOT_RESPONDING;
1568 }
1569
1570 if (TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR)
1571 {
1572 if (TD->HwTD.ControlStatus.ActualLength == UHCI_TD_LENGTH_NULL)
1573 {
1574 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DEV_NOT_RESPONDING, TD - %p\n", TD);
1575 return USBD_STATUS_DEV_NOT_RESPONDING;
1576 }
1577 else
1578 {
1579 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_CRC, TD - %p\n", TD);
1580 return USBD_STATUS_CRC;
1581 }
1582 }
1583 else if (TdStatus & UHCI_TD_STS_DATA_BUFFER_ERROR)
1584 {
1585 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DATA_OVERRUN, TD - %p\n", TD);
1586 USBDStatus = USBD_STATUS_DATA_OVERRUN;
1587 }
1588 else if (TdStatus & UHCI_TD_STS_STALLED)
1589 {
1590 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_STALL_PID, TD - %p\n", TD);
1591 USBDStatus = USBD_STATUS_STALL_PID;
1592 }
1593 else
1594 {
1595 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_INTERNAL_HC_ERROR, TD - %p\n", TD);
1596 USBDStatus = USBD_STATUS_INTERNAL_HC_ERROR;
1597 }
1598
1599 return USBDStatus;
1600 }
1601
1602 VOID
1603 NTAPI
1604 UhciProcessDoneNonIsoTD(IN PUHCI_EXTENSION UhciExtension,
1605 IN PUHCI_HCD_TD TD)
1606 {
1607 PUSBPORT_TRANSFER_PARAMETERS TransferParameters;
1608 PUHCI_ENDPOINT UhciEndpoint;
1609 PUHCI_TRANSFER UhciTransfer;
1610 USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
1611 SIZE_T TransferedLen;
1612
1613 DPRINT_UHCI("UhciProcessDoneNonIsoTD: TD - %p\n", TD);
1614
1615 UhciTransfer = TD->UhciTransfer;
1616 UhciTransfer->PendingTds--;
1617
1618 TransferParameters = UhciTransfer->TransferParameters;
1619 UhciEndpoint = UhciTransfer->UhciEndpoint;
1620
1621 if (!(TD->Flags & UHCI_HCD_TD_FLAG_NOT_ACCESSED))
1622 {
1623 if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
1624 USBDStatus = UhciGetErrorFromTD(UhciExtension, TD);
1625
1626 if (USBDStatus != USBD_STATUS_SUCCESS ||
1627 (TD->HwTD.ControlStatus.ActualLength == UHCI_TD_LENGTH_NULL))
1628 {
1629 TransferedLen = 0;
1630 }
1631 else
1632 {
1633 TransferedLen = TD->HwTD.ControlStatus.ActualLength + 1;
1634 }
1635
1636 if (TD->HwTD.Token.PIDCode != UHCI_TD_PID_SETUP)
1637 UhciTransfer->TransferLen += TransferedLen;
1638
1639 if (TD->HwTD.Token.PIDCode == UHCI_TD_PID_IN &&
1640 TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER)
1641 {
1642 DPRINT_IMPL("UhciProcessDoneNonIsoTD: UNIMPLEMENTED. FIXME\n");
1643 }
1644
1645 if (USBDStatus != USBD_STATUS_SUCCESS)
1646 UhciTransfer->USBDStatus = USBDStatus;
1647 }
1648
1649 if (TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER)
1650 DPRINT_IMPL("UhciProcessDoneNonIsoTD: UNIMPLEMENTED. FIXME\n");
1651
1652 UhciEndpoint->AllocatedTDs--;
1653
1654 TD->HwTD.NextElement = 0;
1655 TD->UhciTransfer = NULL;
1656 TD->Flags = 0;
1657
1658 if (UhciTransfer->PendingTds == 0)
1659 {
1660 InterlockedDecrement(&UhciEndpoint->EndpointLock);
1661
1662 if (UhciEndpoint->EndpointProperties.TransferType ==
1663 USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1664 {
1665 InterlockedDecrement(&UhciExtension->ExtensionLock);
1666 }
1667
1668 RegPacket.UsbPortCompleteTransfer(UhciExtension,
1669 UhciEndpoint,
1670 TransferParameters,
1671 UhciTransfer->USBDStatus,
1672 UhciTransfer->TransferLen);
1673 }
1674 }
1675
1676 MPSTATUS
1677 NTAPI
1678 UhciIsochTransfer(IN PVOID ehciExtension,
1679 IN PVOID ehciEndpoint,
1680 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
1681 IN PVOID ehciTransfer,
1682 IN PVOID isoParameters)
1683 {
1684 DPRINT_IMPL("UhciIsochTransfer: UNIMPLEMENTED. FIXME\n");
1685 return MP_STATUS_SUCCESS;
1686 }
1687
1688 VOID
1689 NTAPI
1690 UhciAbortIsoTransfer(IN PUHCI_EXTENSION UhciExtension,
1691 IN PUHCI_ENDPOINT UhciEndpoint,
1692 IN PUHCI_TRANSFER UhciTransfer)
1693 {
1694 DPRINT_IMPL("UhciAbortIsoTransfer: UNIMPLEMENTED. FIXME\n");
1695 }
1696
1697 VOID
1698 NTAPI
1699 UhciAbortNonIsoTransfer(IN PUHCI_EXTENSION UhciExtension,
1700 IN PUHCI_ENDPOINT UhciEndpoint,
1701 IN PUHCI_TRANSFER UhciTransfer,
1702 IN PULONG CompletedLength)
1703 {
1704 PUHCI_HCD_TD TD;
1705 PUHCI_HCD_TD PrevTD = NULL;
1706 ULONG PhysicalAddress;
1707 BOOL DataToggle;
1708 BOOLEAN IsHeadTD = FALSE;
1709
1710 DPRINT("UhciAbortNonIsoTransfer: UhciExtension - %p, QH - %p, UhciTransfer - %p\n",
1711 UhciExtension,
1712 UhciEndpoint->QH,
1713 UhciTransfer);
1714
1715 for (TD = UhciEndpoint->HeadTD;
1716 TD && TD->UhciTransfer != UhciTransfer;
1717 TD = TD->NextHcdTD)
1718 {
1719 PrevTD = TD;
1720 }
1721
1722 DataToggle = TD->HwTD.Token.DataToggle;
1723
1724 if (TD == UhciEndpoint->HeadTD)
1725 IsHeadTD = TRUE;
1726
1727 while (TD && TD->UhciTransfer == UhciTransfer);
1728 {
1729 DPRINT_UHCI("UhciAbortNonIsoTransfer: TD - %p\n", TD);
1730
1731 if (TD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE)
1732 {
1733 if (TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER)
1734 DPRINT_IMPL("UhciAbortNonIsoTransfer: UNIMPLEMENTED. FIXME\n");
1735
1736 UhciEndpoint->AllocatedTDs--;
1737
1738 DPRINT_UHCI("UhciAbortNonIsoTransfer: Active TD - %p\n", TD);
1739
1740 TD->HwTD.NextElement = 0;
1741 TD->Flags = 0;
1742 TD->UhciTransfer = NULL;
1743 }
1744 else
1745 {
1746 UhciProcessDoneNonIsoTD(UhciExtension, TD);
1747 }
1748
1749 TD = TD->NextHcdTD;
1750 }
1751
1752 UhciFixDataToggle(UhciExtension,
1753 UhciEndpoint,
1754 TD,
1755 DataToggle);
1756
1757 if (IsHeadTD)
1758 {
1759 if (TD)
1760 {
1761 UhciEndpoint->HeadTD = TD;
1762 }
1763 else
1764 {
1765 UhciEndpoint->HeadTD = NULL;
1766 UhciEndpoint->TailTD = NULL;
1767 }
1768
1769 if (TD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
1770 {
1771 PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
1772 }
1773 else
1774 {
1775 PhysicalAddress = TD->PhysicalAddress;
1776 PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
1777 }
1778
1779 DPRINT_UHCI("UhciAbortNonIsoTransfer: TD - %p\n", TD);
1780
1781 UhciEndpoint->QH->HwQH.NextElement = PhysicalAddress;
1782 UhciEndpoint->QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH;
1783 }
1784 else if (TD)
1785 {
1786 PrevTD->HwTD.NextElement = TD->PhysicalAddress & UHCI_TD_LINK_POINTER_MASK;
1787 PrevTD->NextHcdTD = TD;
1788 }
1789 else
1790 {
1791 PrevTD->NextHcdTD = NULL;
1792 PrevTD->HwTD.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
1793
1794 UhciEndpoint->TailTD = PrevTD;
1795 }
1796
1797 *CompletedLength = UhciTransfer->TransferLen;
1798 }
1799
1800 VOID
1801 NTAPI
1802 UhciAbortTransfer(IN PVOID uhciExtension,
1803 IN PVOID uhciEndpoint,
1804 IN PVOID uhciTransfer,
1805 IN PULONG CompletedLength)
1806 {
1807 PUHCI_EXTENSION UhciExtension = uhciExtension;
1808 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
1809 PUHCI_TRANSFER UhciTransfer = uhciTransfer;
1810 ULONG TransferType;
1811
1812 DPRINT("UhciAbortTransfer: ...\n");
1813
1814 InterlockedDecrement(&UhciEndpoint->EndpointLock);
1815
1816 TransferType = UhciEndpoint->EndpointProperties.TransferType;
1817
1818 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1819 {
1820 InterlockedDecrement(&UhciExtension->ExtensionLock);
1821
1822 UhciAbortIsoTransfer(UhciExtension,
1823 UhciEndpoint,
1824 UhciTransfer);
1825 }
1826
1827 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
1828 TransferType == USBPORT_TRANSFER_TYPE_BULK ||
1829 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1830 {
1831 UhciAbortNonIsoTransfer(UhciExtension,
1832 UhciEndpoint,
1833 UhciTransfer,
1834 CompletedLength);
1835 }
1836 }
1837
1838 ULONG
1839 NTAPI
1840 UhciGetEndpointState(IN PVOID uhciExtension,
1841 IN PVOID uhciEndpoint)
1842 {
1843 DPRINT_IMPL("UhciGetEndpointState: UNIMPLEMENTED. FIXME\n");
1844 return 0;
1845 }
1846
1847 VOID
1848 NTAPI
1849 UhciInsertQH(IN PUHCI_EXTENSION UhciExtension,
1850 IN PUHCI_HCD_QH StaticQH,
1851 IN PUHCI_HCD_QH QH)
1852 {
1853 PUHCI_HCD_QH NextHcdQH;
1854
1855 DPRINT("UhciInsertQH: UhciExtension - %p, StaticQH - %p, QH - %p\n", UhciExtension, StaticQH, QH);
1856
1857 QH->HwQH.NextQH = StaticQH->HwQH.NextQH;
1858 NextHcdQH = StaticQH->NextHcdQH;
1859
1860 QH->PrevHcdQH = StaticQH;
1861 QH->NextHcdQH = NextHcdQH;
1862
1863 if (NextHcdQH)
1864 NextHcdQH->PrevHcdQH = QH;
1865 else
1866 UhciExtension->BulkTailQH = QH;
1867
1868 StaticQH->HwQH.NextQH = QH->PhysicalAddress | UHCI_QH_HEAD_LINK_PTR_QH;
1869 StaticQH->NextHcdQH = QH;
1870
1871 QH->QhFlags |= UHCI_HCD_QH_FLAG_ACTIVE;
1872 }
1873
1874 VOID
1875 NTAPI
1876 UhciUnlinkQH(IN PUHCI_EXTENSION UhciExtension,
1877 IN PUHCI_HCD_QH QH)
1878 {
1879 PUHCI_HCD_QH NextHcdQH;
1880 PUHCI_HCD_QH PrevHcdQH;
1881 PUHCI_HCD_QH BulkQH;
1882
1883 DPRINT("UhciUnlinkQH: ... \n");
1884
1885 NextHcdQH = QH->NextHcdQH;
1886 PrevHcdQH = QH->PrevHcdQH;
1887
1888 if (UhciExtension->BulkTailQH == QH)
1889 UhciExtension->BulkTailQH = PrevHcdQH;
1890
1891 PrevHcdQH->HwQH.NextQH = QH->HwQH.NextQH;
1892 PrevHcdQH->NextHcdQH = NextHcdQH;
1893
1894 if (NextHcdQH)
1895 NextHcdQH->PrevHcdQH = PrevHcdQH;
1896
1897 QH->PrevHcdQH = QH;
1898 QH->NextHcdQH = QH;
1899
1900 if (!(QH->UhciEndpoint->EndpointProperties.TransferType ==
1901 USBPORT_TRANSFER_TYPE_BULK))
1902 {
1903 QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE;
1904 return;
1905 }
1906
1907 if ((UhciExtension->BulkTailQH->HwQH.NextQH & UHCI_QH_HEAD_LINK_PTR_TERMINATE)
1908 == UHCI_QH_HEAD_LINK_PTR_TERMINATE)
1909 {
1910 QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE;
1911 return;
1912 }
1913
1914 BulkQH = UhciExtension->BulkQH;
1915
1916 while (TRUE)
1917 {
1918 BulkQH = BulkQH->NextHcdQH;
1919
1920 if (!BulkQH)
1921 break;
1922
1923 if (!(BulkQH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_PTR_TERMINATE))
1924 {
1925 QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE;
1926 return;
1927 }
1928 }
1929
1930 UhciExtension->BulkTailQH->HwQH.NextQH |= UHCI_QH_HEAD_LINK_PTR_TERMINATE;
1931
1932 QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE;
1933 }
1934
1935 VOID
1936 NTAPI
1937 UhciSetEndpointState(IN PVOID uhciExtension,
1938 IN PVOID uhciEndpoint,
1939 IN ULONG EndpointState)
1940 {
1941 PUHCI_EXTENSION UhciExtension = uhciExtension;
1942 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
1943 ULONG TransferType;
1944 PUHCI_HCD_QH QH;
1945 ULONG Idx;
1946
1947 TransferType = UhciEndpoint->EndpointProperties.TransferType;
1948 QH = UhciEndpoint->QH;
1949
1950 DPRINT("UhciSetEndpointState: EndpointState - %x, TransferType - %x\n",
1951 EndpointState,
1952 TransferType);
1953
1954 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1955 return;
1956
1957 if (TransferType != USBPORT_TRANSFER_TYPE_CONTROL &&
1958 TransferType != USBPORT_TRANSFER_TYPE_BULK &&
1959 TransferType != USBPORT_TRANSFER_TYPE_INTERRUPT)
1960 {
1961 DPRINT("UhciSetEndpointState: Unknown TransferType - %x\n",
1962 TransferType);
1963 }
1964
1965 switch (EndpointState)
1966 {
1967 case USBPORT_ENDPOINT_PAUSED:
1968 UhciUnlinkQH(UhciExtension, QH);
1969 return;
1970
1971 case USBPORT_ENDPOINT_ACTIVE:
1972 switch (TransferType)
1973 {
1974 case USBPORT_TRANSFER_TYPE_CONTROL:
1975 UhciInsertQH(UhciExtension,
1976 UhciExtension->ControlQH,
1977 UhciEndpoint->QH);
1978 break;
1979
1980 case USBPORT_TRANSFER_TYPE_BULK:
1981 UhciInsertQH(UhciExtension,
1982 UhciExtension->BulkQH,
1983 UhciEndpoint->QH);
1984 break;
1985
1986 case USBPORT_TRANSFER_TYPE_INTERRUPT:
1987 Idx = UhciEndpoint->EndpointProperties.Period +
1988 UhciEndpoint->EndpointProperties.ScheduleOffset;
1989
1990 UhciInsertQH(UhciExtension,
1991 UhciExtension->IntQH[Idx - 1],
1992 UhciEndpoint->QH);
1993 break;
1994 default:
1995 ASSERT(FALSE);
1996 break;
1997 }
1998
1999 break;
2000
2001 case USBPORT_ENDPOINT_REMOVE:
2002 QH->QhFlags |= UHCI_HCD_QH_FLAG_REMOVE;
2003 UhciUnlinkQH(UhciExtension, QH);
2004 break;
2005
2006 default:
2007 ASSERT(FALSE);
2008 break;
2009 }
2010 }
2011
2012 ULONG
2013 NTAPI
2014 UhciGetEndpointStatus(IN PVOID uhciExtension,
2015 IN PVOID uhciEndpoint)
2016 {
2017 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
2018 ULONG EndpointStatus;
2019
2020 DPRINT_UHCI("UhciGetEndpointStatus: ...\n");
2021
2022 if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
2023 EndpointStatus = USBPORT_ENDPOINT_HALT;
2024 else
2025 EndpointStatus = USBPORT_ENDPOINT_RUN;
2026
2027 return EndpointStatus;
2028 }
2029
2030 VOID
2031 NTAPI
2032 UhciSetEndpointStatus(IN PVOID uhciExtension,
2033 IN PVOID uhciEndpoint,
2034 IN ULONG EndpointStatus)
2035 {
2036 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
2037 ULONG PhysicalAddress;
2038
2039 DPRINT("UhciSetEndpointStatus: uhciEndpoint - %p, EndpointStatus - %X\n",
2040 uhciEndpoint,
2041 EndpointStatus);
2042
2043 if (EndpointStatus != USBPORT_ENDPOINT_RUN)
2044 return;
2045
2046 if (!(UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED))
2047 return;
2048
2049 UhciEndpoint->Flags &= ~UHCI_ENDPOINT_FLAG_HALTED;
2050
2051 if (UhciEndpoint->HeadTD == NULL)
2052 UhciEndpoint->TailTD = NULL;
2053
2054 if (UhciEndpoint->HeadTD)
2055 {
2056 PhysicalAddress = UhciEndpoint->HeadTD->PhysicalAddress;
2057 PhysicalAddress &= ~UHCI_TD_LINK_PTR_TERMINATE;
2058 UhciEndpoint->QH->HwQH.NextElement = PhysicalAddress;
2059 UhciEndpoint->QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH;
2060 }
2061 else
2062 {
2063 UhciEndpoint->QH->HwQH.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
2064 }
2065 }
2066
2067 VOID
2068 NTAPI
2069 UhciPollIsoEndpoint(IN PUHCI_EXTENSION UhciExtension,
2070 IN PUHCI_ENDPOINT UhciEndpoint)
2071 {
2072 DPRINT_IMPL("UhciPollIsoEndpoint: UNIMPLEMENTED. FIXME\n");
2073 }
2074
2075 VOID
2076 NTAPI
2077 UhciPollNonIsoEndpoint(IN PUHCI_EXTENSION UhciExtension,
2078 IN PUHCI_ENDPOINT UhciEndpoint)
2079 {
2080 PUHCI_HCD_QH QH;
2081 PUHCI_HCD_TD NextTD;
2082 PUHCI_HCD_TD TD;
2083 ULONG NextTdPA;
2084 ULONG PhysicalAddress;
2085 SIZE_T TransferedLen;
2086 PLIST_ENTRY ListTDs;
2087 UCHAR TdStatus;
2088
2089 DPRINT_UHCI("UhciPollNonIsoEndpoint: UhciExtension - %p, UhciEndpoint - %p\n",
2090 UhciExtension,
2091 UhciEndpoint);
2092
2093 if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
2094 {
2095 DPRINT("UhciPollNonIsoEndpoint: Ep->Flags & UHCI_ENDPOINT_FLAG_HALTED \n");
2096 return;
2097 }
2098
2099 QH = UhciEndpoint->QH;
2100
2101 NextTdPA = QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_POINTER_MASK;
2102
2103 if (NextTdPA)
2104 {
2105 NextTD = RegPacket.UsbPortGetMappedVirtualAddress(NextTdPA,
2106 UhciExtension,
2107 UhciEndpoint);
2108 }
2109 else
2110 {
2111 NextTD = NULL;
2112 }
2113
2114 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, NextTdPA - %p\n",
2115 NextTD,
2116 NextTdPA);
2117
2118 for (TD = UhciEndpoint->HeadTD; TD != NextTD && TD != NULL; TD = TD->NextHcdTD)
2119 {
2120 DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p, TD->NextHcdTD - %p\n",
2121 TD,
2122 TD->NextHcdTD);
2123
2124 TD->Flags |= UHCI_HCD_TD_FLAG_DONE;
2125 InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink);
2126
2127 if (TD->NextHcdTD &&
2128 TD->NextHcdTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE)
2129 {
2130 if (NextTdPA == 0)
2131 {
2132 TD = TD->NextHcdTD;
2133 goto EnqueueTD;
2134 }
2135
2136 if (NextTdPA != TD->NextHcdTD->PhysicalAddress)
2137 {
2138 DPRINT("UhciPollNonIsoEndpoint: TD->NextHcdTD->PhysicalAddress - %p\n",
2139 TD->NextHcdTD->PhysicalAddress);
2140 ASSERT(FALSE);
2141 }
2142 }
2143 else
2144 {
2145 if (TD->NextHcdTD == NULL)
2146 {
2147 DPRINT_UHCI("UhciPollNonIsoEndpoint: TD->NextHcdTD == NULL\n");
2148 }
2149 else
2150 {
2151 DPRINT_UHCI("UhciPollNonIsoEndpoint: ControlStatus - %X\n",
2152 TD->NextHcdTD->HwTD.ControlStatus.AsULONG);
2153 }
2154 }
2155 }
2156
2157 UhciEndpoint->HeadTD = NextTD;
2158
2159 if (NextTD == NULL)
2160 {
2161 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD == NULL\n");
2162
2163 UhciEndpoint->HeadTD = NULL;
2164 UhciEndpoint->TailTD = NULL;
2165
2166 QH->HwQH.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
2167
2168 goto ProcessListTDs;
2169 }
2170
2171 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, NextTdPA - %p\n",
2172 NextTD,
2173 NextTdPA);
2174
2175 TdStatus = NextTD->HwTD.ControlStatus.Status;
2176
2177 if (TdStatus & UHCI_TD_STS_ACTIVE)
2178 {
2179 DPRINT_UHCI("UhciPollNonIsoEndpoint: UHCI_TD_STS_ACTIVE \n");
2180 goto ProcessListTDs;
2181 }
2182
2183 if (NextTD->HwTD.Token.PIDCode == UHCI_TD_PID_IN &&
2184 TdStatus & UHCI_TD_STS_STALLED &&
2185 TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR &&
2186 !(TdStatus & UHCI_TD_STS_NAK_RECEIVED) &&
2187 !(TdStatus & UHCI_TD_STS_BABBLE_DETECTED) &&
2188 !(TdStatus & UHCI_TD_STS_BITSTUFF_ERROR))
2189 {
2190 DPRINT("UhciPollNonIsoEndpoint: USBD_STATUS_DEV_NOT_RESPONDING\n");
2191
2192 UhciDumpHcdTD(NextTD);
2193
2194 if (!(NextTD->Flags & UHCI_HCD_TD_FLAG_STALLED_SETUP))
2195 {
2196 NextTD->HwTD.ControlStatus.ErrorCounter = 3;
2197
2198 NextTD->HwTD.ControlStatus.Status &= ~(UHCI_TD_STS_STALLED |
2199 UHCI_TD_STS_TIMEOUT_CRC_ERROR);
2200
2201 NextTD->HwTD.ControlStatus.Status |= UHCI_TD_STS_ACTIVE;
2202
2203 NextTD->Flags = NextTD->Flags | UHCI_HCD_TD_FLAG_STALLED_SETUP;
2204
2205 goto ProcessListTDs;
2206 }
2207 }
2208
2209 if (TdStatus & (UHCI_TD_STS_STALLED |
2210 UHCI_TD_STS_DATA_BUFFER_ERROR |
2211 UHCI_TD_STS_BABBLE_DETECTED |
2212 UHCI_TD_STS_TIMEOUT_CRC_ERROR |
2213 UHCI_TD_STS_BITSTUFF_ERROR))
2214 {
2215 DPRINT("UhciPollNonIsoEndpoint: NextTD UHCI_TD_STS_ - %02X, PIDCode - %02X\n",
2216 NextTD->HwTD.ControlStatus.Status,
2217 NextTD->HwTD.Token.PIDCode);
2218
2219 UhciDumpHcdTD(NextTD);
2220
2221 UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_HALTED;
2222 NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE;
2223
2224 InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink);
2225
2226 if (TD->UhciTransfer != NextTD->UhciTransfer)
2227 ASSERT(TD->UhciTransfer == NextTD->UhciTransfer);
2228
2229 while (TD &&
2230 TD->UhciTransfer->TransferParameters->TransferCounter ==
2231 NextTD->UhciTransfer->TransferParameters->TransferCounter)
2232 {
2233 DPRINT("UhciPollNonIsoEndpoint: Bad TD - %p\n", TD);
2234
2235 if (!(TD->Flags & UHCI_HCD_TD_FLAG_DONE))
2236 {
2237 TD->Flags |= UHCI_HCD_TD_FLAG_DONE;
2238 TD->Flags |= UHCI_HCD_TD_FLAG_NOT_ACCESSED;
2239
2240 InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink);
2241 }
2242
2243 TD = TD->NextHcdTD;
2244 }
2245
2246 if (UhciEndpoint->EndpointProperties.TransferType !=
2247 USBPORT_TRANSFER_TYPE_CONTROL)
2248 {
2249 UhciFixDataToggle(UhciExtension,
2250 UhciEndpoint,
2251 TD,
2252 NextTD->HwTD.Token.DataToggle);
2253 }
2254 }
2255 else
2256 {
2257 TransferedLen = NextTD->HwTD.ControlStatus.ActualLength;
2258
2259 if (TransferedLen == UHCI_TD_LENGTH_NULL)
2260 TransferedLen = 0;
2261 else
2262 TransferedLen += 1;
2263
2264 if (NextTD->HwTD.Token.MaximumLength == UHCI_TD_LENGTH_NULL ||
2265 TransferedLen >= (NextTD->HwTD.Token.MaximumLength + 1))
2266 {
2267 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, TransferedLen - %X\n",
2268 NextTD,
2269 TransferedLen);
2270
2271 if (NextTdPA ==
2272 (QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_POINTER_MASK))
2273 {
2274 NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE;
2275 InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink);
2276
2277 UhciEndpoint->HeadTD = NextTD->NextHcdTD;
2278
2279 QH->HwQH.NextElement = NextTD->HwTD.NextElement;
2280 QH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TD;
2281
2282 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, TD - %p\n",
2283 NextTD,
2284 TD);
2285 }
2286
2287 goto ProcessListTDs;
2288 }
2289
2290 DPRINT_UHCI("UhciPollNonIsoEndpoint: ShortPacket. ControlStatus - %X\n",
2291 NextTD->HwTD.ControlStatus.AsULONG);
2292
2293 NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE;
2294 InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink);
2295
2296 while (TD &&
2297 TD->UhciTransfer->TransferParameters->TransferCounter ==
2298 NextTD->UhciTransfer->TransferParameters->TransferCounter)
2299 {
2300 if (TD->Flags & UHCI_HCD_TD_FLAG_CONTROLL &&
2301 NextTD->UhciTransfer->TransferParameters->TransferFlags &
2302 USBD_SHORT_TRANSFER_OK)
2303 {
2304 break;
2305 }
2306
2307 if (!(TD->Flags & UHCI_HCD_TD_FLAG_DONE))
2308 {
2309 DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p\n", TD);
2310
2311 TD->Flags |= (UHCI_HCD_TD_FLAG_DONE |
2312 UHCI_HCD_TD_FLAG_NOT_ACCESSED);
2313
2314 InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink);
2315 }
2316
2317 TD = TD->NextHcdTD;
2318 }
2319
2320 if (NextTD->NextHcdTD &&
2321 (UhciEndpoint->EndpointProperties.TransferType !=
2322 USBPORT_TRANSFER_TYPE_CONTROL))
2323 {
2324 UhciFixDataToggle(UhciExtension,
2325 UhciEndpoint,
2326 TD,
2327 NextTD->NextHcdTD->HwTD.Token.DataToggle);
2328 }
2329
2330 if (!(NextTD->UhciTransfer->TransferParameters->TransferFlags &
2331 USBD_SHORT_TRANSFER_OK))
2332 {
2333 UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_HALTED;
2334 }
2335 }
2336
2337 EnqueueTD:
2338
2339 if (TD)
2340 {
2341 UhciEndpoint->HeadTD = TD;
2342 }
2343 else
2344 {
2345 UhciEndpoint->HeadTD = NULL;
2346 UhciEndpoint->TailTD = NULL;
2347 }
2348
2349 if (TD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
2350 {
2351 PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
2352 }
2353 else
2354 {
2355 PhysicalAddress = TD->PhysicalAddress;
2356 PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
2357 }
2358
2359 DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p\n", TD);
2360
2361 QH->HwQH.NextElement = PhysicalAddress;
2362 QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH;
2363
2364 ProcessListTDs:
2365
2366 ListTDs = &UhciEndpoint->ListTDs;
2367
2368 while (!IsListEmpty(ListTDs))
2369 {
2370 TD = CONTAINING_RECORD(ListTDs->Flink,
2371 UHCI_HCD_TD,
2372 TdLink.Flink);
2373
2374 RemoveHeadList(ListTDs);
2375
2376 if ((TD->Flags & (UHCI_HCD_TD_FLAG_PROCESSED | UHCI_HCD_TD_FLAG_DONE)) ==
2377 (UHCI_HCD_TD_FLAG_PROCESSED | UHCI_HCD_TD_FLAG_DONE))
2378 {
2379 UhciProcessDoneNonIsoTD(UhciExtension, TD);
2380 }
2381 }
2382
2383 if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_CONTROL_OR_ISO &&
2384 UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
2385 {
2386 DPRINT_UHCI("UhciPollNonIsoEndpoint: Halted periodic EP - %p\n",
2387 UhciEndpoint);
2388
2389 UhciSetEndpointStatus(UhciExtension,
2390 UhciEndpoint,
2391 USBPORT_ENDPOINT_RUN);
2392 }
2393 }
2394
2395 VOID
2396 NTAPI
2397 UhciPollEndpoint(IN PVOID uhciExtension,
2398 IN PVOID uhciEndpoint)
2399 {
2400 PUHCI_EXTENSION UhciExtension = uhciExtension;
2401 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
2402 ULONG TransferType;
2403
2404 DPRINT_UHCI("UhciPollEndpoint: ...\n");
2405
2406 TransferType = UhciEndpoint->EndpointProperties.TransferType;
2407
2408 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
2409 {
2410 UhciPollIsoEndpoint(UhciExtension, UhciEndpoint);
2411 return;
2412 }
2413
2414 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
2415 TransferType == USBPORT_TRANSFER_TYPE_BULK ||
2416 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
2417 {
2418 UhciPollNonIsoEndpoint(UhciExtension, UhciEndpoint);
2419 }
2420 }
2421
2422 VOID
2423 NTAPI
2424 UhciCheckController(IN PVOID uhciExtension)
2425 {
2426 PUHCI_EXTENSION UhciExtension = uhciExtension;
2427
2428 if (!UhciHardwarePresent(UhciExtension) ||
2429 UhciExtension->HcScheduleError >= UHCI_MAX_HC_SCHEDULE_ERRORS)
2430 {
2431 DPRINT1("UhciCheckController: INVALIDATE_CONTROLLER_SURPRISE_REMOVE !!!\n");
2432
2433 RegPacket.UsbPortInvalidateController(UhciExtension,
2434 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
2435 }
2436 }
2437
2438 ULONG
2439 NTAPI
2440 UhciGet32BitFrameNumber(IN PVOID uhciExtension)
2441 {
2442 PUHCI_EXTENSION UhciExtension = uhciExtension;
2443 ULONG Uhci32BitFrame;
2444 USHORT Fn; // FrameNumber
2445 ULONG Hp; // FrameHighPart
2446
2447 Fn = READ_PORT_USHORT(&UhciExtension->BaseRegister->FrameNumber);
2448 Fn &= UHCI_FRNUM_FRAME_MASK;
2449 Hp = UhciExtension->FrameHighPart;
2450
2451 Uhci32BitFrame = Hp;
2452 Uhci32BitFrame += ((USHORT)Hp ^ Fn) & UHCI_FRNUM_OVERFLOW_LIST;
2453 Uhci32BitFrame |= Fn;
2454
2455 DPRINT_UHCI("UhciGet32BitFrameNumber: Uhci32BitFrame - %lX\n",
2456 Uhci32BitFrame);
2457
2458 return Uhci32BitFrame;
2459 }
2460
2461 VOID
2462 NTAPI
2463 UhciInterruptNextSOF(IN PVOID uhciExtension)
2464 {
2465 PUHCI_EXTENSION UhciExtension = uhciExtension;
2466 PUHCI_HC_RESOURCES UhciResources;
2467 ULONG CurrentFrame;
2468 PUHCI_HCD_TD SOF_HcdTDs;
2469 ULONG ix;
2470 ULONG NextFrame;
2471 ULONG SofFrame;
2472 ULONG Idx;
2473
2474 DPRINT_UHCI("UhciInterruptNextSOF: ...\n");
2475
2476 CurrentFrame = UhciGet32BitFrameNumber(UhciExtension);
2477
2478 SOF_HcdTDs = UhciExtension->SOF_HcdTDs;
2479 NextFrame = CurrentFrame + 2;
2480
2481 for (ix = 0; ix < UHCI_MAX_STATIC_SOF_TDS; ++ix)
2482 {
2483 SofFrame = SOF_HcdTDs->Frame;
2484
2485 if (SofFrame == NextFrame)
2486 break;
2487
2488 if (SofFrame < CurrentFrame)
2489 {
2490 SOF_HcdTDs->Frame = NextFrame;
2491 SOF_HcdTDs->Flags |= UHCI_HCD_TD_FLAG_GOOD_FRAME;
2492
2493 /* Insert SOF_HcdTD (InterruptOnComplete = TRUE) in Frame List */
2494 UhciResources = UhciExtension->HcResourcesVA;
2495 Idx = SOF_HcdTDs->Frame & UHCI_FRAME_LIST_INDEX_MASK;
2496
2497 InterlockedExchange((PLONG)&SOF_HcdTDs->HwTD.NextElement,
2498 UhciResources->FrameList[Idx]);
2499
2500 UhciResources->FrameList[Idx] = SOF_HcdTDs->PhysicalAddress;
2501 break;
2502 }
2503
2504 /* Go to next SOF_HcdTD */
2505 SOF_HcdTDs += 1;
2506 }
2507
2508 for (ix = 0; ix < UHCI_MAX_STATIC_SOF_TDS; ++ix)
2509 {
2510 SOF_HcdTDs = &UhciExtension->SOF_HcdTDs[ix];
2511
2512 if (SOF_HcdTDs->Frame &&
2513 (SOF_HcdTDs->Frame < CurrentFrame ||
2514 (SOF_HcdTDs->Frame - CurrentFrame) > UHCI_FRAME_LIST_MAX_ENTRIES))
2515 {
2516 SOF_HcdTDs->Frame = 0;
2517 }
2518 }
2519 }
2520
2521 VOID
2522 NTAPI
2523 UhciEnableInterrupts(IN PVOID uhciExtension)
2524 {
2525 PUHCI_EXTENSION UhciExtension = uhciExtension;
2526 PUHCI_HW_REGISTERS BaseRegister;
2527 UHCI_PCI_LEGSUP LegacySupport;
2528
2529 DPRINT("UhciEnableInterrupts: UhciExtension - %p\n", UhciExtension);
2530
2531 BaseRegister = UhciExtension->BaseRegister;
2532
2533 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
2534 TRUE,
2535 &LegacySupport.AsUSHORT,
2536 PCI_LEGSUP,
2537 sizeof(USHORT));
2538
2539 LegacySupport.UsbPIRQ = 1;
2540
2541 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
2542 FALSE,
2543 &LegacySupport.AsUSHORT,
2544 PCI_LEGSUP,
2545 sizeof(USHORT));
2546
2547 WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT,
2548 UhciExtension->StatusMask.AsUSHORT);
2549 }
2550
2551 VOID
2552 NTAPI
2553 UhciDisableInterrupts(IN PVOID uhciExtension)
2554 {
2555 PUHCI_EXTENSION UhciExtension = uhciExtension;
2556 PUHCI_HW_REGISTERS BaseRegister;
2557 USB_CONTROLLER_FLAVOR HcFlavor;
2558 UHCI_PCI_LEGSUP LegacySupport;
2559
2560 DPRINT("UhciDisableInterrupts: UhciExtension - %p\n", UhciExtension);
2561
2562 BaseRegister = UhciExtension->BaseRegister;
2563 WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT, 0);
2564
2565 HcFlavor = UhciExtension->HcFlavor;
2566 DPRINT("UhciDisableInterrupts: FIXME HcFlavor - %lx\n", HcFlavor);
2567
2568 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
2569 TRUE,
2570 &LegacySupport.AsUSHORT,
2571 PCI_LEGSUP,
2572 sizeof(USHORT));
2573
2574 LegacySupport.UsbPIRQ = 0;
2575
2576 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
2577 FALSE,
2578 &LegacySupport.AsUSHORT,
2579 PCI_LEGSUP,
2580 sizeof(USHORT));
2581 }
2582
2583 VOID
2584 NTAPI
2585 UhciPollController(IN PVOID uhciExtension)
2586 {
2587 PUHCI_EXTENSION UhciExtension = uhciExtension;
2588 PUHCI_HW_REGISTERS BaseRegister;
2589 PUSHORT PortRegister;
2590 UHCI_PORT_STATUS_CONTROL PortControl;
2591 USHORT Port;
2592
2593 DPRINT_UHCI("UhciPollController: UhciExtension - %p\n", UhciExtension);
2594
2595 BaseRegister = UhciExtension->BaseRegister;
2596
2597 if (!(UhciExtension->Flags & UHCI_EXTENSION_FLAG_SUSPENDED))
2598 {
2599 UhciCleanupFrameList(UhciExtension, FALSE);
2600 UhciUpdateCounter(UhciExtension);
2601 RegPacket.UsbPortInvalidateRootHub(UhciExtension);
2602 return;
2603 }
2604
2605 for (Port = 0; Port < UHCI_NUM_ROOT_HUB_PORTS; Port++)
2606 {
2607 PortRegister = (PUSHORT)&BaseRegister->PortControl[Port];
2608 PortControl.AsUSHORT = READ_PORT_USHORT(PortRegister);
2609
2610 if (PortControl.ConnectStatusChange == 1)
2611 RegPacket.UsbPortInvalidateRootHub(UhciExtension);
2612 }
2613 }
2614
2615 VOID
2616 NTAPI
2617 UhciSetEndpointDataToggle(IN PVOID uhciExtension,
2618 IN PVOID uhciEndpoint,
2619 IN ULONG DataToggle)
2620 {
2621 DPRINT_IMPL("UhciSetEndpointDataToggle: UNIMPLEMENTED. FIXME\n");
2622 }
2623
2624 VOID
2625 NTAPI
2626 UhciResetController(IN PVOID uhciExtension)
2627 {
2628 DPRINT_IMPL("UhciResetController: UNIMPLEMENTED. FIXME\n");
2629 }
2630
2631 MPSTATUS
2632 NTAPI
2633 UhciStartSendOnePacket(IN PVOID uhciExtension,
2634 IN PVOID PacketParameters,
2635 IN PVOID Data,
2636 IN PULONG pDataLength,
2637 IN PVOID BufferVA,
2638 IN PVOID BufferPA,
2639 IN ULONG BufferLength,
2640 IN USBD_STATUS * pUSBDStatus)
2641 {
2642 DPRINT_IMPL("UhciStartSendOnePacket: UNIMPLEMENTED. FIXME\n");
2643 return MP_STATUS_SUCCESS;
2644 }
2645
2646 MPSTATUS
2647 NTAPI
2648 UhciEndSendOnePacket(IN PVOID uhciExtension,
2649 IN PVOID PacketParameters,
2650 IN PVOID Data,
2651 IN PULONG pDataLength,
2652 IN PVOID BufferVA,
2653 IN PVOID BufferPA,
2654 IN ULONG BufferLength,
2655 IN USBD_STATUS * pUSBDStatus)
2656 {
2657 DPRINT_IMPL("UhciEndSendOnePacket: UNIMPLEMENTED. FIXME\n");
2658 return MP_STATUS_SUCCESS;
2659 }
2660
2661 MPSTATUS
2662 NTAPI
2663 UhciPassThru(IN PVOID uhciExtension,
2664 IN PVOID passThruParameters,
2665 IN ULONG ParameterLength,
2666 IN PVOID pParameters)
2667 {
2668 DPRINT_IMPL("UhciPassThru: UNIMPLEMENTED. FIXME\n");
2669 return MP_STATUS_SUCCESS;
2670 }
2671
2672 VOID
2673 NTAPI
2674 UhciFlushInterrupts(IN PVOID uhciExtension)
2675 {
2676 DPRINT_IMPL("UhciFlushInterrupts: UNIMPLEMENTED. FIXME\n");
2677 }
2678
2679 MPSTATUS
2680 NTAPI
2681 UhciUnload(IN PVOID uhciExtension)
2682 {
2683 DPRINT_IMPL("UhciUnload: UNIMPLEMENTED. FIXME\n");
2684 return MP_STATUS_SUCCESS;
2685 }
2686
2687 NTSTATUS
2688 NTAPI
2689 DriverEntry(IN PDRIVER_OBJECT DriverObject,
2690 IN PUNICODE_STRING RegistryPath)
2691 {
2692 DPRINT("DriverEntry: DriverObject - %p, RegistryPath - %p\n", DriverObject, RegistryPath);
2693
2694 RtlZeroMemory(&RegPacket, sizeof(USBPORT_REGISTRATION_PACKET));
2695
2696 RegPacket.MiniPortVersion = USB_MINIPORT_VERSION_UHCI;
2697
2698 RegPacket.MiniPortFlags = USB_MINIPORT_FLAGS_INTERRUPT |
2699 USB_MINIPORT_FLAGS_PORT_IO |
2700 USB_MINIPORT_FLAGS_NOT_LOCK_INT |
2701 USB_MINIPORT_FLAGS_POLLING |
2702 USB_MINIPORT_FLAGS_WAKE_SUPPORT;
2703
2704 RegPacket.MiniPortBusBandwidth = TOTAL_USB11_BUS_BANDWIDTH;
2705
2706 RegPacket.MiniPortExtensionSize = sizeof(UHCI_EXTENSION);
2707 RegPacket.MiniPortEndpointSize = sizeof(UHCI_ENDPOINT);
2708 RegPacket.MiniPortTransferSize = sizeof(UHCI_TRANSFER);
2709 RegPacket.MiniPortResourcesSize = sizeof(UHCI_HC_RESOURCES);
2710
2711 RegPacket.OpenEndpoint = UhciOpenEndpoint;
2712 RegPacket.ReopenEndpoint = UhciReopenEndpoint;
2713 RegPacket.QueryEndpointRequirements = UhciQueryEndpointRequirements;
2714 RegPacket.CloseEndpoint = UhciCloseEndpoint;
2715 RegPacket.StartController = UhciStartController;
2716 RegPacket.StopController = UhciStopController;
2717 RegPacket.SuspendController = UhciSuspendController;
2718 RegPacket.ResumeController = UhciResumeController;
2719 RegPacket.InterruptService = UhciInterruptService;
2720 RegPacket.InterruptDpc = UhciInterruptDpc;
2721 RegPacket.SubmitTransfer = UhciSubmitTransfer;
2722 RegPacket.SubmitIsoTransfer = UhciIsochTransfer;
2723 RegPacket.AbortTransfer = UhciAbortTransfer;
2724 RegPacket.GetEndpointState = UhciGetEndpointState;
2725 RegPacket.SetEndpointState = UhciSetEndpointState;
2726 RegPacket.PollEndpoint = UhciPollEndpoint;
2727 RegPacket.CheckController = UhciCheckController;
2728 RegPacket.Get32BitFrameNumber = UhciGet32BitFrameNumber;
2729 RegPacket.InterruptNextSOF = UhciInterruptNextSOF;
2730 RegPacket.EnableInterrupts = UhciEnableInterrupts;
2731 RegPacket.DisableInterrupts = UhciDisableInterrupts;
2732 RegPacket.PollController = UhciPollController;
2733 RegPacket.SetEndpointDataToggle = UhciSetEndpointDataToggle;
2734 RegPacket.GetEndpointStatus = UhciGetEndpointStatus;
2735 RegPacket.SetEndpointStatus = UhciSetEndpointStatus;
2736 RegPacket.RH_GetRootHubData = UhciRHGetRootHubData;
2737 RegPacket.RH_GetStatus = UhciRHGetStatus;
2738 RegPacket.RH_GetPortStatus = UhciRHGetPortStatus;
2739 RegPacket.RH_GetHubStatus = UhciRHGetHubStatus;
2740 RegPacket.RH_SetFeaturePortReset = UhciRHSetFeaturePortReset;
2741 RegPacket.RH_SetFeaturePortPower = UhciRHSetFeaturePortPower;
2742 RegPacket.RH_SetFeaturePortEnable = UhciRHSetFeaturePortEnable;
2743 RegPacket.RH_SetFeaturePortSuspend = UhciRHSetFeaturePortSuspend;
2744 RegPacket.RH_ClearFeaturePortEnable = UhciRHClearFeaturePortEnable;
2745 RegPacket.RH_ClearFeaturePortPower = UhciRHClearFeaturePortPower;
2746 RegPacket.RH_ClearFeaturePortSuspend = UhciRHClearFeaturePortSuspend;
2747 RegPacket.RH_ClearFeaturePortEnableChange = UhciRHClearFeaturePortEnableChange;
2748 RegPacket.RH_ClearFeaturePortConnectChange = UhciRHClearFeaturePortConnectChange;
2749 RegPacket.RH_ClearFeaturePortResetChange = UhciRHClearFeaturePortResetChange;
2750 RegPacket.RH_ClearFeaturePortSuspendChange = UhciRHClearFeaturePortSuspendChange;
2751 RegPacket.RH_ClearFeaturePortOvercurrentChange = UhciRHClearFeaturePortOvercurrentChange;
2752 RegPacket.RH_DisableIrq = UhciRHDisableIrq;
2753 RegPacket.RH_EnableIrq = UhciRHEnableIrq;
2754 RegPacket.StartSendOnePacket = UhciStartSendOnePacket;
2755 RegPacket.EndSendOnePacket = UhciEndSendOnePacket;
2756 RegPacket.PassThru = UhciPassThru;
2757 RegPacket.FlushInterrupts = UhciFlushInterrupts;
2758
2759 DriverObject->DriverUnload = NULL;
2760
2761 return USBPORT_RegisterUSBPortDriver(DriverObject,
2762 USB10_MINIPORT_INTERFACE_VERSION,
2763 &RegPacket);
2764 }