[USBPORT] Continue implementation USBPORT_AllocateBandwidthUSB2().
[reactos.git] / drivers / usb / usbohci_new / usbohci.c
1 #include "usbohci.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 #define NDEBUG_OHCI_TRACE
7 #include "dbg_ohci.h"
8
9 USBPORT_REGISTRATION_PACKET RegPacket;
10
11 static const UCHAR Index[8] =
12 {
13 ENDPOINT_INTERRUPT_1ms - 1,
14 ENDPOINT_INTERRUPT_2ms - 1,
15 ENDPOINT_INTERRUPT_4ms - 1,
16 ENDPOINT_INTERRUPT_8ms - 1,
17 ENDPOINT_INTERRUPT_16ms - 1,
18 ENDPOINT_INTERRUPT_32ms - 1,
19 ENDPOINT_INTERRUPT_32ms - 1,
20 ENDPOINT_INTERRUPT_32ms - 1
21 };
22
23 static const UCHAR Balance[OHCI_NUMBER_OF_INTERRUPTS] =
24 {
25 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30,
26 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31
27 };
28
29 VOID
30 NTAPI
31 OHCI_DumpHcdED(POHCI_HCD_ED ED)
32 {
33 DPRINT("ED - %p\n", ED);
34 DPRINT("EndpointControl - %X\n", ED->HwED.EndpointControl.AsULONG);
35 DPRINT("TailPointer - %08X\n", ED->HwED.TailPointer);
36 DPRINT("HeadPointer - %08X\n", ED->HwED.HeadPointer);
37 DPRINT("NextED - %08X\n", ED->HwED.NextED);
38 }
39
40 VOID
41 NTAPI
42 OHCI_DumpHcdTD(POHCI_HCD_TD TD)
43 {
44 DPRINT("TD - %p\n", TD);
45 DPRINT("gTD.Control - %08X\n", TD->HwTD.gTD.Control.AsULONG);
46 if (TD->HwTD.gTD.CurrentBuffer)
47 DPRINT("gTD.CurrentBuffer - %08X\n", TD->HwTD.gTD.CurrentBuffer);
48 if (TD->HwTD.gTD.NextTD)
49 DPRINT("gTD.NextTD - %08X\n", TD->HwTD.gTD.NextTD);
50 if (TD->HwTD.gTD.BufferEnd)
51 DPRINT("gTD.BufferEnd - %08X\n", TD->HwTD.gTD.BufferEnd);
52
53 if (TD->HwTD.SetupPacket.bmRequestType.B)
54 DPRINT("bmRequestType - %02X\n", TD->HwTD.SetupPacket.bmRequestType.B);
55 if (TD->HwTD.SetupPacket.bRequest)
56 DPRINT("bRequest - %02X\n", TD->HwTD.SetupPacket.bRequest);
57 if (TD->HwTD.SetupPacket.wValue.W)
58 DPRINT("wValue - %04X\n", TD->HwTD.SetupPacket.wValue.W);
59 if (TD->HwTD.SetupPacket.wIndex.W)
60 DPRINT("wIndex - %04X\n", TD->HwTD.SetupPacket.wIndex.W);
61 if (TD->HwTD.SetupPacket.wLength)
62 DPRINT("wLength - %04X\n", TD->HwTD.SetupPacket.wLength);
63
64 DPRINT("PhysicalAddress - %p\n", TD->PhysicalAddress);
65 DPRINT("Flags - %X\n", TD->Flags);
66 DPRINT("OhciTransfer - %08X\n", TD->OhciTransfer);
67 DPRINT("NextHcdTD - %08X\n", TD->NextHcdTD);
68 if (TD->TransferLen)
69 DPRINT("TransferLen - %X\n", TD->TransferLen);
70 }
71
72 VOID
73 NTAPI
74 OHCI_EnableList(IN POHCI_EXTENSION OhciExtension,
75 IN POHCI_ENDPOINT OhciEndpoint)
76 {
77 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
78 PULONG CommandStatusReg;
79 ULONG TransferType;
80 OHCI_REG_COMMAND_STATUS CommandStatus;
81
82 DPRINT_OHCI("OHCI_EnableList: ... \n");
83
84 OperationalRegs = OhciExtension->OperationalRegs;
85 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
86
87 CommandStatus.AsULONG = 0;
88
89 if (READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcControlHeadED))
90 CommandStatus.ControlListFilled = 1;
91
92 if (READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcBulkHeadED))
93 CommandStatus.BulkListFilled = 1;
94
95 TransferType = OhciEndpoint->EndpointProperties.TransferType;
96
97 if (TransferType == USBPORT_TRANSFER_TYPE_BULK)
98 CommandStatus.BulkListFilled = 1;
99 else if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
100 CommandStatus.ControlListFilled = 1;
101
102 WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG);
103 }
104
105 VOID
106 NTAPI
107 OHCI_InsertEndpointInSchedule(IN POHCI_ENDPOINT OhciEndpoint)
108 {
109 POHCI_STATIC_ED HeadED;
110 POHCI_HCD_ED ED;
111 POHCI_HCD_ED PrevED;
112 PLIST_ENTRY HeadLink;
113
114 DPRINT_OHCI("OHCI_InsertEndpointInSchedule: OhciEndpoint - %p\n",
115 OhciEndpoint);
116
117 ED = OhciEndpoint->HcdED;
118
119 HeadED = OhciEndpoint->HeadED;
120 HeadLink = &HeadED->Link;
121
122 if (IsListEmpty(HeadLink))
123 {
124 InsertHeadList(HeadLink, &ED->HcdEDLink);
125
126 if (HeadED->Type == OHCI_STATIC_ED_TYPE_CONTROL ||
127 HeadED->Type == OHCI_STATIC_ED_TYPE_BULK)
128 {
129 ED->HwED.NextED = READ_REGISTER_ULONG(HeadED->pNextED);
130 WRITE_REGISTER_ULONG(HeadED->pNextED, ED->PhysicalAddress);
131 }
132 else if (HeadED->Type == OHCI_STATIC_ED_TYPE_INTERRUPT)
133 {
134 ED->HwED.NextED = *HeadED->pNextED;
135 *HeadED->pNextED = ED->PhysicalAddress;
136 }
137 else
138 {
139 DPRINT1("OHCI_InsertEndpointInSchedule: Unknown HeadED->Type - %x\n",
140 HeadED->Type);
141 DbgBreakPoint();
142 }
143 }
144 else
145 {
146 PrevED = CONTAINING_RECORD(HeadLink->Blink,
147 OHCI_HCD_ED,
148 HcdEDLink);
149
150 InsertTailList(HeadLink, &ED->HcdEDLink);
151
152 ED->HwED.NextED = 0;
153 PrevED->HwED.NextED = ED->PhysicalAddress;
154 }
155 }
156
157 POHCI_HCD_ED
158 NTAPI
159 OHCI_InitializeED(IN POHCI_ENDPOINT OhciEndpoint,
160 IN POHCI_HCD_ED ED,
161 IN POHCI_HCD_TD FirstTD,
162 IN ULONG_PTR EdPA)
163 {
164 OHCI_ENDPOINT_CONTROL EndpointControl;
165 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
166
167 DPRINT_OHCI("OHCI_InitializeED: OhciEndpoint - %p, ED - %p, FirstTD - %p, EdPA - %p\n",
168 OhciEndpoint,
169 ED,
170 FirstTD,
171 EdPA);
172
173 RtlZeroMemory(ED, sizeof(OHCI_HCD_ED));
174
175 ED->PhysicalAddress = EdPA;
176
177 EndpointProperties = &OhciEndpoint->EndpointProperties;
178
179 EndpointControl = ED->HwED.EndpointControl;
180
181 EndpointControl.FunctionAddress = EndpointProperties->DeviceAddress;
182 EndpointControl.EndpointNumber = EndpointProperties->EndpointAddress;
183 EndpointControl.MaximumPacketSize = EndpointProperties->TotalMaxPacketSize;
184
185 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
186 {
187 EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_FROM_TD;
188 }
189 else if (EndpointProperties->Direction)
190 {
191 EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_OUT;
192 }
193 else
194 {
195 EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_IN;
196 }
197
198 if (EndpointProperties->DeviceSpeed == UsbLowSpeed)
199 EndpointControl.Speed = OHCI_ENDPOINT_LOW_SPEED;
200
201 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
202 EndpointControl.Format = OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
203 else
204 EndpointControl.sKip = 1;
205
206 ED->HwED.EndpointControl = EndpointControl;
207
208 ED->HwED.TailPointer = FirstTD->PhysicalAddress;
209 ED->HwED.HeadPointer = FirstTD->PhysicalAddress;
210
211 FirstTD->Flags |= OHCI_HCD_TD_FLAG_ALLOCATED;
212
213 OhciEndpoint->HcdTailP = FirstTD;
214 OhciEndpoint->HcdHeadP = FirstTD;
215
216 return ED;
217 }
218
219 VOID
220 NTAPI
221 OHCI_InitializeTDs(IN POHCI_ENDPOINT OhciEndpoint,
222 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties)
223 {
224 POHCI_HCD_TD TdVA;
225 ULONG TdPA;
226 ULONG TdCount;
227 ULONG ix;
228
229 ASSERT(EndpointProperties->BufferLength > sizeof(OHCI_HCD_ED));
230
231 TdCount = (EndpointProperties->BufferLength - sizeof(OHCI_HCD_ED)) /
232 sizeof(OHCI_HCD_TD);
233
234 OhciEndpoint->MaxTransferDescriptors = TdCount;
235
236 DPRINT_OHCI("OHCI_InitializeTDs: TdCount - %x\n", TdCount);
237
238 ASSERT(TdCount > 0);
239
240 TdVA = OhciEndpoint->FirstTD;
241
242 TdPA = (ULONG)EndpointProperties->BufferPA + sizeof(OHCI_HCD_ED);
243
244 for (ix = 0; ix < TdCount; ix++)
245 {
246 DPRINT_OHCI("OHCI_InitializeTDs: TdVA - %p, TdPA - %08X\n", TdVA, TdPA);
247
248 RtlZeroMemory(TdVA, sizeof(OHCI_HCD_TD));
249
250 TdVA->PhysicalAddress = TdPA;
251 TdVA->Flags = 0;
252 TdVA->OhciTransfer = 0;
253
254 TdVA++;
255 TdPA += sizeof(OHCI_HCD_TD);
256 }
257 }
258
259 MPSTATUS
260 NTAPI
261 OHCI_OpenControlEndpoint(IN POHCI_EXTENSION OhciExtension,
262 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
263 IN POHCI_ENDPOINT OhciEndpoint)
264 {
265 POHCI_HCD_ED ED;
266
267 DPRINT_OHCI("OHCI_OpenControlEndpoint: ... \n");
268
269 ED = (POHCI_HCD_ED)EndpointProperties->BufferVA;
270
271 OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED));
272 OhciEndpoint->HeadED = &OhciExtension->ControlStaticED;
273
274 OHCI_InitializeTDs(OhciEndpoint, EndpointProperties);
275
276 OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint,
277 ED,
278 OhciEndpoint->FirstTD,
279 EndpointProperties->BufferPA);
280
281 OhciEndpoint->HcdED->Flags = OHCI_HCD_ED_FLAG_CONTROL |
282 OHCI_HCD_ED_FLAG_RESET_ON_HALT;
283
284 OHCI_InsertEndpointInSchedule(OhciEndpoint);
285
286 return MP_STATUS_SUCCESS;
287 }
288
289 MPSTATUS
290 NTAPI
291 OHCI_OpenBulkEndpoint(IN POHCI_EXTENSION OhciExtension,
292 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
293 IN POHCI_ENDPOINT OhciEndpoint)
294 {
295 POHCI_HCD_ED ED;
296
297 DPRINT_OHCI("OHCI_OpenBulkEndpoint: ... \n");
298
299 ED = (POHCI_HCD_ED)EndpointProperties->BufferVA;
300
301 OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED));
302 OhciEndpoint->HeadED = &OhciExtension->BulkStaticED;
303
304 OHCI_InitializeTDs(OhciEndpoint, EndpointProperties);
305
306 OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint,
307 ED,
308 OhciEndpoint->FirstTD,
309 EndpointProperties->BufferPA);
310
311 OHCI_InsertEndpointInSchedule(OhciEndpoint);
312
313 return MP_STATUS_SUCCESS;
314 }
315
316 MPSTATUS
317 NTAPI
318 OHCI_OpenInterruptEndpoint(IN POHCI_EXTENSION OhciExtension,
319 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
320 IN POHCI_ENDPOINT OhciEndpoint)
321 {
322 UCHAR Period;
323 ULONG PeriodIdx = 0;
324 POHCI_HCD_ED ED;
325 ULONG ScheduleOffset;
326
327 DPRINT_OHCI("OHCI_OpenInterruptEndpoint: ... \n");
328
329 ED = (POHCI_HCD_ED)EndpointProperties->BufferVA;
330
331 OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED));
332
333 Period = EndpointProperties->Period;
334
335 ASSERT(Period != 0);
336
337 while (!(Period & 1))
338 {
339 PeriodIdx++;
340 Period >>= 1;
341 }
342
343 ASSERT(PeriodIdx < ARRAYSIZE(Index));
344
345 ScheduleOffset = EndpointProperties->ScheduleOffset;
346 DPRINT_OHCI("OHCI_OpenInterruptEndpoint: InitTD. Index[PeriodIdx] - %x, ScheduleOffset - %x\n",
347 Index[PeriodIdx],
348 ScheduleOffset);
349
350 OhciEndpoint->HeadED = &OhciExtension->IntStaticED[Index[PeriodIdx] +
351 ScheduleOffset];
352
353 //OhciEndpoint->HeadED->UsbBandwidth += EndpointProperties->UsbBandwidth;
354
355 OHCI_InitializeTDs(OhciEndpoint, EndpointProperties);
356
357 OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint,
358 ED,
359 OhciEndpoint->FirstTD,
360 EndpointProperties->BufferPA);
361
362 OHCI_InsertEndpointInSchedule(OhciEndpoint);
363
364 return MP_STATUS_SUCCESS;
365 }
366
367 MPSTATUS
368 NTAPI
369 OHCI_OpenIsoEndpoint(IN POHCI_EXTENSION OhciExtension,
370 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
371 IN POHCI_ENDPOINT OhciEndpoint)
372 {
373 DPRINT1("OHCI_OpenIsoEndpoint: UNIMPLEMENTED. FIXME\n");
374 return MP_STATUS_NOT_SUPPORTED;
375 }
376
377 MPSTATUS
378 NTAPI
379 OHCI_OpenEndpoint(IN PVOID ohciExtension,
380 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
381 IN PVOID ohciEndpoint)
382 {
383 POHCI_EXTENSION OhciExtension = ohciExtension;
384 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
385 ULONG TransferType;
386 MPSTATUS MPStatus;
387
388 DPRINT_OHCI("OHCI_OpenEndpoint: ... \n");
389
390 RtlCopyMemory(&OhciEndpoint->EndpointProperties,
391 EndpointProperties,
392 sizeof(OhciEndpoint->EndpointProperties));
393
394 InitializeListHead(&OhciEndpoint->TDList);
395
396 TransferType = EndpointProperties->TransferType;
397
398 switch (TransferType)
399 {
400 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
401 MPStatus = OHCI_OpenIsoEndpoint(OhciExtension,
402 EndpointProperties,
403 OhciEndpoint);
404 break;
405
406 case USBPORT_TRANSFER_TYPE_CONTROL:
407 MPStatus = OHCI_OpenControlEndpoint(OhciExtension,
408 EndpointProperties,
409 OhciEndpoint);
410 break;
411
412 case USBPORT_TRANSFER_TYPE_BULK:
413 MPStatus = OHCI_OpenBulkEndpoint(OhciExtension,
414 EndpointProperties,
415 OhciEndpoint);
416 break;
417
418 case USBPORT_TRANSFER_TYPE_INTERRUPT:
419 MPStatus = OHCI_OpenInterruptEndpoint(OhciExtension,
420 EndpointProperties,
421 OhciEndpoint);
422 break;
423
424 default:
425 MPStatus = MP_STATUS_NOT_SUPPORTED;
426 break;
427 }
428
429 return MPStatus;
430 }
431
432 MPSTATUS
433 NTAPI
434 OHCI_ReopenEndpoint(IN PVOID ohciExtension,
435 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
436 IN PVOID ohciEndpoint)
437 {
438 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
439 POHCI_HCD_ED ED;
440
441 DPRINT_OHCI("OHCI_ReopenEndpoint: ... \n");
442
443 ED = OhciEndpoint->HcdED;
444
445 RtlCopyMemory(&OhciEndpoint->EndpointProperties,
446 EndpointProperties,
447 sizeof(OhciEndpoint->EndpointProperties));
448
449 ED->HwED.EndpointControl.FunctionAddress =
450 OhciEndpoint->EndpointProperties.DeviceAddress;
451
452 ED->HwED.EndpointControl.MaximumPacketSize =
453 OhciEndpoint->EndpointProperties.TotalMaxPacketSize;
454
455 return MP_STATUS_SUCCESS;
456 }
457
458 VOID
459 NTAPI
460 OHCI_QueryEndpointRequirements(IN PVOID ohciExtension,
461 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
462 IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements)
463 {
464 ULONG TransferType;
465
466 DPRINT_OHCI("OHCI_QueryEndpointRequirements: ... \n");
467
468 TransferType = EndpointProperties->TransferType;
469
470 switch (TransferType)
471 {
472 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
473 DPRINT_OHCI("OHCI_QueryEndpointRequirements: IsoTransfer\n");
474 EndpointRequirements->MaxTransferSize = OHCI_MAX_ISO_TRANSFER_SIZE;
475 EndpointRequirements->HeaderBufferSize =
476 sizeof(OHCI_HCD_ED) + OHCI_MAX_ISO_TD_COUNT * sizeof(OHCI_HCD_TD);
477 break;
478
479 case USBPORT_TRANSFER_TYPE_CONTROL:
480 DPRINT_OHCI("OHCI_QueryEndpointRequirements: ControlTransfer\n");
481 EndpointRequirements->MaxTransferSize = OHCI_MAX_CONTROL_TRANSFER_SIZE;
482 EndpointRequirements->HeaderBufferSize =
483 sizeof(OHCI_HCD_ED) + OHCI_MAX_CONTROL_TD_COUNT * sizeof(OHCI_HCD_TD);
484 break;
485
486 case USBPORT_TRANSFER_TYPE_BULK:
487 DPRINT_OHCI("OHCI_QueryEndpointRequirements: BulkTransfer\n");
488 EndpointRequirements->MaxTransferSize = OHCI_MAX_BULK_TRANSFER_SIZE;
489 EndpointRequirements->HeaderBufferSize =
490 sizeof(OHCI_HCD_ED) + OHCI_MAX_BULK_TD_COUNT * sizeof(OHCI_HCD_TD);
491 break;
492
493 case USBPORT_TRANSFER_TYPE_INTERRUPT:
494 DPRINT_OHCI("OHCI_QueryEndpointRequirements: InterruptTransfer\n");
495 EndpointRequirements->MaxTransferSize = OHCI_MAX_INTERRUPT_TRANSFER_SIZE;
496 EndpointRequirements->HeaderBufferSize =
497 sizeof(OHCI_HCD_ED) + OHCI_MAX_INTERRUPT_TD_COUNT * sizeof(OHCI_HCD_TD);
498 break;
499
500 default:
501 DPRINT1("OHCI_QueryEndpointRequirements: Unknown TransferType - %x\n",
502 TransferType);
503 DbgBreakPoint();
504 break;
505 }
506 }
507
508 VOID
509 NTAPI
510 OHCI_CloseEndpoint(IN PVOID ohciExtension,
511 IN PVOID ohciEndpoint,
512 IN BOOLEAN IsDoDisablePeriodic)
513 {
514 #if DBG
515 DPRINT1("OHCI_CloseEndpoint: Not supported\n");
516 #endif
517 return;
518 }
519
520 MPSTATUS
521 NTAPI
522 OHCI_TakeControlHC(IN POHCI_EXTENSION OhciExtension,
523 IN PUSBPORT_RESOURCES Resources)
524 {
525 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
526 PULONG ControlReg;
527 PULONG InterruptEnableReg;
528 PULONG InterruptDisableReg;
529 PULONG CommandStatusReg;
530 PULONG InterruptStatusReg;
531 OHCI_REG_CONTROL Control;
532 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
533 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable;
534 OHCI_REG_COMMAND_STATUS CommandStatus;
535 OHCI_REG_INTERRUPT_STATUS IntStatus;
536 LARGE_INTEGER EndTime;
537 LARGE_INTEGER SystemTime;
538
539 DPRINT("OHCI_TakeControlHC: ...\n");
540
541 OperationalRegs = OhciExtension->OperationalRegs;
542
543 ControlReg = (PULONG)&OperationalRegs->HcControl;
544 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
545 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
546 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
547 InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus;
548
549 /* 5.1.1.3 Take Control of Host Controller */
550 Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
551
552 if (Control.InterruptRouting == 0)
553 return MP_STATUS_SUCCESS;
554
555 DPRINT1("OHCI_TakeControlHC: detected Legacy BIOS\n");
556
557 IntEnable.AsULONG = READ_REGISTER_ULONG(InterruptEnableReg);
558
559 DPRINT("OHCI_TakeControlHC: Control - %lX, IntEnable - %lX\n",
560 Control.AsULONG,
561 IntEnable.AsULONG);
562
563 if (Control.HostControllerFunctionalState == OHCI_HC_STATE_RESET &&
564 IntEnable.AsULONG == 0)
565 {
566 Control.AsULONG = 0;
567 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
568 return MP_STATUS_SUCCESS;
569 }
570
571 /* Enable interrupt generations */
572 IntEnable.AsULONG = 0;
573 IntEnable.MasterInterruptEnable = 1;
574
575 WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG);
576
577 /* Request a change of control of the HC */
578 CommandStatus.AsULONG = 0;
579 CommandStatus.OwnershipChangeRequest = 1;
580
581 WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG);
582
583 /* Disable interrupt generation due to Root Hub Status Change */
584 IntDisable.AsULONG = 0;
585 IntDisable.RootHubStatusChange = 1;
586
587 WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG);
588
589 /* Monitoring the InterruptRouting bit
590 to determine when the ownership change has taken effect. */
591
592 KeQuerySystemTime(&EndTime);
593 EndTime.QuadPart += 500 * 10000; // 0.5 sec;
594
595 do
596 {
597 Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
598
599 if (Control.InterruptRouting == 0)
600 {
601 /* Clear all bits in register */
602 IntStatus.AsULONG = 0xFFFFFFFF;
603 WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG);
604
605 /* Disable interrupt generations */
606 IntDisable.AsULONG = 0;
607 IntDisable.MasterInterruptEnable = 1;
608
609 WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG);
610
611 return MP_STATUS_SUCCESS;
612 }
613
614 KeQuerySystemTime(&SystemTime);
615 }
616 while (SystemTime.QuadPart < EndTime.QuadPart);
617
618 return MP_STATUS_HW_ERROR;
619 }
620
621 MPSTATUS
622 NTAPI
623 OHCI_StartController(IN PVOID ohciExtension,
624 IN PUSBPORT_RESOURCES Resources)
625 {
626 POHCI_EXTENSION OhciExtension = ohciExtension;
627 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
628 PULONG CommandStatusReg;
629 PULONG FmIntervalReg;
630 PULONG ControlReg;
631 PULONG InterruptEnableReg;
632 PULONG RhStatusReg;
633 OHCI_REG_COMMAND_STATUS CommandStatus;
634 OHCI_REG_INTERRUPT_ENABLE_DISABLE Interrupts;
635 OHCI_REG_RH_STATUS RhStatus;
636 OHCI_REG_FRAME_INTERVAL FrameInterval;
637 ULONG MaxFrameIntervalAdjusting;
638 OHCI_REG_CONTROL Control;
639 UCHAR HeadIndex;
640 POHCI_ENDPOINT_DESCRIPTOR IntED;
641 ULONG_PTR IntEdPA;
642 POHCI_HCCA OhciHCCA;
643 LARGE_INTEGER SystemTime;
644 LARGE_INTEGER EndTime;
645 ULONG ix;
646 ULONG jx;
647 MPSTATUS MPStatus = MP_STATUS_SUCCESS;
648
649 DPRINT_OHCI("OHCI_StartController: ohciExtension - %p, Resources - %p\n",
650 ohciExtension,
651 Resources);
652
653 /* HC on-chip operational registers */
654 OperationalRegs = (POHCI_OPERATIONAL_REGISTERS)Resources->ResourceBase;
655 OhciExtension->OperationalRegs = OperationalRegs;
656
657 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
658 FmIntervalReg = (PULONG)&OperationalRegs->HcFmInterval;
659 ControlReg = (PULONG)&OperationalRegs->HcControl;
660 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
661 RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
662
663 /* 5.1.1 Initialization */
664
665 MPStatus = OHCI_TakeControlHC(OhciExtension, Resources);
666
667 if (MPStatus != MP_STATUS_SUCCESS)
668 {
669 DPRINT1("OHCI_StartController: OHCI_TakeControlHC return MPStatus - %x\n",
670 MPStatus);
671
672 return MPStatus;
673 }
674
675 OhciExtension->HcResourcesVA = Resources->StartVA;
676 OhciExtension->HcResourcesPA = Resources->StartPA;
677
678 DPRINT_OHCI("OHCI_StartController: HcResourcesVA - %p, HcResourcesPA - %p\n",
679 OhciExtension->HcResourcesVA,
680 OhciExtension->HcResourcesPA);
681
682 /* 5.2.7.2 Interrupt */
683
684 /* Build structure of interrupt static EDs */
685 for (ix = 0; ix < INTERRUPT_ENDPOINTs; ix++)
686 {
687 IntED = &OhciExtension->HcResourcesVA->InterrruptHeadED[ix];
688 IntEdPA = (ULONG_PTR)&OhciExtension->HcResourcesPA->InterrruptHeadED[ix];
689
690 if (ix == (ENDPOINT_INTERRUPT_1ms - 1))
691 {
692 HeadIndex = ED_EOF;
693 IntED->NextED = 0;
694 }
695 else
696 {
697 HeadIndex = ((ix - 1) / 2);
698
699 ASSERT(HeadIndex >= (ENDPOINT_INTERRUPT_1ms - 1) &&
700 HeadIndex < (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms));
701
702 IntED->NextED = OhciExtension->IntStaticED[HeadIndex].PhysicalAddress;
703 }
704
705 IntED->EndpointControl.sKip = 1;
706
707 IntED->TailPointer = 0;
708 IntED->HeadPointer = 0;
709
710 OhciExtension->IntStaticED[ix].HwED = IntED;
711 OhciExtension->IntStaticED[ix].PhysicalAddress = IntEdPA;
712 OhciExtension->IntStaticED[ix].HeadIndex = HeadIndex;
713 OhciExtension->IntStaticED[ix].pNextED = &IntED->NextED;
714 OhciExtension->IntStaticED[ix].Type = OHCI_STATIC_ED_TYPE_INTERRUPT;
715
716 InitializeListHead(&OhciExtension->IntStaticED[ix].Link);
717 }
718
719 OhciHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
720 DPRINT_OHCI("OHCI_InitializeSchedule: OhciHCCA - %p\n", OhciHCCA);
721
722 /* Set head pointers which start from HCCA */
723 for (ix = 0, jx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms);
724 ix < OHCI_NUMBER_OF_INTERRUPTS;
725 ix++, jx++)
726 {
727 OhciHCCA->InterrruptTable[Balance[ix]] =
728 OhciExtension->IntStaticED[jx].PhysicalAddress;
729
730 OhciExtension->IntStaticED[jx].pNextED =
731 (PULONG)&OhciHCCA->InterrruptTable[Balance[ix]];
732
733 OhciExtension->IntStaticED[jx].HccaIndex = Balance[ix];
734 }
735
736 DPRINT_OHCI("OHCI_InitializeSchedule: ix - %x\n", ix);
737
738 /* Init static Control and Bulk EDs head pointers which start from HCCA */
739 InitializeListHead(&OhciExtension->ControlStaticED.Link);
740
741 OhciExtension->ControlStaticED.HeadIndex = ED_EOF;
742 OhciExtension->ControlStaticED.Type = OHCI_STATIC_ED_TYPE_CONTROL;
743 OhciExtension->ControlStaticED.pNextED = &OperationalRegs->HcControlHeadED;
744
745 InitializeListHead(&OhciExtension->BulkStaticED.Link);
746
747 OhciExtension->BulkStaticED.HeadIndex = ED_EOF;
748 OhciExtension->BulkStaticED.Type = OHCI_STATIC_ED_TYPE_BULK;
749 OhciExtension->BulkStaticED.pNextED = &OperationalRegs->HcBulkHeadED;
750
751 /* 6.3.1 Frame Timing */
752 FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg);
753
754 MaxFrameIntervalAdjusting = OHCI_DEFAULT_FRAME_INTERVAL / 10; // 10%
755
756 if ((FrameInterval.FrameInterval) < (OHCI_DEFAULT_FRAME_INTERVAL - MaxFrameIntervalAdjusting) ||
757 (FrameInterval.FrameInterval) > (OHCI_DEFAULT_FRAME_INTERVAL + MaxFrameIntervalAdjusting))
758 {
759 FrameInterval.FrameInterval = OHCI_DEFAULT_FRAME_INTERVAL;
760 }
761
762 /* 5.4 FrameInterval Counter */
763 FrameInterval.FrameIntervalToggle = 1;
764
765 /* OHCI_MAXIMUM_OVERHEAD is the maximum overhead per frame */
766 FrameInterval.FSLargestDataPacket =
767 ((FrameInterval.FrameInterval - OHCI_MAXIMUM_OVERHEAD) * 6) / 7;
768
769 OhciExtension->FrameInterval = FrameInterval;
770
771 DPRINT_OHCI("OHCI_StartController: FrameInterval - %lX\n",
772 FrameInterval.AsULONG);
773
774 /* Reset HostController */
775 CommandStatus.AsULONG = 0;
776 CommandStatus.HostControllerReset = 1;
777
778 WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG);
779
780 KeStallExecutionProcessor(25);
781
782 Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
783 Control.HostControllerFunctionalState = OHCI_HC_STATE_RESET;
784
785 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
786
787 KeQuerySystemTime(&EndTime);
788 EndTime.QuadPart += 500 * 10000; // 0.5 sec
789
790 while (TRUE)
791 {
792 WRITE_REGISTER_ULONG(FmIntervalReg, OhciExtension->FrameInterval.AsULONG);
793 FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg);
794
795 KeQuerySystemTime(&SystemTime);
796
797 if (SystemTime.QuadPart >= EndTime.QuadPart)
798 {
799 MPStatus = MP_STATUS_HW_ERROR;
800 break;
801 }
802
803 if (FrameInterval.AsULONG == OhciExtension->FrameInterval.AsULONG)
804 {
805 MPStatus = MP_STATUS_SUCCESS;
806 break;
807 }
808 }
809
810 if (MPStatus != MP_STATUS_SUCCESS)
811 {
812 DPRINT_OHCI("OHCI_StartController: frame interval not set\n");
813 return MPStatus;
814 }
815
816 /* Setup HcPeriodicStart register */
817 WRITE_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart,
818 (OhciExtension->FrameInterval.FrameInterval * 9) / 10); //90%
819
820 /* Setup HcHCCA register */
821 WRITE_REGISTER_ULONG(&OperationalRegs->HcHCCA,
822 (ULONG)&OhciExtension->HcResourcesPA->HcHCCA);
823
824 /* Setup HcInterruptEnable register */
825 Interrupts.AsULONG = 0;
826
827 Interrupts.SchedulingOverrun = 1;
828 Interrupts.WritebackDoneHead = 1;
829 Interrupts.UnrecoverableError = 1;
830 Interrupts.FrameNumberOverflow = 1;
831 Interrupts.OwnershipChange = 1;
832
833 WRITE_REGISTER_ULONG(InterruptEnableReg, Interrupts.AsULONG);
834
835 /* Setup HcControl register */
836 Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
837
838 Control.ControlBulkServiceRatio = 0; // FIXME (1 : 1)
839 Control.PeriodicListEnable = 1;
840 Control.IsochronousEnable = 1;
841 Control.ControlListEnable = 1;
842 Control.BulkListEnable = 1;
843 Control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL;
844
845 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
846
847 /* Setup HcRhStatus register */
848 RhStatus.AsULONG = 0;
849 RhStatus.SetGlobalPower = 1;
850
851 WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG);
852
853 return MP_STATUS_SUCCESS;
854 }
855
856 VOID
857 NTAPI
858 OHCI_StopController(IN PVOID ohciExtension,
859 IN BOOLEAN IsDoDisableInterrupts)
860 {
861 POHCI_EXTENSION OhciExtension = ohciExtension;
862 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
863 PULONG ControlReg;
864 PULONG InterruptDisableReg;
865 PULONG InterruptStatusReg;
866 OHCI_REG_CONTROL Control;
867 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable;
868 OHCI_REG_INTERRUPT_STATUS IntStatus;
869
870 DPRINT("OHCI_StopController: ... \n");
871
872 OperationalRegs = OhciExtension->OperationalRegs;
873
874 ControlReg = (PULONG)&OperationalRegs->HcControl;
875 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
876 InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus;
877
878 /* Setup HcControl register */
879 Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
880
881 Control.PeriodicListEnable = 0;
882 Control.IsochronousEnable = 0;
883 Control.ControlListEnable = 0;
884 Control.BulkListEnable = 0;
885 Control.HostControllerFunctionalState = OHCI_HC_STATE_SUSPEND;
886 Control.RemoteWakeupEnable = 0;
887
888 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
889
890 /* Disable interrupt generations */
891 IntDisable.AsULONG = 0xFFFFFFFF;
892 WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG);
893
894 /* Clear all bits in HcInterruptStatus register */
895 IntStatus.AsULONG = 0xFFFFFFFF;
896 WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG);
897 }
898
899 VOID
900 NTAPI
901 OHCI_SuspendController(IN PVOID ohciExtension)
902 {
903 POHCI_EXTENSION OhciExtension = ohciExtension;
904 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
905 PULONG ControlReg;
906 PULONG InterruptEnableReg;
907 OHCI_REG_CONTROL Control;
908 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptReg;
909
910 DPRINT("OHCI_SuspendController: ... \n");
911
912 OperationalRegs = OhciExtension->OperationalRegs;
913 ControlReg = (PULONG)&OperationalRegs->HcControl;
914 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
915
916 /* Disable all interrupt generations */
917 WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptDisable.AsULONG,
918 0xFFFFFFFF);
919
920 /* Clear all bits in HcInterruptStatus register */
921 WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptStatus.AsULONG,
922 0xFFFFFFFF);
923
924 /* Setup HcControl register */
925 Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
926 Control.HostControllerFunctionalState = OHCI_HC_STATE_SUSPEND;
927 Control.RemoteWakeupEnable = 1;
928
929 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
930
931 /* Setup HcInterruptEnable register */
932 InterruptReg.AsULONG = 0;
933 InterruptReg.ResumeDetected = 1;
934 InterruptReg.UnrecoverableError = 1;
935 InterruptReg.RootHubStatusChange = 1;
936 InterruptReg.MasterInterruptEnable = 1;
937
938 WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptReg.AsULONG);
939 }
940
941 MPSTATUS
942 NTAPI
943 OHCI_ResumeController(IN PVOID ohciExtension)
944 {
945 POHCI_EXTENSION OhciExtension = ohciExtension;
946 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
947 PULONG ControlReg;
948 PULONG InterruptEnableReg;
949 POHCI_HCCA HcHCCA;
950 OHCI_REG_CONTROL control;
951 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptReg;
952
953 DPRINT("OHCI_ResumeController \n");
954
955 OperationalRegs = OhciExtension->OperationalRegs;
956 ControlReg = (PULONG)&OperationalRegs->HcControl;
957 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
958
959 control.AsULONG = READ_REGISTER_ULONG(ControlReg);
960
961 if (control.HostControllerFunctionalState != OHCI_HC_STATE_SUSPEND)
962 return MP_STATUS_HW_ERROR;
963
964 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
965 HcHCCA->Pad1 = 0;
966
967 /* Setup HcControl register */
968 control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL;
969 WRITE_REGISTER_ULONG(ControlReg, control.AsULONG);
970
971 /* Setup HcInterruptEnable register */
972 InterruptReg.AsULONG = 0;
973 InterruptReg.SchedulingOverrun = 1;
974 InterruptReg.WritebackDoneHead = 1;
975 InterruptReg.UnrecoverableError = 1;
976 InterruptReg.FrameNumberOverflow = 1;
977 InterruptReg.OwnershipChange = 1;
978
979 WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptReg.AsULONG);
980 WRITE_REGISTER_ULONG(ControlReg, control.AsULONG);
981
982 return MP_STATUS_SUCCESS;
983 }
984
985 BOOLEAN
986 NTAPI
987 OHCI_HardwarePresent(IN POHCI_EXTENSION OhciExtension,
988 IN BOOLEAN IsInvalidateController)
989 {
990 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
991 PULONG CommandStatusReg;
992
993 OperationalRegs = OhciExtension->OperationalRegs;
994 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
995
996 if (READ_REGISTER_ULONG(CommandStatusReg) != 0xFFFFFFFF)
997 return TRUE;
998
999 DPRINT1("OHCI_HardwarePresent: IsInvalidateController - %x\n",
1000 IsInvalidateController);
1001
1002 if (IsInvalidateController)
1003 {
1004 RegPacket.UsbPortInvalidateController(OhciExtension,
1005 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
1006 }
1007
1008 return FALSE;
1009 }
1010
1011 BOOLEAN
1012 NTAPI
1013 OHCI_InterruptService(IN PVOID ohciExtension)
1014 {
1015 POHCI_EXTENSION OhciExtension = ohciExtension;
1016 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
1017 OHCI_REG_INTERRUPT_STATUS IntStatus;
1018 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
1019 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable;
1020 BOOLEAN HardwarePresent = FALSE;
1021
1022 DPRINT_OHCI("OHCI_Interrupt: Ext %p\n", OhciExtension);
1023
1024 OperationalRegs = OhciExtension->OperationalRegs;
1025
1026 HardwarePresent = OHCI_HardwarePresent(OhciExtension, FALSE);
1027
1028 if (!HardwarePresent)
1029 return FALSE;
1030
1031 IntEnable.AsULONG = READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptEnable);
1032 IntStatus.AsULONG = READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptStatus) & IntEnable.AsULONG;
1033
1034 if ((IntStatus.AsULONG == 0) || (IntEnable.MasterInterruptEnable == 0))
1035 return FALSE;
1036
1037 if (IntStatus.UnrecoverableError)
1038 DPRINT1("OHCI_InterruptService: IntStatus.UnrecoverableError\n");
1039
1040 if (IntStatus.FrameNumberOverflow)
1041 {
1042 POHCI_HCCA HcHCCA;
1043 ULONG fm;
1044 ULONG hp;
1045
1046 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
1047
1048 DPRINT("FrameNumberOverflow %lX\n", HcHCCA->FrameNumber);
1049
1050 hp = OhciExtension->FrameHighPart;
1051 fm = HcHCCA->FrameNumber;
1052
1053 /* Increment value of FrameHighPart */
1054 OhciExtension->FrameHighPart += 1 * (1 << 16) - ((hp ^ fm) & 0x8000);
1055 }
1056
1057 /* Disable interrupt generation */
1058 IntDisable.AsULONG = 0;
1059 IntDisable.MasterInterruptEnable = 1;
1060 WRITE_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptDisable,
1061 IntDisable.AsULONG);
1062
1063 return TRUE;
1064 }
1065
1066 VOID
1067 NTAPI
1068 OHCI_InterruptDpc(IN PVOID ohciExtension,
1069 IN BOOLEAN IsDoEnableInterrupts)
1070 {
1071 POHCI_EXTENSION OhciExtension = ohciExtension;
1072 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
1073 PULONG InterruptDisableReg;
1074 PULONG InterruptEnableReg;
1075 PULONG InterruptStatusReg;
1076 OHCI_REG_INTERRUPT_STATUS IntStatus;
1077 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptBits;
1078 POHCI_HCCA HcHCCA;
1079
1080 OperationalRegs = OhciExtension->OperationalRegs;
1081
1082 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
1083 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
1084 InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus;
1085
1086 DPRINT_OHCI("OHCI_InterruptDpc: OhciExtension - %p, IsDoEnableInterrupts - %x\n",
1087 OhciExtension,
1088 IsDoEnableInterrupts);
1089
1090 IntStatus.AsULONG = READ_REGISTER_ULONG(InterruptStatusReg);
1091
1092 if (IntStatus.RootHubStatusChange)
1093 {
1094 DPRINT_OHCI("OHCI_InterruptDpc: RootHubStatusChange\n");
1095 RegPacket.UsbPortInvalidateRootHub(OhciExtension);
1096 }
1097
1098 if (IntStatus.WritebackDoneHead)
1099 {
1100 DPRINT_OHCI("OHCI_InterruptDpc: WritebackDoneHead\n");
1101
1102 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
1103 HcHCCA->DoneHead = 0;
1104
1105 RegPacket.UsbPortInvalidateEndpoint(OhciExtension, NULL);
1106 }
1107
1108 if (IntStatus.StartofFrame)
1109 {
1110 /* Disable interrupt generation due to Start of Frame */
1111 InterruptBits.AsULONG = 0;
1112 InterruptBits.StartofFrame = 1;
1113
1114 WRITE_REGISTER_ULONG(InterruptDisableReg, InterruptBits.AsULONG);
1115 }
1116
1117 if (IntStatus.ResumeDetected)
1118 DPRINT1("OHCI_IntDpc: ResumeDetected\n");
1119
1120 if (IntStatus.UnrecoverableError)
1121 {
1122 DPRINT1("OHCI_IntDpc: UnrecoverableError\n");
1123 }
1124
1125 WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG);
1126
1127 if (IsDoEnableInterrupts)
1128 {
1129 /* Enable interrupt generation */
1130 InterruptBits.AsULONG = 0;
1131 InterruptBits.MasterInterruptEnable = 1;
1132
1133 WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptBits.AsULONG);
1134 }
1135 }
1136
1137 ULONG
1138 NTAPI
1139 OHCI_MapTransferToTD(IN POHCI_EXTENSION OhciExtension,
1140 IN ULONG MaxPacketSize,
1141 IN OUT ULONG TransferedLen,
1142 IN POHCI_TRANSFER OhciTransfer,
1143 IN POHCI_HCD_TD TD,
1144 IN PUSBPORT_SCATTER_GATHER_LIST SGList)
1145 {
1146 PUSBPORT_SCATTER_GATHER_ELEMENT SgElement;
1147 ULONG SgIdx;
1148 ULONG SgRemain;
1149 ULONG LengthThisTd;
1150 ULONG BufferEnd;
1151 ULONG Offset;
1152 ULONG TransferLength;
1153 ULONG Buffer;
1154
1155 DPRINT_OHCI("OHCI_MapTransferToTD: TransferedLen - %x\n", TransferedLen);
1156
1157 for (SgIdx = 0; SgIdx < SGList->SgElementCount; SgIdx++)
1158 {
1159 SgElement = &SGList->SgElement[SgIdx];
1160
1161 if (TransferedLen >= SgElement->SgOffset &&
1162 TransferedLen < SgElement->SgOffset + SgElement->SgTransferLength)
1163 {
1164 break;
1165 }
1166 }
1167
1168 DPRINT_OHCI("OHCI_MapTransferToTD: SgIdx - %x, SgCount - %x\n",
1169 SgIdx,
1170 SGList->SgElementCount);
1171
1172 ASSERT(SgIdx < SGList->SgElementCount);
1173
1174 Offset = TransferedLen - SGList->SgElement[SgIdx].SgOffset;
1175 Buffer = SGList->SgElement[SgIdx].SgPhysicalAddress.LowPart + Offset;
1176
1177 SgRemain = SGList->SgElementCount - SgIdx;
1178
1179 if (SgRemain == 1)
1180 {
1181 LengthThisTd = OhciTransfer->TransferParameters->TransferBufferLength -
1182 TransferedLen -
1183 Offset;
1184
1185 BufferEnd = SGList->SgElement[SgIdx].SgPhysicalAddress.LowPart +
1186 LengthThisTd;
1187 }
1188 else if (SgRemain == 2)
1189 {
1190 LengthThisTd = OhciTransfer->TransferParameters->TransferBufferLength -
1191 TransferedLen;
1192
1193 BufferEnd = SGList->SgElement[SgIdx + 1].SgPhysicalAddress.LowPart +
1194 SGList->SgElement[SgIdx + 1].SgTransferLength;
1195 }
1196 else
1197 {
1198 TransferLength = SGList->SgElement[SgIdx].SgTransferLength +
1199 SGList->SgElement[SgIdx+1].SgTransferLength -
1200 Offset;
1201
1202 BufferEnd = SGList->SgElement[SgIdx + 1].SgPhysicalAddress.LowPart +
1203 SGList->SgElement[SgIdx + 1].SgTransferLength;
1204
1205 LengthThisTd = MaxPacketSize * (TransferLength / MaxPacketSize);
1206
1207 if (TransferLength > LengthThisTd)
1208 BufferEnd -= (TransferLength - LengthThisTd);
1209 }
1210
1211 TD->HwTD.gTD.CurrentBuffer = Buffer;
1212 TD->HwTD.gTD.BufferEnd = BufferEnd - 1;
1213 TD->TransferLen = LengthThisTd;
1214
1215 return TransferedLen + LengthThisTd;
1216 }
1217
1218 POHCI_HCD_TD
1219 NTAPI
1220 OHCI_AllocateTD(IN POHCI_EXTENSION OhciExtension,
1221 IN POHCI_ENDPOINT OhciEndpoint)
1222 {
1223 POHCI_HCD_TD TD;
1224
1225 DPRINT_OHCI("OHCI_AllocateTD: ... \n");
1226
1227 TD = OhciEndpoint->FirstTD;
1228
1229 while (TD->Flags & OHCI_HCD_TD_FLAG_ALLOCATED)
1230 {
1231 TD += 1;
1232 }
1233
1234 TD->Flags |= OHCI_HCD_TD_FLAG_ALLOCATED;
1235
1236 return TD;
1237 }
1238
1239 ULONG
1240 NTAPI
1241 OHCI_RemainTDs(IN POHCI_EXTENSION OhciExtension,
1242 IN POHCI_ENDPOINT OhciEndpoint)
1243 {
1244 POHCI_HCD_TD TD;
1245 ULONG MaxTDs;
1246 ULONG RemainTDs;
1247 ULONG ix;
1248
1249 DPRINT_OHCI("OHCI_RemainTDs: ... \n");
1250
1251 MaxTDs = OhciEndpoint->MaxTransferDescriptors;
1252 TD = (POHCI_HCD_TD)OhciEndpoint->FirstTD;
1253
1254 RemainTDs = 0;
1255
1256 for (ix = 0; ix < MaxTDs; ix++)
1257 {
1258 if (!(TD->Flags & OHCI_HCD_TD_FLAG_ALLOCATED))
1259 RemainTDs++;
1260
1261 TD += 1;
1262 }
1263
1264 return RemainTDs;
1265 }
1266
1267 MPSTATUS
1268 NTAPI
1269 OHCI_ControlTransfer(IN POHCI_EXTENSION OhciExtension,
1270 IN POHCI_ENDPOINT OhciEndpoint,
1271 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
1272 IN POHCI_TRANSFER OhciTransfer,
1273 IN PUSBPORT_SCATTER_GATHER_LIST SGList)
1274 {
1275 POHCI_HCD_TD FirstTD;
1276 POHCI_HCD_TD FirstTdPA;
1277 POHCI_HCD_TD TD;
1278 POHCI_HCD_TD TD2;
1279 POHCI_HCD_TD PrevTD;
1280 POHCI_HCD_TD NextTD;
1281 ULONG MaxTDs;
1282 ULONG TransferedLen;
1283 ULONG MaxPacketSize;
1284 ULONG BufferEnd;
1285 UCHAR DataToggle;
1286
1287 DPRINT_OHCI("OHCI_ControlTransfer: Ext %p, Endpoint %p\n",
1288 OhciExtension,
1289 OhciEndpoint);
1290
1291 MaxTDs = OHCI_RemainTDs(OhciExtension, OhciEndpoint);
1292
1293 if ((SGList->SgElementCount + OHCI_NON_DATA_CONTROL_TDS) > MaxTDs)
1294 return MP_STATUS_FAILURE;
1295
1296 FirstTD = OhciEndpoint->HcdTailP;
1297 FirstTD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
1298
1299 FirstTD->HwTD.gTD.NextTD = 0;
1300 FirstTD->HwTD.gTD.CurrentBuffer = 0;
1301 FirstTD->HwTD.gTD.BufferEnd = 0;
1302
1303 FirstTD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED;
1304 FirstTD->NextHcdTD = 0;
1305 FirstTD->OhciTransfer = (ULONG)OhciTransfer;
1306
1307 FirstTD->HwTD.Padded[0] = 0;
1308 FirstTD->HwTD.Padded[1] = 0;
1309
1310 OhciTransfer->PendingTDs++;
1311
1312 RtlCopyMemory(&FirstTD->HwTD.SetupPacket,
1313 &TransferParameters->SetupPacket,
1314 sizeof(FirstTD->HwTD.SetupPacket));
1315
1316 FirstTdPA = (POHCI_HCD_TD)FirstTD->PhysicalAddress;
1317
1318 FirstTD->HwTD.gTD.CurrentBuffer = (ULONG)&FirstTdPA->HwTD.SetupPacket;
1319
1320 BufferEnd = (ULONG_PTR)&FirstTdPA->HwTD.SetupPacket +
1321 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET) - 1;
1322
1323 FirstTD->HwTD.gTD.BufferEnd = BufferEnd;
1324
1325 FirstTD->HwTD.gTD.Control.AsULONG = 0;
1326 FirstTD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
1327 FirstTD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED;
1328 FirstTD->HwTD.gTD.Control.DataToggle = OHCI_TD_DATA_TOGGLE_DATA0;
1329
1330 TD2 = OHCI_AllocateTD(OhciExtension, OhciEndpoint);
1331
1332 TD2->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
1333 TD2->HwTD.gTD.CurrentBuffer = 0;
1334 TD2->HwTD.gTD.BufferEnd = 0;
1335 TD2->HwTD.gTD.NextTD = 0;
1336
1337 TD2->Flags |= OHCI_HCD_TD_FLAG_PROCESSED;
1338 TD2->NextHcdTD = 0;
1339 TD2->OhciTransfer = (ULONG)OhciTransfer;
1340
1341 RtlZeroMemory(&TD2->HwTD.SetupPacket,
1342 sizeof(TD2->HwTD.SetupPacket));
1343
1344 TD2->HwTD.Padded[0] = 0;
1345 TD2->HwTD.Padded[1] = 0;
1346
1347 PrevTD = FirstTD;
1348 TD = TD2;
1349
1350 PrevTD->HwTD.gTD.NextTD = TD2->PhysicalAddress;
1351 PrevTD->NextHcdTD = (ULONG)TD2;
1352
1353 MaxPacketSize = OhciEndpoint->EndpointProperties.TotalMaxPacketSize;
1354
1355 TransferedLen = 0;
1356 DataToggle = OHCI_TD_DATA_TOGGLE_DATA1;
1357
1358 while (TransferedLen < TransferParameters->TransferBufferLength)
1359 {
1360 OhciTransfer->PendingTDs++;
1361
1362 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1363 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN;
1364 else
1365 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT;
1366
1367 TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
1368 TD->HwTD.gTD.Control.DataToggle = DataToggle;
1369 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED;
1370
1371 DataToggle = OHCI_TD_DATA_TOGGLE_FROM_ED;
1372
1373 TransferedLen = OHCI_MapTransferToTD(OhciExtension,
1374 MaxPacketSize,
1375 TransferedLen,
1376 OhciTransfer,
1377 TD,
1378 SGList);
1379
1380 PrevTD = TD;
1381
1382 TD = OHCI_AllocateTD(OhciExtension, OhciEndpoint);
1383
1384 TD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED;
1385
1386 TD->HwTD.gTD.NextTD = 0;
1387 TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
1388
1389 TD->NextHcdTD = 0;
1390 TD->OhciTransfer = (ULONG)OhciTransfer;
1391
1392 TD->HwTD.gTD.CurrentBuffer = 0;
1393 TD->HwTD.gTD.BufferEnd = 0;
1394
1395 RtlZeroMemory(&TD->HwTD.SetupPacket,
1396 sizeof(TD->HwTD.SetupPacket));
1397
1398 TD->HwTD.Padded[0] = 0;
1399 TD->HwTD.Padded[1] = 0;
1400
1401 PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress;
1402 PrevTD->NextHcdTD = (ULONG)TD;
1403 }
1404
1405 if (TransferParameters->TransferFlags & USBD_SHORT_TRANSFER_OK)
1406 {
1407 PrevTD->HwTD.gTD.Control.BufferRounding = TRUE;
1408 OhciTransfer->Flags |= OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK;
1409 }
1410
1411 TD->HwTD.gTD.CurrentBuffer = 0;
1412 TD->HwTD.gTD.BufferEnd = 0;
1413
1414 TD->Flags |= OHCI_HCD_TD_FLAG_CONTROL_STATUS;
1415 TD->TransferLen = 0;
1416
1417 TD->HwTD.gTD.Control.AsULONG = 0;
1418
1419 if ((TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) != 0)
1420 {
1421 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT;
1422 }
1423 else
1424 {
1425 TD->HwTD.gTD.Control.BufferRounding = TRUE;
1426 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN;
1427 }
1428
1429 TD->HwTD.gTD.Control.DataToggle = OHCI_TD_DATA_TOGGLE_DATA1;
1430 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED;
1431
1432 OhciTransfer->PendingTDs++;
1433 OhciTransfer->ControlStatusTD = TD;
1434
1435 NextTD = OHCI_AllocateTD(OhciExtension, OhciEndpoint);
1436
1437 TD->HwTD.gTD.NextTD = NextTD->PhysicalAddress;
1438 TD->NextHcdTD = (ULONG)NextTD;
1439
1440 NextTD->NextHcdTD = 0;
1441 NextTD->HwTD.gTD.NextTD = 0;
1442
1443 OhciTransfer->NextTD = NextTD;
1444 OhciEndpoint->HcdTailP = NextTD;
1445
1446 OhciEndpoint->HcdED->HwED.TailPointer = NextTD->PhysicalAddress;
1447
1448 OHCI_EnableList(OhciExtension, OhciEndpoint);
1449
1450 return MP_STATUS_SUCCESS;
1451 }
1452
1453 MPSTATUS
1454 NTAPI
1455 OHCI_BulkOrInterruptTransfer(IN POHCI_EXTENSION OhciExtension,
1456 IN POHCI_ENDPOINT OhciEndpoint,
1457 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
1458 IN POHCI_TRANSFER OhciTransfer,
1459 IN PUSBPORT_SCATTER_GATHER_LIST SGList)
1460 {
1461 POHCI_HCD_TD TD;
1462 POHCI_HCD_TD PrevTD;
1463 ULONG TransferedLen;
1464 ULONG MaxTDs;
1465 ULONG MaxPacketSize;
1466
1467 DPRINT_OHCI("OHCI_BulkOrInterruptTransfer: ... \n");
1468
1469 MaxTDs = OHCI_RemainTDs(OhciExtension, OhciEndpoint);
1470
1471 if (SGList->SgElementCount > MaxTDs)
1472 return MP_STATUS_FAILURE;
1473
1474 TD = OhciEndpoint->HcdTailP;
1475
1476 TransferedLen = 0;
1477
1478 do
1479 {
1480 TD->HwTD.gTD.Control.AsULONG = 0;
1481 TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
1482 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED;
1483
1484 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1485 {
1486 TD->HwTD.gTD.Control.BufferRounding = 0;
1487 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN;
1488 }
1489 else
1490 {
1491 TD->HwTD.gTD.Control.BufferRounding = TRUE;
1492 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT;
1493 }
1494
1495 TD->HwTD.gTD.CurrentBuffer = 0;
1496 TD->HwTD.gTD.NextTD = 0;
1497 TD->HwTD.gTD.BufferEnd = 0;
1498
1499 RtlZeroMemory(&TD->HwTD.SetupPacket,
1500 sizeof(TD->HwTD.SetupPacket));
1501
1502 TD->HwTD.Padded[0] = 0;
1503 TD->HwTD.Padded[1] = 0;
1504
1505 TD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED;
1506 TD->OhciTransfer = (ULONG)OhciTransfer;
1507 TD->NextHcdTD = 0;
1508
1509 if (TransferParameters->TransferBufferLength)
1510 {
1511 MaxPacketSize = OhciEndpoint->EndpointProperties.TotalMaxPacketSize;
1512
1513 TransferedLen = OHCI_MapTransferToTD(OhciExtension,
1514 MaxPacketSize,
1515 TransferedLen,
1516 OhciTransfer,
1517 TD,
1518 SGList);
1519 }
1520 else
1521 {
1522 ASSERT(SGList->SgElementCount == 0);
1523
1524 TD->HwTD.gTD.CurrentBuffer = 0;
1525 TD->HwTD.gTD.BufferEnd = 0;
1526
1527 TD->TransferLen = 0;
1528 }
1529
1530 PrevTD = TD;
1531
1532 TD = OHCI_AllocateTD(OhciExtension, OhciEndpoint);
1533 OhciTransfer->PendingTDs++;
1534
1535 PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress;
1536 PrevTD->NextHcdTD = (ULONG)TD;
1537 }
1538 while (TransferedLen < TransferParameters->TransferBufferLength);
1539
1540 if (TransferParameters->TransferFlags & USBD_SHORT_TRANSFER_OK)
1541 {
1542 PrevTD->HwTD.gTD.Control.BufferRounding = TRUE;
1543 OhciTransfer->Flags |= OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK;
1544 }
1545
1546 PrevTD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_IMMEDIATE;
1547 PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress;
1548 PrevTD->NextHcdTD = (ULONG)TD;
1549
1550 TD->HwTD.gTD.NextTD = 0;
1551 TD->NextHcdTD = 0;
1552
1553 OhciTransfer->NextTD = TD;
1554 OhciEndpoint->HcdTailP = TD;
1555
1556 OhciEndpoint->HcdED->HwED.TailPointer = TD->PhysicalAddress;
1557
1558 OHCI_EnableList(OhciExtension, OhciEndpoint);
1559
1560 return MP_STATUS_SUCCESS;
1561 }
1562
1563 MPSTATUS
1564 NTAPI
1565 OHCI_SubmitTransfer(IN PVOID ohciExtension,
1566 IN PVOID ohciEndpoint,
1567 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
1568 IN PVOID ohciTransfer,
1569 IN PUSBPORT_SCATTER_GATHER_LIST SGList)
1570 {
1571 POHCI_EXTENSION OhciExtension = ohciExtension;
1572 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
1573 POHCI_TRANSFER OhciTransfer = ohciTransfer;
1574 ULONG TransferType;
1575
1576 DPRINT_OHCI("OHCI_SubmitTransfer: ... \n");
1577
1578 RtlZeroMemory(OhciTransfer, sizeof(OHCI_TRANSFER));
1579
1580 OhciTransfer->TransferParameters = TransferParameters;
1581 OhciTransfer->OhciEndpoint = OhciEndpoint;
1582
1583 TransferType = OhciEndpoint->EndpointProperties.TransferType;
1584
1585 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
1586 {
1587 return OHCI_ControlTransfer(OhciExtension,
1588 OhciEndpoint,
1589 TransferParameters,
1590 OhciTransfer,
1591 SGList);
1592 }
1593
1594 if (TransferType == USBPORT_TRANSFER_TYPE_BULK ||
1595 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1596 {
1597 return OHCI_BulkOrInterruptTransfer(OhciExtension,
1598 OhciEndpoint,
1599 TransferParameters,
1600 OhciTransfer,
1601 SGList);
1602 }
1603
1604 return MP_STATUS_FAILURE;
1605 }
1606
1607 MPSTATUS
1608 NTAPI
1609 OHCI_SubmitIsoTransfer(IN PVOID ohciExtension,
1610 IN PVOID ohciEndpoint,
1611 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
1612 IN PVOID ohciTransfer,
1613 IN PVOID isoParameters)
1614 {
1615 DPRINT1("OHCI_SubmitIsoTransfer: UNIMPLEMENTED. FIXME\n");
1616 return MP_STATUS_SUCCESS;
1617 }
1618
1619 VOID
1620 NTAPI
1621 OHCI_ProcessDoneTD(IN POHCI_EXTENSION OhciExtension,
1622 IN POHCI_HCD_TD TD,
1623 IN BOOLEAN IsPortComplete)
1624 {
1625 POHCI_TRANSFER OhciTransfer;
1626 POHCI_ENDPOINT OhciEndpoint;
1627 ULONG Buffer;
1628 ULONG BufferEnd;
1629 ULONG Length;
1630
1631 DPRINT_OHCI("OHCI_ProcessDoneTD: ... \n");
1632
1633 OhciTransfer = (POHCI_TRANSFER)TD->OhciTransfer;
1634 OhciEndpoint = OhciTransfer->OhciEndpoint;
1635
1636 OhciTransfer->PendingTDs--;
1637
1638 Buffer = TD->HwTD.gTD.CurrentBuffer;
1639 BufferEnd = TD->HwTD.gTD.BufferEnd;
1640
1641 if (TD->Flags & OHCI_HCD_TD_FLAG_NOT_ACCESSED)
1642 {
1643 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NO_ERROR;
1644 }
1645 else
1646 {
1647 if (TD->HwTD.gTD.CurrentBuffer)
1648 {
1649 if (TD->TransferLen)
1650 {
1651 Length = (BufferEnd & (PAGE_SIZE - 1)) -
1652 (Buffer & (PAGE_SIZE - 1));
1653
1654 Length++;
1655
1656 if (Buffer >> PAGE_SHIFT != BufferEnd >> PAGE_SHIFT)
1657 Length += PAGE_SIZE;
1658
1659 TD->TransferLen -= Length;
1660 }
1661 }
1662
1663 if (TD->HwTD.gTD.Control.DirectionPID != OHCI_TD_DIRECTION_PID_SETUP)
1664 OhciTransfer->TransferLen += TD->TransferLen;
1665
1666 if (TD->HwTD.gTD.Control.ConditionCode)
1667 {
1668 OhciTransfer->USBDStatus = USBD_STATUS_HALTED |
1669 TD->HwTD.gTD.Control.ConditionCode;
1670 }
1671 }
1672
1673 TD->Flags = 0;
1674 TD->HwTD.gTD.NextTD = 0;
1675 TD->OhciTransfer = 0;
1676
1677 TD->DoneLink.Flink = NULL;
1678 TD->DoneLink.Blink = NULL;
1679
1680 if (IsPortComplete && (OhciTransfer->PendingTDs == 0))
1681 {
1682 RegPacket.UsbPortCompleteTransfer(OhciExtension,
1683 OhciEndpoint,
1684 OhciTransfer->TransferParameters,
1685 OhciTransfer->USBDStatus,
1686 OhciTransfer->TransferLen);
1687 }
1688 }
1689
1690 VOID
1691 NTAPI
1692 OHCI_ProcessDoneIsoTD(IN POHCI_EXTENSION OhciExtension,
1693 IN POHCI_HCD_TD TD,
1694 IN BOOLEAN IsPortComplete)
1695 {
1696 DPRINT1("OHCI_ProcessDoneIsoTD: UNIMPLEMENTED. FIXME\n");
1697 }
1698
1699 VOID
1700 NTAPI
1701 OHCI_AbortTransfer(IN PVOID ohciExtension,
1702 IN PVOID ohciEndpoint,
1703 IN PVOID ohciTransfer,
1704 IN OUT PULONG CompletedLength)
1705 {
1706 POHCI_EXTENSION OhciExtension = ohciExtension;
1707 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
1708 POHCI_TRANSFER OhciTransfer = ohciTransfer;
1709 POHCI_TRANSFER TmpTransfer;
1710 POHCI_HCD_ED ED;
1711 ULONG_PTR NextTdPA;
1712 POHCI_HCD_TD NextTD;
1713 POHCI_HCD_TD TD;
1714 POHCI_HCD_TD PrevTD;
1715 POHCI_HCD_TD LastTD;
1716 POHCI_HCD_TD td = NULL;
1717 ULONG ix;
1718 BOOLEAN IsIsoEndpoint = FALSE;
1719 BOOLEAN IsProcessed = FALSE;
1720
1721 DPRINT("OHCI_AbortTransfer: ohciEndpoint - %p, ohciTransfer - %p\n",
1722 OhciEndpoint,
1723 OhciTransfer);
1724
1725 if (OhciEndpoint->EndpointProperties.TransferType ==
1726 USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1727 {
1728 IsIsoEndpoint = TRUE;
1729 }
1730
1731 ED = OhciEndpoint->HcdED;
1732 NextTdPA = ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_MASK;
1733
1734 NextTD = RegPacket.UsbPortGetMappedVirtualAddress((PVOID)NextTdPA,
1735 OhciExtension,
1736 OhciEndpoint);
1737
1738 if (NextTD->OhciTransfer == (ULONG)OhciTransfer)
1739 {
1740 LastTD = OhciTransfer->NextTD;
1741
1742 ED->HwED.HeadPointer = LastTD->PhysicalAddress |
1743 (ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_CARRY);
1744
1745 OhciEndpoint->HcdHeadP = LastTD;
1746
1747 for (ix = 0; ix < OhciEndpoint->MaxTransferDescriptors; ix++)
1748 {
1749 TD = &OhciEndpoint->FirstTD[ix];
1750
1751 if (TD->OhciTransfer == (ULONG)OhciTransfer)
1752 {
1753 if (IsIsoEndpoint)
1754 OHCI_ProcessDoneIsoTD(OhciExtension, TD, FALSE);
1755 else
1756 OHCI_ProcessDoneTD(OhciExtension, TD, FALSE);
1757 }
1758 }
1759
1760 *CompletedLength = OhciTransfer->TransferLen;
1761 return;
1762 }
1763
1764 TD = OhciEndpoint->HcdHeadP;
1765
1766 if (TD == NextTD)
1767 goto Exit;
1768
1769 do
1770 {
1771 if (TD->OhciTransfer == (ULONG)ohciTransfer)
1772 {
1773 PrevTD = TD;
1774 TD = (POHCI_HCD_TD)TD->NextHcdTD;
1775
1776 if (PrevTD == OhciEndpoint->HcdHeadP)
1777 OhciEndpoint->HcdHeadP = TD;
1778
1779 if (IsIsoEndpoint)
1780 OHCI_ProcessDoneIsoTD(OhciExtension, PrevTD, FALSE);
1781 else
1782 OHCI_ProcessDoneTD(OhciExtension, PrevTD, FALSE);
1783
1784 IsProcessed = TRUE;
1785 }
1786 else
1787 {
1788 TD = (POHCI_HCD_TD)TD->NextHcdTD;
1789 }
1790 }
1791 while (TD != NextTD);
1792
1793 if (!IsProcessed)
1794 {
1795 TD = OhciEndpoint->HcdHeadP;
1796
1797 LastTD = TD;
1798 td = NULL;
1799
1800 while (TD != OhciEndpoint->HcdTailP)
1801 {
1802 if (TD->OhciTransfer == (ULONG)OhciTransfer)
1803 {
1804 td = TD;
1805 break;
1806 }
1807
1808 LastTD = TD;
1809
1810 TD = (POHCI_HCD_TD)TD->NextHcdTD;
1811 }
1812
1813 TD = td;
1814
1815 do
1816 {
1817 if (TD == OhciEndpoint->HcdTailP)
1818 break;
1819
1820 PrevTD = TD;
1821 TD = (POHCI_HCD_TD)TD->NextHcdTD;
1822
1823 if (IsIsoEndpoint)
1824 OHCI_ProcessDoneIsoTD(OhciExtension, PrevTD, FALSE);
1825 else
1826 OHCI_ProcessDoneTD(OhciExtension, PrevTD, FALSE);
1827 }
1828 while (TD->OhciTransfer == (ULONG)OhciTransfer);
1829
1830 TmpTransfer = (POHCI_TRANSFER)LastTD->OhciTransfer;
1831 TmpTransfer->NextTD = TD;
1832
1833 LastTD->NextHcdTD = (ULONG)TD;
1834 LastTD->HwTD.gTD.NextTD = TD->PhysicalAddress;
1835 }
1836
1837 Exit:
1838
1839 *CompletedLength = OhciTransfer->TransferLen;
1840
1841 if (OhciTransfer->TransferLen)
1842 {
1843 DPRINT("OHCI_AbortTransfer: *CompletedLength - %x\n", *CompletedLength);
1844 }
1845 }
1846
1847 ULONG
1848 NTAPI
1849 OHCI_GetEndpointState(IN PVOID ohciExtension,
1850 IN PVOID ohciEndpoint)
1851 {
1852 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
1853 POHCI_HCD_ED ED;
1854
1855 DPRINT_OHCI("OHCI_GetEndpointState: ... \n");
1856
1857 ED = OhciEndpoint->HcdED;
1858
1859 if (ED->Flags & OHCI_HCD_TD_FLAG_NOT_ACCESSED)
1860 return USBPORT_ENDPOINT_REMOVE;
1861
1862 if (ED->HwED.EndpointControl.sKip)
1863 return USBPORT_ENDPOINT_PAUSED;
1864
1865 return USBPORT_ENDPOINT_ACTIVE;
1866 }
1867
1868 VOID
1869 NTAPI
1870 OHCI_RemoveEndpointFromSchedule(IN POHCI_ENDPOINT OhciEndpoint)
1871 {
1872 POHCI_HCD_ED ED;
1873 POHCI_HCD_ED PreviousED;
1874 POHCI_STATIC_ED HeadED;
1875
1876 DPRINT_OHCI("OHCI_RemoveEndpointFromSchedule \n");
1877
1878 ED = OhciEndpoint->HcdED;
1879 HeadED = OhciEndpoint->HeadED;
1880
1881 if (&HeadED->Link == ED->HcdEDLink.Blink)
1882 {
1883 if (HeadED->Type == OHCI_STATIC_ED_TYPE_CONTROL ||
1884 HeadED->Type == OHCI_STATIC_ED_TYPE_BULK)
1885 {
1886 WRITE_REGISTER_ULONG(HeadED->pNextED, ED->HwED.NextED);
1887 }
1888 else if (HeadED->Type == OHCI_STATIC_ED_TYPE_INTERRUPT)
1889 {
1890 *HeadED->pNextED = ED->HwED.NextED;
1891 }
1892 else
1893 {
1894 DPRINT1("OHCI_RemoveEndpointFromSchedule: Unknown HeadED->Type - %x\n",
1895 HeadED->Type);
1896 DbgBreakPoint();
1897 }
1898 }
1899 else
1900 {
1901 PreviousED = CONTAINING_RECORD(ED->HcdEDLink.Blink,
1902 OHCI_HCD_ED,
1903 HcdEDLink);
1904
1905 PreviousED->HwED.NextED = ED->HwED.NextED;
1906 }
1907
1908 RemoveEntryList(&ED->HcdEDLink);
1909
1910 OhciEndpoint->HeadED = NULL;
1911 }
1912
1913 VOID
1914 NTAPI
1915 OHCI_SetEndpointState(IN PVOID ohciExtension,
1916 IN PVOID ohciEndpoint,
1917 IN ULONG EndpointState)
1918 {
1919 POHCI_EXTENSION OhciExtension = ohciExtension;
1920 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
1921 POHCI_HCD_ED ED;
1922
1923 DPRINT_OHCI("OHCI_SetEndpointState: EndpointState - %x\n",
1924 EndpointState);
1925
1926 ED = OhciEndpoint->HcdED;
1927
1928 switch (EndpointState)
1929 {
1930 case USBPORT_ENDPOINT_PAUSED:
1931 ED->HwED.EndpointControl.sKip = 1;
1932 break;
1933
1934 case USBPORT_ENDPOINT_ACTIVE:
1935 ED->HwED.EndpointControl.sKip = 0;
1936 OHCI_EnableList(OhciExtension, OhciEndpoint);
1937 break;
1938
1939 case USBPORT_ENDPOINT_REMOVE:
1940 ED->HwED.EndpointControl.sKip = 1;
1941 ED->Flags |= OHCI_HCD_ED_FLAG_NOT_ACCESSED;
1942 OHCI_RemoveEndpointFromSchedule(OhciEndpoint);
1943 break;
1944
1945 default:
1946 ASSERT(FALSE);
1947 break;
1948 }
1949 }
1950
1951 VOID
1952 NTAPI
1953 OHCI_PollAsyncEndpoint(IN POHCI_EXTENSION OhciExtension,
1954 IN POHCI_ENDPOINT OhciEndpoint)
1955 {
1956 PUSBPORT_TRANSFER_PARAMETERS TransferParameters;
1957 POHCI_HCD_ED ED;
1958 ULONG_PTR NextTdPA;
1959 POHCI_HCD_TD NextTD;
1960 POHCI_HCD_TD TD;
1961 PLIST_ENTRY DoneList;
1962 POHCI_TRANSFER OhciTransfer;
1963 POHCI_HCD_TD ControlStatusTD;
1964 ULONG_PTR PhysicalAddress;
1965 ULONG TransferNumber;
1966 POHCI_TRANSFER transfer;
1967 UCHAR ConditionCode;
1968 BOOLEAN IsResetOnHalt = FALSE;
1969
1970 //DPRINT_OHCI("OHCI_PollAsyncEndpoint: Endpoint - %p\n", OhciEndpoint);
1971
1972 ED = OhciEndpoint->HcdED;
1973 NextTdPA = ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_MASK;
1974
1975 if (!NextTdPA)
1976 {
1977 OHCI_DumpHcdED(ED);
1978 DbgBreakPoint();
1979 }
1980
1981 NextTD = RegPacket.UsbPortGetMappedVirtualAddress((PVOID)NextTdPA,
1982 OhciExtension,
1983 OhciEndpoint);
1984 DPRINT_OHCI("NextTD - %p\n", NextTD);
1985
1986 if ((ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_HALT) == 0)
1987 goto ProcessListTDs;
1988
1989 OHCI_DumpHcdED(ED);
1990
1991 IsResetOnHalt = (ED->Flags & OHCI_HCD_ED_FLAG_RESET_ON_HALT) != 0;
1992 DPRINT1("PollAsyncEndpoint: IsResetOnHalt %x\n", IsResetOnHalt);
1993
1994 for (TD = OhciEndpoint->HcdHeadP; ; TD = (POHCI_HCD_TD)TD->NextHcdTD)
1995 {
1996 if (!TD)
1997 {
1998 OHCI_DumpHcdED(ED);
1999 DbgBreakPoint();
2000 }
2001
2002 if (TD == NextTD)
2003 {
2004 DPRINT("TD == NextTD - %p\n", TD);
2005 goto HandleDoneList;
2006 }
2007
2008 OhciTransfer = (POHCI_TRANSFER)TD->OhciTransfer;
2009 ConditionCode = TD->HwTD.gTD.Control.ConditionCode;
2010
2011 DPRINT("TD - %p, ConditionCode - %X\n", TD, ConditionCode);
2012 OHCI_DumpHcdTD(TD);
2013
2014 switch (ConditionCode)
2015 {
2016 case OHCI_TD_CONDITION_NO_ERROR:
2017 TD->Flags |= OHCI_HCD_TD_FLAG_DONE;
2018 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
2019 continue;
2020
2021 case OHCI_TD_CONDITION_NOT_ACCESSED:
2022 TD->Flags |= (OHCI_HCD_TD_FLAG_DONE | OHCI_HCD_TD_FLAG_NOT_ACCESSED);
2023 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
2024 continue;
2025
2026 case OHCI_TD_CONDITION_DATA_UNDERRUN:
2027 DPRINT1("DATA_UNDERRUN. Transfer->Flags - %X\n", OhciTransfer->Flags);
2028
2029 if (OhciTransfer->Flags & OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK)
2030 {
2031 IsResetOnHalt = TRUE;
2032 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NO_ERROR;
2033
2034 ControlStatusTD = OhciTransfer->ControlStatusTD;
2035
2036 if ((TD->Flags & OHCI_HCD_TD_FLAG_CONTROL_STATUS) == 0 &&
2037 ControlStatusTD)
2038 {
2039 PhysicalAddress = ControlStatusTD->PhysicalAddress;
2040 PhysicalAddress |= (ED->HwED.HeadPointer &
2041 OHCI_ED_HEAD_POINTER_FLAGS_MASK);
2042
2043 ED->HwED.HeadPointer = PhysicalAddress;
2044
2045 NextTD = OhciTransfer->ControlStatusTD;
2046 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD);
2047 }
2048 else
2049 {
2050 TransferParameters = OhciTransfer->TransferParameters;
2051
2052 if (TransferParameters->IsTransferSplited)
2053 {
2054 TransferNumber = TransferParameters->TransferCounter;
2055 transfer = OhciTransfer;
2056
2057 do
2058 {
2059 transfer = (POHCI_TRANSFER)transfer->NextTD->OhciTransfer;
2060 NextTD = transfer->NextTD;
2061 }
2062 while (transfer && TransferNumber ==
2063 transfer->TransferParameters->TransferCounter);
2064
2065 PhysicalAddress = NextTD->PhysicalAddress;
2066 PhysicalAddress |= (ED->HwED.HeadPointer &
2067 OHCI_ED_HEAD_POINTER_FLAGS_MASK);
2068
2069 ED->HwED.HeadPointer = PhysicalAddress;
2070 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD);
2071 }
2072 else
2073 {
2074 PhysicalAddress = OhciTransfer->NextTD->PhysicalAddress;
2075 PhysicalAddress |= (ED->HwED.HeadPointer &
2076 OHCI_ED_HEAD_POINTER_FLAGS_MASK);
2077
2078 ED->HwED.HeadPointer = PhysicalAddress;
2079
2080 NextTD = OhciTransfer->NextTD;
2081 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD);
2082 }
2083 }
2084
2085 TD->Flags |= OHCI_HCD_TD_FLAG_DONE;
2086 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
2087 continue;
2088 }
2089
2090 /* fall through */
2091
2092 default:
2093 TD->Flags |= OHCI_HCD_TD_FLAG_DONE;
2094 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
2095
2096 ED->HwED.HeadPointer = OhciTransfer->NextTD->PhysicalAddress |
2097 (ED->HwED.HeadPointer &
2098 OHCI_ED_HEAD_POINTER_FLAGS_MASK);
2099
2100 NextTD = OhciTransfer->NextTD;
2101 break;
2102 }
2103 }
2104
2105 ProcessListTDs:
2106
2107 TD = OhciEndpoint->HcdHeadP;
2108
2109 while (TD != NextTD)
2110 {
2111 OHCI_DumpHcdTD(TD);
2112 TD->Flags |= OHCI_HCD_TD_FLAG_DONE;
2113 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
2114 TD = (POHCI_HCD_TD)TD->NextHcdTD;
2115 }
2116
2117 HandleDoneList:
2118
2119 TD = NextTD;
2120 OhciEndpoint->HcdHeadP = NextTD;
2121
2122 DoneList = &OhciEndpoint->TDList;
2123
2124 while (!IsListEmpty(DoneList))
2125 {
2126 TD = CONTAINING_RECORD(DoneList->Flink,
2127 OHCI_HCD_TD,
2128 DoneLink);
2129
2130 RemoveHeadList(DoneList);
2131
2132 if (TD->Flags & OHCI_HCD_TD_FLAG_DONE &&
2133 TD->Flags & OHCI_HCD_TD_FLAG_PROCESSED)
2134 {
2135 OHCI_ProcessDoneTD(OhciExtension, TD, TRUE);
2136 }
2137 }
2138
2139 if (IsResetOnHalt)
2140 {
2141 ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_HALT;
2142 DPRINT("ED->HwED.HeadPointer - %p\n", ED->HwED.HeadPointer);
2143 }
2144 }
2145
2146 VOID
2147 NTAPI
2148 OHCI_PollIsoEndpoint(IN POHCI_EXTENSION OhciExtension,
2149 IN POHCI_ENDPOINT OhciEndpoint)
2150 {
2151 DPRINT1("OHCI_PollAsyncEndpoint: UNIMPLEMENTED. FIXME \n");
2152 ASSERT(FALSE);
2153 }
2154
2155 VOID
2156 NTAPI
2157 OHCI_PollEndpoint(IN PVOID ohciExtension,
2158 IN PVOID ohciEndpoint)
2159 {
2160 POHCI_EXTENSION OhciExtension = ohciExtension;
2161 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
2162 ULONG TransferType;
2163
2164 DPRINT_OHCI("OHCI_PollEndpoint: OhciExtension - %p, Endpoint - %p\n",
2165 OhciExtension,
2166 OhciEndpoint);
2167
2168 TransferType = OhciEndpoint->EndpointProperties.TransferType;
2169
2170 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
2171 {
2172 OHCI_PollIsoEndpoint(OhciExtension, OhciEndpoint);
2173 return;
2174 }
2175
2176 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
2177 TransferType == USBPORT_TRANSFER_TYPE_BULK ||
2178 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
2179 {
2180 OHCI_PollAsyncEndpoint(OhciExtension, OhciEndpoint);
2181 }
2182 }
2183
2184 VOID
2185 NTAPI
2186 OHCI_CheckController(IN PVOID ohciExtension)
2187 {
2188 POHCI_EXTENSION OhciExtension = ohciExtension;
2189 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
2190 PULONG HcControlReg;
2191 OHCI_REG_CONTROL HcControl;
2192 ULONG FmNumber;
2193 USHORT FmDiff;
2194 POHCI_HCCA HcHCCA;
2195
2196 //DPRINT_OHCI("OHCI_CheckController: ...\n");
2197
2198 OperationalRegs = OhciExtension->OperationalRegs;
2199
2200 if (!OHCI_HardwarePresent(OhciExtension, TRUE))
2201 return;
2202
2203 HcControlReg = (PULONG)&OperationalRegs->HcControl;
2204 HcControl.AsULONG = READ_REGISTER_ULONG(HcControlReg);
2205
2206 if (HcControl.HostControllerFunctionalState != OHCI_HC_STATE_OPERATIONAL)
2207 return;
2208
2209 FmNumber = READ_REGISTER_ULONG(&OperationalRegs->HcFmNumber);
2210 FmDiff = (USHORT)(FmNumber - OhciExtension->HcdFmNumber);
2211
2212 if (FmNumber == 0 || FmDiff < 5)
2213 return;
2214
2215 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
2216 OhciExtension->HcdFmNumber = FmNumber;
2217
2218 if (HcHCCA->Pad1 == 0)
2219 {
2220 HcHCCA->Pad1 = 0xBAD1;
2221 return;
2222 }
2223
2224 DPRINT1("OHCI_CheckController: HcHCCA->Pad1 - %x\n", HcHCCA->Pad1);
2225
2226 if (HcHCCA->Pad1 == 0xBAD1)
2227 {
2228 HcHCCA->Pad1 = 0xBAD2;
2229 }
2230 else if (HcHCCA->Pad1 == 0xBAD2)
2231 {
2232 HcHCCA->Pad1 = 0xBAD3;
2233
2234 RegPacket.UsbPortInvalidateController(OhciExtension,
2235 USBPORT_INVALIDATE_CONTROLLER_RESET);
2236 }
2237 }
2238
2239 ULONG
2240 NTAPI
2241 OHCI_Get32BitFrameNumber(IN PVOID ohciExtension)
2242 {
2243 POHCI_EXTENSION OhciExtension = ohciExtension;
2244 POHCI_HCCA HcHCCA;
2245 ULONG fm;
2246 ULONG hp;
2247
2248 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
2249
2250 /* 5.4 FrameInterval Counter: Get32BitFrameNumber() */
2251
2252 hp = OhciExtension->FrameHighPart;
2253 fm = HcHCCA->FrameNumber;
2254
2255 DPRINT_OHCI("OHCI_Get32BitFrameNumber: hp - %lX, fm - %lX\n", hp, fm);
2256
2257 return ((fm & 0x7FFF) | hp) + ((fm ^ hp) & 0x8000);
2258 }
2259
2260 VOID
2261 NTAPI
2262 OHCI_InterruptNextSOF(IN PVOID ohciExtension)
2263 {
2264 POHCI_EXTENSION OhciExtension = ohciExtension;
2265 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
2266 PULONG InterruptEnableReg;
2267 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
2268
2269 DPRINT_OHCI("OHCI_InterruptNextSOF: OhciExtension - %p\n",
2270 OhciExtension);
2271
2272 OperationalRegs = OhciExtension->OperationalRegs;
2273 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
2274
2275 /* Enable interrupt generation due to Start of Frame */
2276 IntEnable.AsULONG = 0;
2277 IntEnable.StartofFrame = 1;
2278
2279 WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG);
2280 }
2281
2282 VOID
2283 NTAPI
2284 OHCI_EnableInterrupts(IN PVOID ohciExtension)
2285 {
2286 POHCI_EXTENSION OhciExtension = ohciExtension;
2287 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
2288 PULONG InterruptEnableReg;
2289 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
2290
2291 DPRINT_OHCI("OHCI_EnableInterrupts: OhciExtension - %p\n",
2292 OhciExtension);
2293
2294 OperationalRegs = OhciExtension->OperationalRegs;
2295 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
2296
2297 /* Enable interrupt generation */
2298 IntEnable.AsULONG = 0;
2299 IntEnable.MasterInterruptEnable = 1;
2300
2301 WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG);
2302 }
2303
2304 VOID
2305 NTAPI
2306 OHCI_DisableInterrupts(IN PVOID ohciExtension)
2307 {
2308 POHCI_EXTENSION OhciExtension = ohciExtension;
2309 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
2310 PULONG InterruptDisableReg;
2311 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable;
2312
2313 DPRINT_OHCI("OHCI_DisableInterrupts\n");
2314
2315 OperationalRegs = OhciExtension->OperationalRegs;
2316 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
2317
2318 /* Disable interrupt generation */
2319 IntDisable.AsULONG = 0;
2320 IntDisable.MasterInterruptEnable = 1;
2321
2322 WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG);
2323 }
2324
2325 VOID
2326 NTAPI
2327 OHCI_PollController(IN PVOID ohciExtension)
2328 {
2329 DPRINT1("OHCI_PollController: UNIMPLEMENTED. FIXME\n");
2330 }
2331
2332 VOID
2333 NTAPI
2334 OHCI_SetEndpointDataToggle(IN PVOID ohciExtension,
2335 IN PVOID ohciEndpoint,
2336 IN ULONG DataToggle)
2337 {
2338 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
2339 POHCI_HCD_ED ED;
2340
2341 DPRINT_OHCI("OHCI_SetEndpointDataToggle: Endpoint - %p, DataToggle - %x\n",
2342 OhciEndpoint,
2343 DataToggle);
2344
2345 ED = OhciEndpoint->HcdED;
2346
2347 if (DataToggle)
2348 ED->HwED.HeadPointer |= OHCI_ED_HEAD_POINTER_CARRY;
2349 else
2350 ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_CARRY;
2351 }
2352
2353 ULONG
2354 NTAPI
2355 OHCI_GetEndpointStatus(IN PVOID ohciExtension,
2356 IN PVOID ohciEndpoint)
2357 {
2358 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
2359 POHCI_HCD_ED ED;
2360 ULONG EndpointStatus = USBPORT_ENDPOINT_RUN;
2361
2362 DPRINT_OHCI("OHCI_GetEndpointStatus: ... \n");
2363
2364 ED = OhciEndpoint->HcdED;
2365
2366 if ((ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_HALT) &&
2367 !(ED->Flags & OHCI_HCD_ED_FLAG_RESET_ON_HALT))
2368 {
2369 EndpointStatus = USBPORT_ENDPOINT_HALT;
2370 }
2371
2372 return EndpointStatus;
2373 }
2374
2375 VOID
2376 NTAPI
2377 OHCI_SetEndpointStatus(IN PVOID ohciExtension,
2378 IN PVOID ohciEndpoint,
2379 IN ULONG EndpointStatus)
2380 {
2381 POHCI_EXTENSION OhciExtension = ohciExtension;
2382 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
2383 POHCI_HCD_ED ED;
2384
2385 DPRINT_OHCI("OHCI_SetEndpointStatus: Endpoint - %p, EndpointStatus - %lX\n",
2386 OhciEndpoint,
2387 EndpointStatus);
2388
2389 if (EndpointStatus == USBPORT_ENDPOINT_RUN)
2390 {
2391 ED = OhciEndpoint->HcdED;
2392 ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_HALT;
2393
2394 OHCI_EnableList(OhciExtension, OhciEndpoint);
2395 }
2396 else if (EndpointStatus == USBPORT_ENDPOINT_HALT)
2397 {
2398 ASSERT(FALSE);
2399 }
2400 }
2401
2402 VOID
2403 NTAPI
2404 OHCI_ResetController(IN PVOID ohciExtension)
2405 {
2406 POHCI_EXTENSION OhciExtension = ohciExtension;
2407 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
2408 ULONG FrameNumber;
2409 PULONG ControlReg;
2410 PULONG CommandStatusReg;
2411 PULONG InterruptEnableReg;
2412 PULONG FmIntervalReg;
2413 PULONG RhStatusReg;
2414 PULONG PortStatusReg;
2415 OHCI_REG_CONTROL ControlBak;
2416 OHCI_REG_CONTROL Control;
2417 OHCI_REG_COMMAND_STATUS CommandStatus;
2418 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
2419 ULONG_PTR HCCA;
2420 ULONG_PTR ControlHeadED;
2421 ULONG_PTR BulkHeadED;
2422 OHCI_REG_FRAME_INTERVAL FrameInterval;
2423 ULONG_PTR PeriodicStart;
2424 ULONG_PTR LSThreshold;
2425 OHCI_REG_RH_STATUS RhStatus;
2426 OHCI_REG_RH_DESCRIPTORA RhDescriptorA;
2427 OHCI_REG_RH_PORT_STATUS PortStatus;
2428 ULONG NumPorts;
2429 ULONG ix;
2430
2431 DPRINT("OHCI_ResetController: ... \n");
2432
2433 OperationalRegs = OhciExtension->OperationalRegs;
2434
2435 ControlReg = (PULONG)&OperationalRegs->HcControl;
2436 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
2437 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
2438 FmIntervalReg = (PULONG)&OperationalRegs->HcFmInterval;
2439 RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
2440
2441 /* Backup FrameNumber from HcHCCA */
2442 FrameNumber = OhciExtension->HcResourcesVA->HcHCCA.FrameNumber;
2443
2444 /* Backup registers */
2445 ControlBak.AsULONG = READ_REGISTER_ULONG(ControlReg);
2446 HCCA = READ_REGISTER_ULONG(&OperationalRegs->HcHCCA);
2447 ControlHeadED = READ_REGISTER_ULONG(&OperationalRegs->HcControlHeadED);
2448 BulkHeadED = READ_REGISTER_ULONG(&OperationalRegs->HcBulkHeadED);
2449 FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg);
2450 PeriodicStart = READ_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart);
2451 LSThreshold = READ_REGISTER_ULONG(&OperationalRegs->HcLSThreshold);
2452
2453 /* Reset HostController */
2454 CommandStatus.AsULONG = 0;
2455 CommandStatus.HostControllerReset = 1;
2456 WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG);
2457
2458 KeStallExecutionProcessor(10);
2459
2460 /* Restore registers */
2461 WRITE_REGISTER_ULONG(&OperationalRegs->HcHCCA, HCCA);
2462 WRITE_REGISTER_ULONG(&OperationalRegs->HcControlHeadED, ControlHeadED);
2463 WRITE_REGISTER_ULONG(&OperationalRegs->HcBulkHeadED, BulkHeadED);
2464
2465 /* Set OPERATIONAL state for HC */
2466 Control.AsULONG = 0;
2467 Control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL;
2468 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
2469
2470 /* Set Toggle bit for FmInterval register */
2471 FrameInterval.FrameIntervalToggle = 1;
2472 WRITE_REGISTER_ULONG(FmIntervalReg, FrameInterval.AsULONG);
2473
2474 /* Restore registers */
2475 WRITE_REGISTER_ULONG(&OperationalRegs->HcFmNumber, FrameNumber);
2476 WRITE_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart, PeriodicStart);
2477 WRITE_REGISTER_ULONG(&OperationalRegs->HcLSThreshold, LSThreshold);
2478
2479 /* Setup RhStatus register */
2480 RhStatus.AsULONG = 0;
2481 RhStatus.SetRemoteWakeupEnable = 1;
2482 RhStatus.SetGlobalPower = 1;
2483 WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG);
2484
2485 /* Setup RH PortStatus registers */
2486 RhDescriptorA = OHCI_ReadRhDescriptorA(OhciExtension);
2487 NumPorts = RhDescriptorA.NumberDownstreamPorts;
2488
2489 PortStatus.AsULONG = 0;
2490 PortStatus.SetPortPower = 1;
2491
2492 for (ix = 0; ix < NumPorts; ix++)
2493 {
2494 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[ix];
2495 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
2496 }
2497
2498 /* Restore HcControl register */
2499 ControlBak.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL;
2500 WRITE_REGISTER_ULONG(ControlReg, ControlBak.AsULONG);
2501
2502 /* Setup HcInterruptEnable register */
2503 IntEnable.AsULONG = 0xFFFFFFFF;
2504 IntEnable.Reserved1 = 0;
2505 WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG);
2506 }
2507
2508 MPSTATUS
2509 NTAPI
2510 OHCI_StartSendOnePacket(IN PVOID ohciExtension,
2511 IN PVOID PacketParameters,
2512 IN PVOID Data,
2513 IN PULONG pDataLength,
2514 IN PVOID BufferVA,
2515 IN PVOID BufferPA,
2516 IN ULONG BufferLength,
2517 IN USBD_STATUS * pUSBDStatus)
2518 {
2519 DPRINT1("OHCI_StartSendOnePacket: UNIMPLEMENTED. FIXME\n");
2520 return MP_STATUS_SUCCESS;
2521 }
2522
2523 MPSTATUS
2524 NTAPI
2525 OHCI_EndSendOnePacket(IN PVOID ohciExtension,
2526 IN PVOID PacketParameters,
2527 IN PVOID Data,
2528 IN PULONG pDataLength,
2529 IN PVOID BufferVA,
2530 IN PVOID BufferPA,
2531 IN ULONG BufferLength,
2532 IN USBD_STATUS * pUSBDStatus)
2533 {
2534 DPRINT1("OHCI_EndSendOnePacket: UNIMPLEMENTED. FIXME\n");
2535 return MP_STATUS_SUCCESS;
2536 }
2537
2538 MPSTATUS
2539 NTAPI
2540 OHCI_PassThru(IN PVOID ohciExtension,
2541 IN PVOID passThruParameters,
2542 IN ULONG ParameterLength,
2543 IN PVOID pParameters)
2544 {
2545 DPRINT1("OHCI_PassThru: UNIMPLEMENTED. FIXME\n");
2546 return MP_STATUS_SUCCESS;
2547 }
2548
2549 VOID
2550 NTAPI
2551 OHCI_Unload(IN PDRIVER_OBJECT DriverObject)
2552 {
2553 #if DBG
2554 DPRINT1("OHCI_Unload: Not supported\n");
2555 #endif
2556 return;
2557 }
2558
2559 VOID
2560 NTAPI
2561 OHCI_FlushInterrupts(IN PVOID uhciExtension)
2562 {
2563 #if DBG
2564 DPRINT1("OHCI_FlushInterrupts: Not supported\n");
2565 #endif
2566 return;
2567 }
2568
2569 NTSTATUS
2570 NTAPI
2571 DriverEntry(IN PDRIVER_OBJECT DriverObject,
2572 IN PUNICODE_STRING RegistryPath)
2573 {
2574 NTSTATUS Status;
2575
2576 DPRINT_OHCI("DriverEntry: DriverObject - %p, RegistryPath - %wZ\n",
2577 DriverObject,
2578 RegistryPath);
2579
2580 RtlZeroMemory(&RegPacket, sizeof(USBPORT_REGISTRATION_PACKET));
2581
2582 RegPacket.MiniPortVersion = USB_MINIPORT_VERSION_OHCI;
2583
2584 RegPacket.MiniPortFlags = USB_MINIPORT_FLAGS_INTERRUPT |
2585 USB_MINIPORT_FLAGS_MEMORY_IO;
2586
2587 RegPacket.MiniPortBusBandwidth = TOTAL_USB11_BUS_BANDWIDTH;
2588
2589 RegPacket.MiniPortExtensionSize = sizeof(OHCI_EXTENSION);
2590 RegPacket.MiniPortEndpointSize = sizeof(OHCI_ENDPOINT);
2591 RegPacket.MiniPortTransferSize = sizeof(OHCI_TRANSFER);
2592 RegPacket.MiniPortResourcesSize = sizeof(OHCI_HC_RESOURCES);
2593
2594 RegPacket.OpenEndpoint = OHCI_OpenEndpoint;
2595 RegPacket.ReopenEndpoint = OHCI_ReopenEndpoint;
2596 RegPacket.QueryEndpointRequirements = OHCI_QueryEndpointRequirements;
2597 RegPacket.CloseEndpoint = OHCI_CloseEndpoint;
2598 RegPacket.StartController = OHCI_StartController;
2599 RegPacket.StopController = OHCI_StopController;
2600 RegPacket.SuspendController = OHCI_SuspendController;
2601 RegPacket.ResumeController = OHCI_ResumeController;
2602 RegPacket.InterruptService = OHCI_InterruptService;
2603 RegPacket.InterruptDpc = OHCI_InterruptDpc;
2604 RegPacket.SubmitTransfer = OHCI_SubmitTransfer;
2605 RegPacket.SubmitIsoTransfer = OHCI_SubmitIsoTransfer;
2606 RegPacket.AbortTransfer = OHCI_AbortTransfer;
2607 RegPacket.GetEndpointState = OHCI_GetEndpointState;
2608 RegPacket.SetEndpointState = OHCI_SetEndpointState;
2609 RegPacket.PollEndpoint = OHCI_PollEndpoint;
2610 RegPacket.CheckController = OHCI_CheckController;
2611 RegPacket.Get32BitFrameNumber = OHCI_Get32BitFrameNumber;
2612 RegPacket.InterruptNextSOF = OHCI_InterruptNextSOF;
2613 RegPacket.EnableInterrupts = OHCI_EnableInterrupts;
2614 RegPacket.DisableInterrupts = OHCI_DisableInterrupts;
2615 RegPacket.PollController = OHCI_PollController;
2616 RegPacket.SetEndpointDataToggle = OHCI_SetEndpointDataToggle;
2617 RegPacket.GetEndpointStatus = OHCI_GetEndpointStatus;
2618 RegPacket.SetEndpointStatus = OHCI_SetEndpointStatus;
2619 RegPacket.ResetController = OHCI_ResetController;
2620 RegPacket.RH_GetRootHubData = OHCI_RH_GetRootHubData;
2621 RegPacket.RH_GetStatus = OHCI_RH_GetStatus;
2622 RegPacket.RH_GetPortStatus = OHCI_RH_GetPortStatus;
2623 RegPacket.RH_GetHubStatus = OHCI_RH_GetHubStatus;
2624 RegPacket.RH_SetFeaturePortReset = OHCI_RH_SetFeaturePortReset;
2625 RegPacket.RH_SetFeaturePortPower = OHCI_RH_SetFeaturePortPower;
2626 RegPacket.RH_SetFeaturePortEnable = OHCI_RH_SetFeaturePortEnable;
2627 RegPacket.RH_SetFeaturePortSuspend = OHCI_RH_SetFeaturePortSuspend;
2628 RegPacket.RH_ClearFeaturePortEnable = OHCI_RH_ClearFeaturePortEnable;
2629 RegPacket.RH_ClearFeaturePortPower = OHCI_RH_ClearFeaturePortPower;
2630 RegPacket.RH_ClearFeaturePortSuspend = OHCI_RH_ClearFeaturePortSuspend;
2631 RegPacket.RH_ClearFeaturePortEnableChange = OHCI_RH_ClearFeaturePortEnableChange;
2632 RegPacket.RH_ClearFeaturePortConnectChange = OHCI_RH_ClearFeaturePortConnectChange;
2633 RegPacket.RH_ClearFeaturePortResetChange = OHCI_RH_ClearFeaturePortResetChange;
2634 RegPacket.RH_ClearFeaturePortSuspendChange = OHCI_RH_ClearFeaturePortSuspendChange;
2635 RegPacket.RH_ClearFeaturePortOvercurrentChange = OHCI_RH_ClearFeaturePortOvercurrentChange;
2636 RegPacket.RH_DisableIrq = OHCI_RH_DisableIrq;
2637 RegPacket.RH_EnableIrq = OHCI_RH_EnableIrq;
2638 RegPacket.StartSendOnePacket = OHCI_StartSendOnePacket;
2639 RegPacket.EndSendOnePacket = OHCI_EndSendOnePacket;
2640 RegPacket.PassThru = OHCI_PassThru;
2641 RegPacket.FlushInterrupts = OHCI_FlushInterrupts;
2642
2643 DriverObject->DriverUnload = OHCI_Unload;
2644
2645 Status = USBPORT_RegisterUSBPortDriver(DriverObject,
2646 USB10_MINIPORT_INTERFACE_VERSION,
2647 &RegPacket);
2648
2649 DPRINT_OHCI("DriverEntry: USBPORT_RegisterUSBPortDriver return Status - %x\n",
2650 Status);
2651
2652 return Status;
2653 }