OpenCore  1.0.4
OpenCore Bootloader
1.0.4
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
HdaController.c
Go to the documentation of this file.
1/*
2 * File: HdaController.c
3 *
4 * Copyright (c) 2018, 2020 John Davis
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include "HdaController.h"
27
28#include <Library/BaseOverflowLib.h>
33#include <Library/OcMiscLib.h>
34#include <Library/OcStringLib.h>
35#include <Library/PcdLib.h>
36
37BOOLEAN
39
40EFI_DEVICE_PATH_PROTOCOL *
42
43VOID
44EFIAPI
46 IN EFI_EVENT Event,
47 IN VOID *Context
48 )
49{
50 EFI_STATUS Status;
51 HDA_STREAM *HdaStream;
52 EFI_PCI_IO_PROTOCOL *PciIo;
53
54 UINT8 HdaStreamSts;
55 UINT32 HdaStreamDmaPos;
56 UINT32 HdaSourceLength;
57 UINT32 HdaCurrentBlock;
58 UINT32 HdaNextBlock;
59
60 UINT32 DmaChanged;
61 UINT32 Tmp;
62
63 HdaStream = (HDA_STREAM *)Context;
64 PciIo = HdaStream->HdaDev->PciIo;
65 HdaStreamSts = 0;
66
67 //
68 // Get current stream status bits.
69 //
70 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthFifoUint8, PCI_HDA_BAR, HDA_REG_SDNSTS (HdaStream->Index), 1, &HdaStreamSts);
71 if (EFI_ERROR (Status) || ((HdaStreamSts & (HDA_REG_SDNSTS_FIFOE | HDA_REG_SDNSTS_DESE)) != 0)) {
72 HdaControllerStreamAbort (HdaStream);
73 return;
74 }
75
76 if (HdaStream->UseLpib) {
77 //
78 // Get stream position through LPIB register.
79 //
80 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthFifoUint32, PCI_HDA_BAR, HDA_REG_SDNLPIB (HdaStream->Index), 1, &HdaStreamDmaPos);
81 if (EFI_ERROR (Status)) {
82 HdaControllerStreamAbort (HdaStream);
83 return;
84 }
85 } else {
86 //
87 // Get stream position through DMA positions buffer.
88 //
89 HdaStreamDmaPos = HdaStream->HdaDev->DmaPositions[HdaStream->Index].Position;
90
91 //
92 // If zero, give the stream a few cycles to catch up before falling back to LPIB.
93 // Fallback occurs after the set amount of cycles the DMA position is zero.
94 //
95 if ((HdaStreamDmaPos == 0) && !HdaStream->DmaCheckComplete) {
97 HdaStream->UseLpib = TRUE;
98 }
99
100 //
101 // Get stream position through LPIB register in the meantime.
102 //
103 DEBUG ((DEBUG_VERBOSE, "AudioDxe: Falling back to LPIB after %u more tries!\n", HDA_STREAM_DMA_CHECK_THRESH - HdaStream->DmaCheckCount));
104 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthFifoUint32, PCI_HDA_BAR, HDA_REG_SDNLPIB (HdaStream->Index), 1, &HdaStreamDmaPos);
105 if (EFI_ERROR (Status)) {
106 HdaControllerStreamAbort (HdaStream);
107 return;
108 }
109 }
110 }
111
112 //
113 // Increment cycle counter. Once complete, store status to avoid false fallbacks later on.
114 //
116 HdaStream->DmaCheckCount++;
117 } else {
118 HdaStream->DmaCheckComplete = TRUE;
119 }
120
121 if (HdaStreamDmaPos >= HdaStream->DmaPositionLast) {
122 DmaChanged = HdaStreamDmaPos - HdaStream->DmaPositionLast;
123 } else {
124 DmaChanged = (HDA_STREAM_BUF_SIZE - HdaStream->DmaPositionLast) + HdaStreamDmaPos;
125 }
126
127 HdaStream->DmaPositionLast = HdaStreamDmaPos;
128
129 if (HdaStream->BufferActive) {
130 if (BaseOverflowAddU32 (HdaStream->DmaPositionTotal, DmaChanged, &HdaStream->DmaPositionTotal)) {
131 HdaControllerStreamAbort (HdaStream);
132 return;
133 }
134
135 //
136 // Padding added to account for delay between DMA transfer to controller and actual playback.
137 //
138 if (HdaStream->DmaPositionTotal > HdaStream->BufferSourceLength + HDA_STREAM_BUFFER_PADDING) {
139 DEBUG ((DEBUG_VERBOSE, "AudioDxe: Completed playback of 0x%X buffer with 0x%X bytes read, current DMA: 0x%X\n", HdaStream->BufferSourceLength, HdaStream->DmaPositionTotal, HdaStreamDmaPos));
140 HdaControllerStreamIdle (HdaStream);
141
142 //
143 // TODO: Remove when continous stream run is implemented.
144 //
145 HdaControllerStreamAbort (HdaStream);
146
147 if (HdaStream->Callback != NULL) {
148 HdaStream->Callback (EfiHdaIoTypeOutput, HdaStream->CallbackContext1, HdaStream->CallbackContext2, HdaStream->CallbackContext3);
149 }
150 }
151
152 //
153 // Fill next block on IOC.
154 //
155 if (HdaStreamSts & HDA_REG_SDNSTS_BCIS && (HdaStream->BufferSourcePosition < HdaStream->BufferSourceLength)) {
156 HdaCurrentBlock = HdaStreamDmaPos / HDA_BDL_BLOCKSIZE;
157 HdaNextBlock = HdaCurrentBlock + 1;
158 HdaNextBlock %= HDA_BDL_ENTRY_COUNT;
159
160 HdaSourceLength = HDA_BDL_BLOCKSIZE;
161
162 if (BaseOverflowAddU32 (HdaStream->BufferSourcePosition, HdaSourceLength, &Tmp)) {
163 HdaControllerStreamAbort (HdaStream);
164 return;
165 }
166
167 if (Tmp > HdaStream->BufferSourceLength) {
168 HdaSourceLength = HdaStream->BufferSourceLength - HdaStream->BufferSourcePosition;
169 }
170
171 //
172 // Copy data to DMA buffer.
173 //
174 if (HdaSourceLength < HDA_BDL_BLOCKSIZE) {
175 ZeroMem (HdaStream->BufferData + HdaNextBlock * HDA_BDL_BLOCKSIZE, HDA_BDL_BLOCKSIZE);
176 }
177
178 CopyMem (HdaStream->BufferData + HdaNextBlock * HDA_BDL_BLOCKSIZE, HdaStream->BufferSource + HdaStream->BufferSourcePosition, HdaSourceLength);
179 if (BaseOverflowAddU32 (HdaStream->BufferSourcePosition, HdaSourceLength, &HdaStream->BufferSourcePosition)) {
180 HdaControllerStreamAbort (HdaStream);
181 return;
182 }
183
184 DEBUG ((
185 DEBUG_VERBOSE,
186 "AudioDxe: Block %u of %u filled! (current position 0x%X, buffer 0x%X)\n",
187 HdaStreamDmaPos / HDA_BDL_BLOCKSIZE,
189 HdaStreamDmaPos,
190 HdaStream->BufferSourcePosition
191 ));
192 }
193 }
194
195 //
196 // Reset IOC bit as needed.
197 //
198 if (HdaStreamSts & HDA_REG_SDNSTS_BCIS) {
199 HdaStreamSts = HDA_REG_SDNSTS_BCIS;
200 Status = PciIo->Mem.Write (PciIo, EfiPciIoWidthUint8, PCI_HDA_BAR, HDA_REG_SDNSTS (HdaStream->Index), 1, &HdaStreamSts);
201 if (EFI_ERROR (Status)) {
202 HdaControllerStreamAbort (HdaStream);
203 return;
204 }
205 }
206}
207
208EFI_STATUS
209EFIAPI
211 IN HDA_CONTROLLER_DEV *HdaControllerDev
212 )
213{
214 DEBUG ((DEBUG_VERBOSE, "HdaControllerInitPciHw(): start\n"));
215
216 EFI_STATUS Status;
217 EFI_PCI_IO_PROTOCOL *PciIo = HdaControllerDev->PciIo;
218 UINT64 PciSupports;
219 UINT8 HdaTcSel;
220 UINT16 HdaDevC;
221
222 PciSupports = 0;
223
224 //
225 // Save original PCI I/O attributes and get currently supported ones.
226 //
227 Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0, &HdaControllerDev->OriginalPciAttributes);
228 if (EFI_ERROR (Status)) {
229 return Status;
230 }
231
232 HdaControllerDev->OriginalPciAttributesSaved = TRUE;
233 Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupported, 0, &PciSupports);
234 if (EFI_ERROR (Status)) {
235 return Status;
236 }
237
238 //
239 // Enable the PCI device.
240 //
241 PciSupports &= EFI_PCI_DEVICE_ENABLE;
242 Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable, PciSupports, NULL);
243 if (EFI_ERROR (Status)) {
244 return Status;
245 }
246
247 //
248 // Get vendor and device IDs of PCI device.
249 //
250 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, PCI_VENDOR_ID_OFFSET, 1, &HdaControllerDev->VendorId);
251 if (EFI_ERROR (Status)) {
252 return Status;
253 }
254
255 DEBUG ((
256 DEBUG_VERBOSE,
257 "HdaControllerInitPciHw(): controller %4X:%4X\n",
258 GET_PCI_VENDOR_ID (HdaControllerDev->VendorId),
259 GET_PCI_DEVICE_ID (HdaControllerDev->VendorId)
260 ));
261
262 if (GET_PCI_VENDOR_ID (HdaControllerDev->VendorId) == VEN_INTEL_ID) {
263 //
264 // Set TC0 in TCSEL register for Intel controllers.
265 //
266 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_HDA_TCSEL_OFFSET, 1, &HdaTcSel);
267 if (EFI_ERROR (Status)) {
268 return Status;
269 }
270
271 HdaTcSel &= PCI_HDA_TCSEL_TC0_MASK;
272 Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, PCI_HDA_TCSEL_OFFSET, 1, &HdaTcSel);
273 if (EFI_ERROR (Status)) {
274 return Status;
275 }
276 } else if (GET_PCI_VENDOR_ID (HdaControllerDev->VendorId) == VEN_VMWARE_ID) {
277 HdaControllerDev->Quirks |= HDA_CONTROLLER_QUIRK_CORB_NO_POLL_RESET;
278 }
279
280 //
281 // Get device control PCI register.
282 //
283 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_HDA_DEVC_OFFSET, 1, &HdaDevC);
284 if (EFI_ERROR (Status)) {
285 return Status;
286 }
287
288 //
289 // If No Snoop is currently enabled, disable it.
290 //
291 if (HdaDevC & PCI_HDA_DEVC_NOSNOOPEN) {
292 DEBUG ((DEBUG_INFO, "HDA: Controller disable no snoop\n"));
293 HdaControllerDev->OriginalPciDeviceControl = HdaDevC;
294 HdaControllerDev->OriginalPciDeviceControlSaved = TRUE;
295
296 HdaDevC &= ~PCI_HDA_DEVC_NOSNOOPEN;
297 Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, PCI_HDA_DEVC_OFFSET, 1, &HdaDevC);
298 if (EFI_ERROR (Status)) {
299 return Status;
300 }
301 }
302
303 //
304 // Get major/minor version.
305 //
306 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthUint8, PCI_HDA_BAR, HDA_REG_VMAJ, 1, &HdaControllerDev->MajorVersion);
307 if (EFI_ERROR (Status)) {
308 return Status;
309 }
310
311 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthUint8, PCI_HDA_BAR, HDA_REG_VMIN, 1, &HdaControllerDev->MinorVersion);
312 if (EFI_ERROR (Status)) {
313 return Status;
314 }
315
316 DEBUG ((
317 DEBUG_INFO,
318 "HDA: Controller version %u.%u\n",
319 HdaControllerDev->MajorVersion,
320 HdaControllerDev->MinorVersion
321 ));
322 if (HdaControllerDev->MajorVersion < HDA_VERSION_MIN_MAJOR) {
323 Status = EFI_UNSUPPORTED;
324 return Status;
325 }
326
327 //
328 // Get capabilities.
329 //
330 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_GCAP, 1, &HdaControllerDev->Capabilities);
331 if (EFI_ERROR (Status)) {
332 return Status;
333 }
334
335 DEBUG ((DEBUG_INFO, "HDA: Capabilities:\n"));
336 DEBUG ((
337 DEBUG_INFO,
338 "HDA: | 64-bit: %s Serial Data Out Signals: %u\n",
339 HdaControllerDev->Capabilities & HDA_REG_GCAP_64OK ? L"Yes" : L"No",
340 HDA_REG_GCAP_NSDO (HdaControllerDev->Capabilities)
341 ));
342 DEBUG ((
343 DEBUG_INFO,
344 "HDA: | Bidir streams: %u Input streams: %u Output streams: %u\n",
345 HDA_REG_GCAP_BSS (HdaControllerDev->Capabilities),
346 HDA_REG_GCAP_ISS (HdaControllerDev->Capabilities),
347 HDA_REG_GCAP_OSS (HdaControllerDev->Capabilities)
348 ));
349
350 return EFI_SUCCESS;
351}
352
353VOID
354EFIAPI
356 IN HDA_CONTROLLER_DEV *HdaControllerDev
357 )
358{
359 DEBUG ((DEBUG_VERBOSE, "HdaControllerGetName(): start\n"));
360
361 //
362 // Try to match controller name.
363 //
364 HdaControllerDev->Name = AsciiStrCopyToUnicode (OcHdaControllerGetName (HdaControllerDev->VendorId), 0);
365 DEBUG ((DEBUG_INFO, "HDA: Controller is %s\n", HdaControllerDev->Name));
366}
367
368STATIC
369EFI_STATUS
371 IN HDA_CONTROLLER_DEV *HdaControllerDev
372 )
373{
374 EFI_PCI_IO_PROTOCOL *PciIo;
375
376 if (!HdaControllerDev->OriginalPciDeviceControlSaved) {
377 return EFI_SUCCESS;
378 }
379
380 PciIo = HdaControllerDev->PciIo;
381
382 DEBUG ((DEBUG_VERBOSE, "HdaControllerCleanup(): restore PCI device control\n"));
383 return PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, PCI_HDA_DEVC_OFFSET, 1, &HdaControllerDev->OriginalPciDeviceControl);
384}
385
386STATIC
387VOID
388EFIAPI
390 IN EFI_EVENT Event,
391 IN VOID *Context
392 )
393{
394 HDA_CONTROLLER_DEV *HdaControllerDev;
395
396 HdaControllerDev = Context;
397
398 //
399 // Restore No Snoop Enable bit at Exit Boot Services to avoid breaking in-OS sound in Windows with some firmware.
400 // Windows sound is fine even without this on many systems where AudioDxe disables No Snoop, and doing this
401 // (even though it should only be restoring the previous value) breaks macOS sound on some systems.
402 // REF: https://github.com/acidanthera/bugtracker/issues/1909
403 // REF: https://github.com/acidanthera/bugtracker/issues/1945
404 // REF: Intel I/O Controller Hub 9 (ICH9) Family Datasheet (DEVC - Device Conrol Register/NSNPEN)
405 //
406 HdaControllerRestoreNoSnoopEn (HdaControllerDev);
407}
408
409EFI_STATUS
410EFIAPI
412 IN HDA_CONTROLLER_DEV *HdaControllerDev,
413 IN BOOLEAN Restart
414 )
415{
416 DEBUG ((DEBUG_VERBOSE, "HdaControllerReset(): start\n"));
417
418 EFI_STATUS Status;
419 EFI_PCI_IO_PROTOCOL *PciIo = HdaControllerDev->PciIo;
420 UINT32 HdaGCtl;
421 UINT64 Tmp;
422
423 //
424 // Check if the controller is already in reset. If not, clear CRST bit.
425 // Warning: Like some other (but not all) Intel HDA control and reset
426 // bits, the bit sense is the opposite to what the name implies (here,
427 // zero is reset state; one is run state).
428 //
429 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, 1, &HdaGCtl);
430 if (EFI_ERROR (Status)) {
431 return Status;
432 }
433
434 if (HdaGCtl & HDA_REG_GCTL_CRST) {
435 HdaGCtl &= ~HDA_REG_GCTL_CRST;
436 Status = PciIo->Mem.Write (PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, 1, &HdaGCtl);
437 if (EFI_ERROR (Status)) {
438 return Status;
439 }
440
441 //
442 // Wait for bit to clear. Once bit is clear, the controller is ready to restart.
443 //
444 Status = PciIo->PollMem (
445 PciIo,
446 EfiPciIoWidthUint32,
450 0,
451 MS_TO_NANOSECONDS (100),
452 &Tmp
453 );
454 if (EFI_ERROR (Status)) {
455 return Status;
456 }
457 }
458
459 if (!Restart) {
460 return EFI_SUCCESS;
461 }
462
463 //
464 // Currently restore NSNPEN is the only functionality needed at ExitBootServices.
465 //
466 if (gRestoreNoSnoop && (HdaControllerDev->ExitBootServicesEvent == NULL)) {
467 Status = gBS->CreateEvent (
468 EVT_SIGNAL_EXIT_BOOT_SERVICES,
469 TPL_CALLBACK,
471 HdaControllerDev,
472 &HdaControllerDev->ExitBootServicesEvent
473 );
474 if (EFI_ERROR (Status)) {
475 return Status;
476 }
477 }
478
479 //
480 // Set CRST bit to begin the process of coming out of reset.
481 //
482 HdaGCtl |= HDA_REG_GCTL_CRST;
483 Status = PciIo->Mem.Write (PciIo, EfiPciIoWidthUint32, PCI_HDA_BAR, HDA_REG_GCTL, 1, &HdaGCtl);
484 if (EFI_ERROR (Status)) {
485 return Status;
486 }
487
488 //
489 // Wait for bit to be set. Once bit is set, the controller is ready.
490 //
491 Status = PciIo->PollMem (
492 PciIo,
493 EfiPciIoWidthUint32,
498 MS_TO_NANOSECONDS (100),
499 &Tmp
500 );
501 if (EFI_ERROR (Status)) {
502 return Status;
503 }
504
505 //
506 // Wait 100ms to ensure all codecs have also reset.
507 //
508 gBS->Stall (MS_TO_MICROSECONDS (100));
509 DEBUG ((DEBUG_VERBOSE, "HdaControllerReset(): done\n"));
510 return EFI_SUCCESS;
511}
512
513EFI_STATUS
514EFIAPI
516 IN HDA_CONTROLLER_DEV *HdaControllerDev,
517 IN BOOLEAN PreScan
518 )
519{
520 DEBUG ((DEBUG_VERBOSE, "HdaControllerScanCodecs(%u): start\n", PreScan));
521
522 EFI_STATUS Status;
523 EFI_PCI_IO_PROTOCOL *PciIo;
524 UINT16 HdaStatests;
525 EFI_HDA_IO_VERB_LIST HdaCodecVerbList;
526 UINT32 VendorVerb;
527 UINT32 VendorResponse;
528
529 UINTN CurrentOutputStreamIndex = 0;
530
531 HDA_IO_PRIVATE_DATA *HdaIoPrivateData;
532 VOID *TmpProtocol;
533 UINT32 Index;
534
535 if (HdaControllerDev == NULL) {
536 return EFI_INVALID_PARAMETER;
537 }
538
539 PciIo = HdaControllerDev->PciIo;
540
541 //
542 // Get STATESTS register.
543 //
544 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_STATESTS, 1, &HdaStatests);
545 if (EFI_ERROR (Status)) {
546 return Status;
547 }
548
549 //
550 // Create verb list with single item.
551 //
553 ZeroMem (&HdaCodecVerbList, sizeof (EFI_HDA_IO_VERB_LIST));
554 HdaCodecVerbList.Count = 1;
555 HdaCodecVerbList.Verbs = &VendorVerb;
556 HdaCodecVerbList.Responses = &VendorResponse;
557
558 //
559 // Iterate through register looking for active codecs.
560 //
561 for (Index = 0; Index < HDA_MAX_CODECS; Index++) {
562 //
563 // Do we have a codec at this address?
564 //
565 if (HdaStatests & (1 << Index)) {
566 //
567 // Try to get the vendor ID. If this fails, ignore the codec.
568 //
569 VendorResponse = 0;
570 Status = HdaControllerSendCommands (HdaControllerDev, (UINT8)Index, HDA_NID_ROOT, &HdaCodecVerbList);
571 if ((EFI_ERROR (Status)) || (VendorResponse == 0)) {
572 if (PreScan) {
573 DEBUG ((DEBUG_INFO, "HDA: Ignoring codec @ 0x%X - %r\n", Index, Status));
574 }
575
576 continue;
577 }
578
579 if (PreScan) {
580 if (GET_CODEC_VENDOR_ID (VendorResponse) == VEN_QEMU_ID) {
581 HdaControllerDev->Quirks |= HDA_CONTROLLER_QUIRK_QEMU_2;
582 }
583 } else {
584 HdaIoPrivateData = AllocateZeroPool (sizeof (HDA_IO_PRIVATE_DATA));
585 if (HdaIoPrivateData == NULL) {
586 Status = EFI_OUT_OF_RESOURCES;
587 return Status;
588 }
589
591 HdaIoPrivateData->HdaCodecAddress = (UINT8)Index;
592 HdaIoPrivateData->HdaControllerDev = HdaControllerDev;
597 HdaIoPrivateData->HdaIo.GetStream = HdaControllerHdaIoGetStream;
600
601 //
602 // Assign streams.
603 //
604 if (CurrentOutputStreamIndex < HdaControllerDev->StreamsCount) {
605 DEBUG ((DEBUG_VERBOSE, "Assigning output stream %u to codec\n", CurrentOutputStreamIndex));
606 HdaIoPrivateData->HdaOutputStream = HdaControllerDev->Streams + CurrentOutputStreamIndex;
607 CurrentOutputStreamIndex++;
608 }
609
610 HdaControllerDev->HdaIoChildren[Index].PrivateData = HdaIoPrivateData;
611 }
612 }
613 }
614
615 if (!PreScan) {
616 //
617 // Clear STATESTS register.
618 //
619 HdaStatests = HDA_REG_STATESTS_CLEAR;
620 Status = PciIo->Mem.Write (PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_STATESTS, 1, &HdaStatests);
621 if (EFI_ERROR (Status)) {
622 return Status;
623 }
624
625 //
626 // Install protocols on each codec.
627 //
628 for (Index = 0; Index < HDA_MAX_CODECS; Index++) {
629 if (HdaControllerDev->HdaIoChildren[Index].PrivateData != NULL) {
630 // Create Device Path for codec.
631 EFI_HDA_IO_DEVICE_PATH HdaIoDevicePathNode; // EFI_HDA_IO_DEVICE_PATH_TEMPLATE;
632 HdaIoDevicePathNode.Header.Type = MESSAGING_DEVICE_PATH;
633 HdaIoDevicePathNode.Header.SubType = MSG_VENDOR_DP;
634 HdaIoDevicePathNode.Header.Length[0] = (UINT8)(sizeof (EFI_HDA_IO_DEVICE_PATH));
635 HdaIoDevicePathNode.Header.Length[1] = (UINT8)((sizeof (EFI_HDA_IO_DEVICE_PATH)) >> 8);
636 HdaIoDevicePathNode.Guid = gEfiHdaIoDevicePathGuid;
637 HdaIoDevicePathNode.Address = Index;
638 HdaControllerDev->HdaIoChildren[Index].DevicePath = AppendDevicePathNode (HdaControllerDev->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&HdaIoDevicePathNode);
639 if (HdaControllerDev->HdaIoChildren[Index].DevicePath == NULL) {
640 Status = EFI_INVALID_PARAMETER;
641 return Status;
642 }
643
644 //
645 // Install protocols for the codec. The codec driver will later bind to this.
646 //
647 HdaControllerDev->HdaIoChildren[Index].Handle = NULL;
648 Status = gBS->InstallMultipleProtocolInterfaces (
649 &HdaControllerDev->HdaIoChildren[Index].Handle,
651 HdaControllerDev->HdaIoChildren[Index].DevicePath,
653 &HdaControllerDev->HdaIoChildren[Index].PrivateData->HdaIo,
654 NULL
655 );
656 if (EFI_ERROR (Status)) {
657 return Status;
658 }
659
660 //
661 // Connect child to parent.
662 //
663 Status = gBS->OpenProtocol (
664 HdaControllerDev->ControllerHandle,
665 &gEfiPciIoProtocolGuid,
666 &TmpProtocol,
667 HdaControllerDev->DriverBinding->DriverBindingHandle,
668 HdaControllerDev->HdaIoChildren[Index].Handle,
669 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
670 );
671 if (EFI_ERROR (Status)) {
672 return Status;
673 }
674 }
675 }
676 }
677
678 return EFI_SUCCESS;
679}
680
681EFI_STATUS
682EFIAPI
684 IN HDA_CONTROLLER_DEV *HdaDev,
685 IN UINT8 CodecAddress,
686 IN UINT8 Node,
687 IN EFI_HDA_IO_VERB_LIST *Verbs
688 )
689{
690 // DEBUG((DEBUG_INFO, "HdaControllerSendCommands(): start\n"));
691
692 // Create variables.
693 EFI_STATUS Status;
694 EFI_PCI_IO_PROTOCOL *PciIo = HdaDev->PciIo;
695 UINT32 *HdaCorb;
696 UINT64 *HdaRirb;
697
698 // Ensure parameters are valid.
699 if ((CodecAddress >= HDA_MAX_CODECS) || (Verbs == NULL) || (Verbs->Count < 1)) {
700 return EFI_INVALID_PARAMETER;
701 }
702
703 // Get pointers to CORB and RIRB.
704 HdaCorb = HdaDev->Corb.Buffer;
705 HdaRirb = HdaDev->Rirb.Buffer;
706
707 UINT32 RemainingVerbs;
708 UINT32 RemainingResponses;
709 UINT16 HdaCorbReadPointer;
710 UINT16 HdaRirbWritePointer;
711 BOOLEAN ResponseReceived;
712 UINT8 ResponseTimeout;
713 UINT64 RirbResponse;
714 UINT32 VerbCommand;
715 UINT8 RirbSts;
716 BOOLEAN Retry = FALSE;
717
718 // Lock.
719 AcquireSpinLock (&HdaDev->SpinLock);
720
721START:
722 RemainingVerbs = Verbs->Count;
723 RemainingResponses = Verbs->Count;
724 do {
725 // Keep sending verbs until they are all sent.
726 if (RemainingVerbs) {
727 // Get current CORB read pointer.
728 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_CORBRP, 1, &HdaCorbReadPointer);
729 if (EFI_ERROR (Status)) {
730 goto DONE;
731 }
732
733 // DEBUG((DEBUG_INFO, "old RP: 0x%X\n", HdaCorbReadPointer));
734
735 // Add verbs to CORB until all of them are added or the CORB becomes full.
736 while (RemainingVerbs && ((HdaDev->Corb.Pointer + 1 % HdaDev->Corb.EntryCount) != HdaCorbReadPointer)) {
737 // Move write pointer and write verb to CORB.
738 HdaDev->Corb.Pointer++;
739 HdaDev->Corb.Pointer %= HdaDev->Corb.EntryCount;
740 VerbCommand = HDA_CORB_VERB (CodecAddress, Node, Verbs->Verbs[Verbs->Count - RemainingVerbs]);
741 HdaCorb[HdaDev->Corb.Pointer] = VerbCommand;
742
743 // Move to next verb.
744 RemainingVerbs--;
745 }
746
747 // Set CORB write pointer.
748 Status = PciIo->Mem.Write (PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_CORBWP, 1, &HdaDev->Corb.Pointer);
749 if (EFI_ERROR (Status)) {
750 goto DONE;
751 }
752 }
753
754 // Get responses from RIRB.
755 ResponseReceived = FALSE;
756 ResponseTimeout = 10;
757 while (!ResponseReceived) {
758 // Get current RIRB write pointer.
759 Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthUint16, PCI_HDA_BAR, HDA_REG_RIRBWP, 1, &HdaRirbWritePointer);
760 if (EFI_ERROR (Status)) {
761 goto DONE;
762 }
763
764 // If the read and write pointers differ, there are responses waiting.
765 while (HdaDev->Rirb.Pointer != HdaRirbWritePointer) {
766 if (HdaDev->Quirks & HDA_CONTROLLER_QUIRK_QEMU_1) {
767 // Clear response interrupt flags if set, in order to allow next response through in interrupt mode.
768 RirbSts = 0;
769 Status = PciIo->Mem.Write (PciIo, EfiPciIoWidthUint8, PCI_HDA_BAR, HDA_REG_RIRBSTS, 1, &RirbSts);
770 if (EFI_ERROR (Status)) {
771 goto DONE;
772 }
773 }
774
775 // Increment RIRB read pointer.
776 HdaDev->Rirb.Pointer++;
777 HdaDev->Rirb.Pointer %= HdaDev->Rirb.EntryCount;
778
779 // Get response and ensure it belongs to the current codec.
780 RirbResponse = HdaRirb[HdaDev->Rirb.Pointer];
781 if ((HDA_RIRB_CAD (RirbResponse) != CodecAddress) || HDA_RIRB_UNSOL (RirbResponse)) {
782 DEBUG ((DEBUG_INFO, "Unknown response!\n"));
783 continue;
784 }
785
786 // Add response to list.
787 Verbs->Responses[Verbs->Count - RemainingResponses] = HDA_RIRB_RESP (RirbResponse);
788 RemainingResponses--;
789 ResponseReceived = TRUE;
790 }
791
792 // If no response still, wait a bit.
793 if (!ResponseReceived) {
794 // If timeout reached, fail.
795 if (!ResponseTimeout) {
796 DEBUG ((DEBUG_INFO, "Command: 0x%X\n", VerbCommand));
797 Status = EFI_TIMEOUT;
798 goto TIMEOUT;
799 }
800
801 ResponseTimeout--;
802 gBS->Stall (MS_TO_MICROSECONDS (5));
803 if (ResponseTimeout < 5) {
804 DEBUG ((DEBUG_INFO, "%u timeouts reached while waiting for response!\n", ResponseTimeout));
805 }
806 }
807 }
808 } while (RemainingVerbs || RemainingResponses);
809
810 Status = EFI_SUCCESS;
811 goto DONE;
812
813TIMEOUT:
814 DEBUG ((DEBUG_INFO, "Timeout!\n"));
815 if (!Retry) {
816 DEBUG ((DEBUG_INFO, "Stall detected, restarting CORB and RIRB!\n"));
817 Status = HdaControllerSetRingBufferState (&HdaDev->Corb, FALSE, HDA_RING_BUFFER_TYPE_CORB);
818 if (EFI_ERROR (Status)) {
819 goto DONE;
820 }
821
822 Status = HdaControllerSetRingBufferState (&HdaDev->Rirb, FALSE, HDA_RING_BUFFER_TYPE_RIRB);
823 if (EFI_ERROR (Status)) {
824 goto DONE;
825 }
826
827 Status = HdaControllerSetRingBufferState (&HdaDev->Corb, TRUE, HDA_RING_BUFFER_TYPE_CORB);
828 if (EFI_ERROR (Status)) {
829 goto DONE;
830 }
831
832 Status = HdaControllerSetRingBufferState (&HdaDev->Rirb, TRUE, HDA_RING_BUFFER_TYPE_RIRB);
833 if (EFI_ERROR (Status)) {
834 goto DONE;
835 }
836
837 // Try again.
838 Retry = TRUE;
839 goto START;
840 }
841
842DONE:
843 ReleaseSpinLock (&HdaDev->SpinLock);
844 return Status;
845}
846
847EFI_STATUS
848EFIAPI
850 IN HDA_CONTROLLER_DEV *HdaControllerDev
851 )
852{
853 EFI_STATUS Status;
854 HDA_CONTROLLER_INFO_PRIVATE_DATA *HdaControllerInfoData;
855
856 HdaControllerInfoData = AllocateZeroPool (sizeof (HDA_CONTROLLER_INFO_PRIVATE_DATA));
857 if (HdaControllerInfoData == NULL) {
858 return EFI_OUT_OF_RESOURCES;
859 }
860
861 HdaControllerInfoData->Signature = HDA_CONTROLLER_PRIVATE_DATA_SIGNATURE;
862 HdaControllerInfoData->HdaControllerDev = HdaControllerDev;
863 HdaControllerInfoData->HdaControllerInfo.GetName = HdaControllerInfoGetName;
865
866 //
867 // Install protocols.
868 //
869 HdaControllerDev->HdaControllerInfoData = HdaControllerInfoData;
870 Status = gBS->InstallMultipleProtocolInterfaces (
871 &HdaControllerDev->ControllerHandle,
873 &HdaControllerInfoData->HdaControllerInfo,
874 &gEfiCallerIdGuid,
875 HdaControllerDev,
876 NULL
877 );
878
879 if (!EFI_ERROR (Status)) {
880 DEBUG ((DEBUG_INFO, "HDA: Controller protocols installed\n"));
881 }
882
883 return Status;
884}
885
886VOID
887EFIAPI
889 IN HDA_CONTROLLER_DEV *HdaControllerDev
890 )
891{
892 EFI_STATUS Status;
893 EFI_PCI_IO_PROTOCOL *PciIo;
894
895 DEBUG ((DEBUG_VERBOSE, "HdaControllerCleanup(): start\n"));
896
897 // If controller device is already free, we are done.
898 if (HdaControllerDev == NULL) {
899 return;
900 }
901
902 PciIo = HdaControllerDev->PciIo;
903
904 // Clear ExitBootServices event.
905 if (HdaControllerDev->ExitBootServicesEvent != NULL) {
906 gBS->CloseEvent (HdaControllerDev->ExitBootServicesEvent);
907 HdaControllerDev->ExitBootServicesEvent = NULL;
908 }
909
910 // Clean HDA Controller info protocol.
911 if (HdaControllerDev->HdaControllerInfoData != NULL) {
912 // Uninstall protocol.
913 DEBUG ((DEBUG_VERBOSE, "HdaControllerCleanup(): clean HDA Controller Info\n"));
914 Status = gBS->UninstallProtocolInterface (
915 HdaControllerDev->ControllerHandle,
917 &HdaControllerDev->HdaControllerInfoData->HdaControllerInfo
918 );
919 ASSERT_EFI_ERROR (Status);
920
921 // Free data.
922 FreePool (HdaControllerDev->HdaControllerInfoData);
923 }
924
925 // Clean HDA I/O children.
926 for (UINT8 i = 0; i < HDA_MAX_CODECS; i++) {
927 // Clean Device Path protocol.
928 if (HdaControllerDev->HdaIoChildren[i].DevicePath != NULL) {
929 // Uninstall protocol.
930 DEBUG ((DEBUG_VERBOSE, "HdaControllerCleanup(): clean Device Path index %u\n", i));
931 Status = gBS->UninstallProtocolInterface (
932 HdaControllerDev->HdaIoChildren[i].Handle,
934 HdaControllerDev->HdaIoChildren[i].DevicePath
935 );
936 ASSERT_EFI_ERROR (Status);
937
938 // Free Device Path.
939 FreePool (HdaControllerDev->HdaIoChildren[i].DevicePath);
940 }
941
942 // Clean HDA I/O protocol.
943 if (HdaControllerDev->HdaIoChildren[i].PrivateData != NULL) {
944 // Uninstall protocol.
945 DEBUG ((DEBUG_VERBOSE, "HdaControllerCleanup(): clean HDA I/O index %u\n", i));
946 Status = gBS->UninstallProtocolInterface (
947 HdaControllerDev->HdaIoChildren[i].Handle,
949 &HdaControllerDev->HdaIoChildren[i].PrivateData->HdaIo
950 );
951 ASSERT_EFI_ERROR (Status);
952
953 // Free private data.
954 FreePool (HdaControllerDev->HdaIoChildren[i].PrivateData);
955 }
956 }
957
958 //
959 // Cleanup streams, CORB, and RIRB.
960 //
961 HdaControllerCleanupStreams (HdaControllerDev);
964
965 // Place controller into a reset state to stop it.
966 HdaControllerReset (HdaControllerDev, FALSE);
967
968 //
969 // Restore PCI device control and attributes if needed.
970 //
971 HdaControllerRestoreNoSnoopEn (HdaControllerDev);
972
973 if (HdaControllerDev->OriginalPciAttributesSaved) {
974 DEBUG ((DEBUG_VERBOSE, "HdaControllerCleanup(): restore PCI attributes\n"));
975 PciIo->Attributes (
976 PciIo,
977 EfiPciIoAttributeOperationSet,
978 HdaControllerDev->OriginalPciAttributes,
979 NULL
980 );
981 }
982
983 // Free controller device.
984 DEBUG ((DEBUG_VERBOSE, "HdaControllerCleanup(): free controller device\n"));
985 gBS->UninstallProtocolInterface (
986 HdaControllerDev->ControllerHandle,
987 &gEfiCallerIdGuid,
988 HdaControllerDev
989 );
990 FreePool (HdaControllerDev);
991}
992
993EFI_STATUS
994EFIAPI
996 IN EFI_DRIVER_BINDING_PROTOCOL *This,
997 IN EFI_HANDLE ControllerHandle,
998 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
999 )
1000{
1001 EFI_STATUS Status;
1002 EFI_PCI_IO_PROTOCOL *PciIo;
1003 PCI_CLASSCODE HdaClassReg;
1004 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1005
1006 //
1007 // Open PCI I/O protocol. If this fails, it's not a PCI device.
1008 //
1009 Status = gBS->OpenProtocol (
1010 ControllerHandle,
1011 &gEfiPciIoProtocolGuid,
1012 (VOID **)&PciIo,
1013 This->DriverBindingHandle,
1014 ControllerHandle,
1015 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1016 );
1017
1018 if (EFI_ERROR (Status)) {
1019 return Status;
1020 }
1021
1022 //
1023 // For use when the device is misreporting its class or subclass, so ignore these.
1024 //
1025 if (gForcedControllerDevicePath != NULL) {
1026 Status = EFI_UNSUPPORTED;
1027
1028 DevicePath = DevicePathFromHandle (ControllerHandle);
1029
1030 if ( (DevicePath != NULL)
1032 {
1033 Status = EFI_SUCCESS;
1034 }
1035
1036 return Status;
1037 }
1038
1039 //
1040 // Read class code from PCI.
1041 //
1042 Status = PciIo->Pci.Read (
1043 PciIo,
1044 EfiPciIoWidthUint8,
1045 PCI_CLASSCODE_OFFSET,
1046 sizeof (PCI_CLASSCODE),
1047 &HdaClassReg
1048 );
1049
1050 //
1051 // Check class code, ignore everything but HDA controllers.
1052 //
1053 if ( !EFI_ERROR (Status)
1054 && ( (HdaClassReg.BaseCode != PCI_CLASS_MEDIA)
1055 || (HdaClassReg.SubClassCode != PCI_CLASS_MEDIA_MIXED_MODE)))
1056 {
1057 return EFI_UNSUPPORTED;
1058 }
1059
1060 return Status;
1061}
1062
1063EFI_STATUS
1064EFIAPI
1066 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1067 IN EFI_HANDLE ControllerHandle,
1068 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
1069 )
1070{
1071 EFI_STATUS Status;
1072 EFI_PCI_IO_PROTOCOL *PciIo;
1073 EFI_DEVICE_PATH_PROTOCOL *HdaControllerDevicePath;
1074 HDA_CONTROLLER_DEV *HdaControllerDev;
1075 UINT32 OpenMode;
1076
1077 //
1078 // Identify device by the path required to access it in config.plist.
1079 //
1080 DebugPrintDevicePathForHandle (DEBUG_INFO, "HDA: Connecting controller", ControllerHandle);
1081
1082 OpenMode = EFI_OPEN_PROTOCOL_BY_DRIVER;
1083
1084 //
1085 // Open PCI I/O protocol.
1086 // Access Denied typically means OpenCore DisconnectHda quirk is required
1087 // to free up the controller, e.g. on Apple hardware or VMware Fusion.
1088 //
1089 do {
1090 Status = gBS->OpenProtocol (
1091 ControllerHandle,
1092 &gEfiPciIoProtocolGuid,
1093 (VOID **)&PciIo,
1094 This->DriverBindingHandle,
1095 ControllerHandle,
1096 OpenMode
1097 );
1098
1099 if ( (OpenMode == EFI_OPEN_PROTOCOL_BY_DRIVER)
1100 && (Status == EFI_ALREADY_STARTED))
1101 {
1102 DEBUG ((DEBUG_INFO, "HDA: %a%a - %r\n", "Open PCI I/O protocol", "", Status));
1103 return Status;
1104 }
1105
1106 if (EFI_ERROR (Status)) {
1107 if ( PcdGetBool (PcdAudioControllerTryProtocolGetMode)
1108 && (Status == EFI_ACCESS_DENIED)
1109 && (OpenMode == EFI_OPEN_PROTOCOL_BY_DRIVER))
1110 {
1111 //
1112 // No longer applied just if protocol gVMwareHdaProtocolGuid is found, since it also
1113 // allows sound on other devices where HDA controller is already connected, e.g. Macs.
1114 // On many systems DisconnectHda can be used to avoid the need for this fallback, but
1115 // on some - such as Acer E5 - DisconnectHda does not work but this method does.
1116 //
1117 DEBUG ((DEBUG_INFO, "HDA: %r using DRIVER mode, trying GET mode\n", Status));
1118 OpenMode = EFI_OPEN_PROTOCOL_GET_PROTOCOL;
1119 continue;
1120 }
1121
1122 DEBUG ((DEBUG_WARN, "HDA: %a%a - %r\n", "Open PCI I/O protocol", " (try DisconnectHda quirk?)", Status));
1123 return Status;
1124 }
1125 } while (EFI_ERROR (Status));
1126
1127 //
1128 // Open Device Path protocol.
1129 //
1130 Status = gBS->OpenProtocol (
1131 ControllerHandle,
1133 (VOID **)&HdaControllerDevicePath,
1134 This->DriverBindingHandle,
1135 ControllerHandle,
1136 OpenMode
1137 );
1138 if (EFI_ERROR (Status)) {
1139 DEBUG ((DEBUG_WARN, "HDA: Open device path protocol - %r\n", Status));
1140 goto CLOSE_PCIIO;
1141 }
1142
1143 //
1144 // Allocate controller device.
1145 //
1146 HdaControllerDev = AllocateZeroPool (sizeof (HDA_CONTROLLER_DEV));
1147 if (HdaControllerDev == NULL) {
1148 Status = EFI_OUT_OF_RESOURCES;
1149 goto CLOSE_PCIIO;
1150 }
1151
1152 //
1153 // Fill controller device data.
1154 //
1156 HdaControllerDev->PciIo = PciIo;
1157 HdaControllerDev->DevicePath = HdaControllerDevicePath;
1158 HdaControllerDev->DriverBinding = This;
1159 HdaControllerDev->ControllerHandle = ControllerHandle;
1160 HdaControllerDev->OpenMode = OpenMode;
1161 HdaControllerDev->Quirks = HDA_CONTROLLER_QUIRK_INITIAL;
1162 InitializeSpinLock (&HdaControllerDev->SpinLock);
1163
1164 //
1165 // Setup PCI hardware.
1166 //
1167 Status = HdaControllerInitPciHw (HdaControllerDev);
1168 if (EFI_ERROR (Status)) {
1169 DEBUG ((DEBUG_WARN, "HDA: Init PCI HW - %r\n", Status));
1170 goto FREE_CONTROLLER;
1171 }
1172
1173 //
1174 // Get controller name.
1175 //
1176 HdaControllerGetName (HdaControllerDev);
1177
1178 //
1179 // Reset controller.
1180 //
1181 Status = HdaControllerReset (HdaControllerDev, TRUE);
1182 if (EFI_ERROR (Status)) {
1183 DEBUG ((DEBUG_WARN, "HDA: Controller reset - %r\n", Status));
1184 goto FREE_CONTROLLER;
1185 }
1186
1187 //
1188 // Install info protocol.
1189 //
1190 Status = HdaControllerInstallProtocols (HdaControllerDev);
1191 if (EFI_ERROR (Status)) {
1192 DEBUG ((DEBUG_WARN, "HDA: Install protocols - %r\n", Status));
1193 goto FREE_CONTROLLER;
1194 }
1195
1196 //
1197 // Initialize CORB and RIRB.
1198 //
1199 Status = HdaControllerInitRingBuffer (&HdaControllerDev->Corb, HdaControllerDev, HDA_RING_BUFFER_TYPE_CORB);
1200 if (EFI_ERROR (Status)) {
1201 DEBUG ((DEBUG_WARN, "HDA: Init CORB - %r\n", Status));
1202 goto FREE_CONTROLLER;
1203 }
1204
1205 Status = HdaControllerInitRingBuffer (&HdaControllerDev->Rirb, HdaControllerDev, HDA_RING_BUFFER_TYPE_RIRB);
1206 if (EFI_ERROR (Status)) {
1207 DEBUG ((DEBUG_WARN, "HDA: Init RIRB - %r\n", Status));
1208 goto FREE_CONTROLLER;
1209 }
1210
1211 //
1212 // Start CORB and RIRB.
1213 //
1214 Status = HdaControllerSetRingBufferState (&HdaControllerDev->Corb, TRUE, HDA_RING_BUFFER_TYPE_CORB);
1215 if (EFI_ERROR (Status)) {
1216 DEBUG ((DEBUG_WARN, "HDA: Start CORB - %r\n", Status));
1217 goto FREE_CONTROLLER;
1218 }
1219
1220 Status = HdaControllerSetRingBufferState (&HdaControllerDev->Rirb, TRUE, HDA_RING_BUFFER_TYPE_RIRB);
1221 if (EFI_ERROR (Status)) {
1222 DEBUG ((DEBUG_WARN, "HDA: Start RIRB - %r\n", Status));
1223 goto FREE_CONTROLLER;
1224 }
1225
1226 //
1227 // Prescan codecs for codec vendor id, required before init streams.
1228 //
1229 Status = HdaControllerScanCodecs (HdaControllerDev, TRUE);
1230 if (EFI_ERROR (Status)) {
1231 DEBUG ((DEBUG_WARN, "HDA: Scan codecs 1/2 - %r\n", Status));
1232 goto FREE_CONTROLLER;
1233 }
1234
1235 //
1236 // Init streams after prescan, uses codec vendor id.
1237 //
1238 Status = HdaControllerInitStreams (HdaControllerDev);
1239 if (EFI_ERROR (Status)) {
1240 DEBUG ((DEBUG_WARN, "HDA: Init streams - %r\n", Status));
1241 goto FREE_CONTROLLER;
1242 }
1243
1244 //
1245 // Full scan for codecs once streams are ready.
1246 //
1247 Status = HdaControllerScanCodecs (HdaControllerDev, FALSE);
1248 if (EFI_ERROR (Status)) {
1249 DEBUG ((DEBUG_WARN, "HDA: Scan codecs 2/2 - %r\n", Status));
1250 goto FREE_CONTROLLER;
1251 }
1252
1253 DEBUG ((DEBUG_INFO, "HDA: Controller initialized\n"));
1254 return EFI_SUCCESS;
1255
1256FREE_CONTROLLER:
1257
1258 //
1259 // Free controller device.
1260 //
1261 HdaControllerCleanup (HdaControllerDev);
1262
1263CLOSE_PCIIO:
1264
1265 //
1266 // Close protocols.
1267 //
1268 if (OpenMode == EFI_OPEN_PROTOCOL_BY_DRIVER) {
1269 gBS->CloseProtocol (
1270 ControllerHandle,
1272 This->DriverBindingHandle,
1273 ControllerHandle
1274 );
1275 gBS->CloseProtocol (
1276 ControllerHandle,
1277 &gEfiPciIoProtocolGuid,
1278 This->DriverBindingHandle,
1279 ControllerHandle
1280 );
1281 }
1282
1283 return Status;
1284}
1285
1286EFI_STATUS
1287EFIAPI
1289 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1290 IN EFI_HANDLE ControllerHandle,
1291 IN UINTN NumberOfChildren,
1292 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
1293 )
1294{
1295 EFI_STATUS Status;
1296 HDA_CONTROLLER_DEV *HdaControllerDev;
1297 UINT32 OpenMode;
1298
1299 //
1300 // Identify device by the path required to access it in config.plist.
1301 //
1302 DebugPrintDevicePathForHandle (DEBUG_INFO, "HDA: Disconnecting controller", ControllerHandle);
1303
1304 OpenMode = EFI_OPEN_PROTOCOL_BY_DRIVER;
1305
1306 //
1307 // Get controller device.
1308 //
1309 Status = gBS->OpenProtocol (
1310 ControllerHandle,
1311 &gEfiCallerIdGuid,
1312 (VOID **)&HdaControllerDev,
1313 This->DriverBindingHandle,
1314 ControllerHandle,
1315 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1316 );
1317
1318 if (!EFI_ERROR (Status)) {
1319 DEBUG ((DEBUG_VERBOSE, "HDA: Cleaning up\n"));
1320 //
1321 // Gather open mode.
1322 //
1323 OpenMode = HdaControllerDev->OpenMode;
1324
1325 //
1326 // Ensure controller device is valid.
1327 //
1328 if (HdaControllerDev->Signature != HDA_CONTROLLER_PRIVATE_DATA_SIGNATURE) {
1329 return EFI_INVALID_PARAMETER;
1330 }
1331
1332 //
1333 // Cleanup controller.
1334 //
1335 HdaControllerCleanup (HdaControllerDev);
1336 }
1337
1338 //
1339 // Close protocols.
1340 //
1341 if (OpenMode == EFI_OPEN_PROTOCOL_BY_DRIVER) {
1342 Status = gBS->CloseProtocol (
1343 ControllerHandle,
1345 This->DriverBindingHandle,
1346 ControllerHandle
1347 );
1348 DEBUG ((DEBUG_VERBOSE, "HDA: Close device path protocol - %r\n", Status));
1349 Status = gBS->CloseProtocol (
1350 ControllerHandle,
1351 &gEfiPciIoProtocolGuid,
1352 This->DriverBindingHandle,
1353 ControllerHandle
1354 );
1355 DEBUG ((DEBUG_VERBOSE, "HDA: Close PCI I/O protocol - %r\n", Status));
1356 }
1357
1358 DEBUG ((DEBUG_INFO, "HDA: Disconnected\n"));
1359
1360 return EFI_SUCCESS;
1361}
EFI_STATUS EFIAPI HdaControllerSendCommands(IN HDA_CONTROLLER_DEV *HdaDev, IN UINT8 CodecAddress, IN UINT8 Node, IN EFI_HDA_IO_VERB_LIST *Verbs)
STATIC VOID EFIAPI HdaControllerExitBootServicesHandler(IN EFI_EVENT Event, IN VOID *Context)
VOID EFIAPI HdaControllerStreamOutputPollTimerHandler(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI HdaControllerInstallProtocols(IN HDA_CONTROLLER_DEV *HdaControllerDev)
EFI_STATUS EFIAPI HdaControllerReset(IN HDA_CONTROLLER_DEV *HdaControllerDev, IN BOOLEAN Restart)
EFI_STATUS EFIAPI HdaControllerDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL)
EFI_STATUS EFIAPI HdaControllerDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer OPTIONAL)
EFI_DEVICE_PATH_PROTOCOL * gForcedControllerDevicePath
EFI_STATUS EFIAPI HdaControllerDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL)
EFI_STATUS EFIAPI HdaControllerInitPciHw(IN HDA_CONTROLLER_DEV *HdaControllerDev)
EFI_STATUS EFIAPI HdaControllerScanCodecs(IN HDA_CONTROLLER_DEV *HdaControllerDev, IN BOOLEAN PreScan)
VOID EFIAPI HdaControllerCleanup(IN HDA_CONTROLLER_DEV *HdaControllerDev)
STATIC EFI_STATUS HdaControllerRestoreNoSnoopEn(IN HDA_CONTROLLER_DEV *HdaControllerDev)
BOOLEAN gRestoreNoSnoop
VOID EFIAPI HdaControllerGetName(IN HDA_CONTROLLER_DEV *HdaControllerDev)
#define HDA_RIRB_RESP(Response)
#define HDA_CONTROLLER_QUIRK_INITIAL
EFI_STATUS HdaControllerSetRingBufferState(IN HDA_RING_BUFFER *HdaRingBuffer, IN BOOLEAN Enable, IN HDA_RING_BUFFER_TYPE Type)
VOID HdaControllerStreamIdle(IN HDA_STREAM *HdaStream)
VOID HdaControllerStreamAbort(IN HDA_STREAM *HdaStream)
#define HDA_STREAM_BUF_SIZE
EFI_STATUS EFIAPI HdaControllerHdaIoSendCommand(IN EFI_HDA_IO_PROTOCOL *This, IN UINT8 Node, IN UINT32 Verb, OUT UINT32 *Response)
EFI_STATUS HdaControllerInitStreams(IN HDA_CONTROLLER_DEV *HdaDev)
#define HDA_RIRB_UNSOL(Response)
EFI_STATUS EFIAPI HdaControllerHdaIoStopStream(IN EFI_HDA_IO_PROTOCOL *This, IN EFI_HDA_IO_PROTOCOL_TYPE Type)
#define PCI_HDA_TCSEL_TC0_MASK
EFI_STATUS EFIAPI HdaControllerHdaIoGetAddress(IN EFI_HDA_IO_PROTOCOL *This, OUT UINT8 *CodecAddress)
#define HDA_VERSION_MIN_MAJOR
#define HDA_RIRB_CAD(Response)
#define HDA_BDL_BLOCKSIZE
#define HDA_CONTROLLER_QUIRK_QEMU_1
#define HDA_CONTROLLER_PRIVATE_DATA_SIGNATURE
#define HDA_BDL_ENTRY_COUNT
EFI_STATUS EFIAPI HdaControllerHdaIoGetStream(IN EFI_HDA_IO_PROTOCOL *This, IN EFI_HDA_IO_PROTOCOL_TYPE Type, OUT BOOLEAN *State)
#define PCI_HDA_TCSEL_OFFSET
#define HDA_STREAM_DMA_CHECK_THRESH
#define PCI_HDA_DEVC_OFFSET
#define HDA_CONTROLLER_QUIRK_CORB_NO_POLL_RESET
#define HDA_MAX_CODECS
#define PCI_HDA_BAR
EFI_STATUS EFIAPI HdaControllerHdaIoCloseStream(IN EFI_HDA_IO_PROTOCOL *This, IN EFI_HDA_IO_PROTOCOL_TYPE Type)
EFI_STATUS EFIAPI HdaControllerInfoGetVendorId(IN EFI_HDA_CONTROLLER_INFO_PROTOCOL *This, OUT UINT32 *VendorId)
EFI_STATUS EFIAPI HdaControllerHdaIoSetupStream(IN EFI_HDA_IO_PROTOCOL *This, IN EFI_HDA_IO_PROTOCOL_TYPE Type, IN UINT16 Format, OUT UINT8 *StreamId)
#define HDA_CORB_VERB(Cad, Nid, Verb)
VOID HdaControllerCleanupRingBuffer(IN HDA_RING_BUFFER *HdaRingBuffer, IN HDA_RING_BUFFER_TYPE Type)
#define HDA_STREAM_BUFFER_PADDING
#define PCI_HDA_DEVC_NOSNOOPEN
EFI_STATUS EFIAPI HdaControllerInfoGetName(IN EFI_HDA_CONTROLLER_INFO_PROTOCOL *This, OUT CONST CHAR16 **Name)
EFI_STATUS EFIAPI HdaControllerHdaIoStartStream(IN EFI_HDA_IO_PROTOCOL *This, IN EFI_HDA_IO_PROTOCOL_TYPE Type, IN VOID *Buffer, IN UINTN BufferLength, IN UINTN BufferPosition OPTIONAL, IN EFI_HDA_IO_STREAM_CALLBACK Callback OPTIONAL, IN VOID *Context1 OPTIONAL, IN VOID *Context2 OPTIONAL, IN VOID *Context3 OPTIONAL)
EFI_STATUS HdaControllerInitRingBuffer(IN HDA_RING_BUFFER *HdaRingBuffer, IN HDA_CONTROLLER_DEV *HdaDev, IN HDA_RING_BUFFER_TYPE Type)
VOID HdaControllerCleanupStreams(IN HDA_CONTROLLER_DEV *HdaDev)
@ HDA_RING_BUFFER_TYPE_RIRB
@ HDA_RING_BUFFER_TYPE_CORB
#define HDA_CONTROLLER_QUIRK_QEMU_2
EFI_GUID gEfiHdaControllerInfoProtocolGuid
EFI_GUID gEfiHdaIoProtocolGuid
EFI_GUID gEfiHdaIoDevicePathGuid
@ EfiHdaIoTypeOutput
Definition HdaIo.h:49
#define HDA_REG_SDNSTS_FIFOE
#define HDA_REG_STATESTS_CLEAR
#define HDA_REG_SDNSTS_BCIS
#define HDA_REG_GCTL_CRST
#define HDA_REG_SDNSTS_DESE
#define HDA_REG_GCTL
#define HDA_REG_GCAP_ISS(a)
#define HDA_REG_GCAP
#define HDA_REG_SDNSTS(n)
#define HDA_REG_RIRBSTS
#define HDA_REG_SDNLPIB(n)
#define HDA_REG_CORBRP
#define HDA_REG_GCAP_NSDO(a)
#define HDA_REG_GCAP_64OK
#define HDA_REG_RIRBWP
#define HDA_REG_CORBWP
#define HDA_REG_GCAP_OSS(a)
#define HDA_REG_VMAJ
#define HDA_REG_STATESTS
#define HDA_REG_GCAP_BSS(a)
#define HDA_REG_VMIN
#define HDA_VERB_GET_PARAMETER
Definition HdaVerbs.h:363
#define HDA_CODEC_VERB(Verb, Payload)
Definition HdaVerbs.h:32
#define HDA_NID_ROOT
Definition HdaVerbs.h:29
#define HDA_PARAMETER_VENDOR_ID
Definition HdaVerbs.h:370
EFI_BOOT_SERVICES * gBS
VOID DebugPrintDevicePathForHandle(IN UINTN ErrorLevel, IN CONST CHAR8 *Message, IN EFI_HANDLE Handle OPTIONAL)
BOOLEAN EFIAPI IsDevicePathEqual(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2)
#define VEN_INTEL_ID
#define GET_PCI_VENDOR_ID(a)
#define VEN_VMWARE_ID
CONST CHAR8 * OcHdaControllerGetName(IN UINT32 ControllerId)
#define GET_CODEC_VENDOR_ID(a)
#define VEN_QEMU_ID
#define GET_PCI_DEVICE_ID(a)
#define MS_TO_NANOSECONDS(x)
Definition OcMiscLib.h:37
#define MS_TO_MICROSECONDS(x)
Definition OcMiscLib.h:31
CHAR16 * AsciiStrCopyToUnicode(IN CONST CHAR8 *String, IN UINTN Length)
Definition OcAsciiLib.c:119
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_GUID gEfiDevicePathProtocolGuid
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
Definition UserMisc.c:680
@ DONE
Definition inflate.h:49
HDA_DMA_POS_ENTRY * DmaPositions
EFI_PCI_IO_PROTOCOL * PciIo
EFI_DRIVER_BINDING_PROTOCOL * DriverBinding
HDA_RING_BUFFER Rirb
EFI_HANDLE ControllerHandle
HDA_RING_BUFFER Corb
EFI_DEVICE_PATH_PROTOCOL * DevicePath
EFI_HDA_CONTROLLER_INFO_PROTOCOL HdaControllerInfo
HDA_CONTROLLER_DEV * HdaControllerDev
EFI_HDA_IO_PROTOCOL HdaIo
HDA_CONTROLLER_DEV * HdaControllerDev
HDA_STREAM * HdaOutputStream
EFI_HDA_CONTROLLER_INFO_GET_VENDOR_ID GetVendorId
EFI_HDA_CONTROLLER_INFO_GET_NAME GetName
EFI_DEVICE_PATH_PROTOCOL Header
Definition HdaIo.h:207
EFI_HDA_IO_CLOSE_STREAM CloseStream
Definition HdaIo.h:181
EFI_HDA_IO_GET_ADDRESS GetAddress
Definition HdaIo.h:177
EFI_HDA_IO_START_STREAM StartStream
Definition HdaIo.h:183
EFI_HDA_IO_SETUP_STREAM SetupStream
Definition HdaIo.h:180
EFI_HDA_IO_SEND_COMMAND SendCommand
Definition HdaIo.h:178
EFI_HDA_IO_GET_STREAM GetStream
Definition HdaIo.h:182
EFI_HDA_IO_STOP_STREAM StopStream
Definition HdaIo.h:184
UINT32 * Verbs
Definition HdaIo.h:58
UINT32 * Responses
Definition HdaIo.h:59
BOOLEAN DmaCheckComplete
EFI_HDA_IO_STREAM_CALLBACK Callback
UINT32 DmaPositionTotal
UINT32 BufferSourcePosition
VOID * CallbackContext1
UINT8 * BufferData
VOID * CallbackContext2
UINT32 BufferSourceLength
UINT32 DmaPositionLast
BOOLEAN UseLpib
UINT8 * BufferSource
VOID * CallbackContext3
BOOLEAN BufferActive
UINT32 DmaCheckCount
HDA_CONTROLLER_DEV * HdaDev