Configuring Intel HDA

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Configuring Intel HDA

Post by DavidCooper »

Ethin wrote:If you mean the prog if, status, and command offsets, I have those, which may answer your question
I was asking specifically about function number. Whenever you find a device during the brute force scan where you go through all bus and slot numbers, there can be other related devices hidden on other function numbers with that same bus and slot number. This happens with USB, for example, where if you find a USB 2 controller on function 0 you can expect to find associated USB 1 controllers in the same place but using different function numbers, and there can be unused function numbers between used ones, so you need to check them all. (There's no need to check them if there's no device on function zero though, which is why the brute force scan only looks at 256 x 32 addresses rather than 256 x 32 x 8.) The lack of any content in the BAR fields for function 0 for your multimedia audio device means that the HDA address must be hidden somewhere else.

Remember too that Spyder told you this:-
In QEMU, the HDAudio base address is 0xFEBF0000. You can simply hard-code this address for your Intel HD Audio logic, for now.
Have you looked at that address to see what's there? It should be safe to read those memory-mapped ports, so what do the first few look like? Read 256 bytes from there and paste what you find into a reply here. I'll tell you if it looks right, and if so, you can start programming your driver for it and resolve the PCI issue later.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

I tried a few different ways and either I got a page fault or the kernel just hung when attempting to read from address 0xFEBF0000. I tried to get it to read from addresses 0xFEBF0000-0xFEBF0008, but no go with that. I'm running Qemu with the -hwsound all option, so... not really sure why its hanging. I'm attempting to fix the page fault by making it easier to use my memory manager; right now I have to pass the allocator around, something I don't want to have to do (especially since, if I do need to map the page(s) into memory, I don't want to have to pass the page allocator around all over the place).
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Configuring Intel HDA

Post by DavidCooper »

Do you know if your machine actually has HDA capability? I'm wondering if QEMU can only offer HDA if there's an actual HDA device for it to link up to. I can only help once HDA ports have been found. PCI complications and emulators take things outside my narrow range of my knowledge.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

Yep, this machine is HDA compliant; I have an HDA-compliant internal sound card plus a mixer that (I think) uses HDA; by default that is mydefault sound card. So my HDA sound card is still in use, but is being routed through my mixer.
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

OK, so apparently I do need to map address 0xFEBF0000 into memory to read from it (at least, so says Rust). Just to be safe I've allocated addresses 0xFEBF0000-0xFEBF0008. Reading from that yields me zeros. All zeros. (confused!). I might be doing something wrong, I'll look into things. I'm running qemu like so: qemu-system-x86_64 -drive format=raw,file=target\x86_64-kernel-none\debug\bootimage-kernel.bin -serial stdio -s -soundhw all -machine q35
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

OK, so I've fixed my memory allocator and am able to map the physical address 0xFEBF0000 into RAM with identity mapping. However, reading from it yields zeros. Reading from 0xFEBF0001-0xFEBF0007 also yields zeros. I'm not sure of any other way of reading anything above 64 bits of data from a memory address; while Rust does have 128-bit integral types natively, we don't have 128-bit memory addresses, so using thoe types would be overkill.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Configuring Intel HDA

Post by SpyderTL »

You might want to try removing the -machine q35 switch. That may be moving your PCI devices around to different addresses.

Try removing it and see if you start seeing actual values at that 0xFEBF0000 address. I'll also try adding the q35 switch locally and see if I end up with a different BAR0 address.

If you still get all zeros, you may have a problem with your allocator.

EDIT: I'm fairly confident that the HD Audio device is emulated, so it should work even if your host does not support it.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

That worked, thanks! And it got some values!
FEBF0000h => 3C00004401h
FEBF0001h => 3C000044h
FEBF0002h => 3C0000h
FEBF0003h => 3C00h
FEBF0004h => 3Ch
FEBF0005h => 0h
FEBF0006h => 0h
FEBF0007h => 0h
What does all of this mean now that I have it configured? (And that makes me wonder if my PCI code is fine, -machine q35 was must making it look broken?)
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Configuring Intel HDA

Post by SpyderTL »

Yeah, I tried adding -machine q35, and my OS won't even boot. :shock:

I'm going to have to do some digging and find out what the story behind q35 is. From what I've read, it's a lot faster than the default machine, as it uses a lot of Virtio devices that are normally emulated PC compatible devices.

Those values you are seeing are the HD Audio registers. You read and write to those to enable the device, and set up your audio buffers to begin playing audio data. There is a wiki page describing how these registers work. But let us know if you have any specific questions.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

Um?! Wow? I'm surprised now. Never thought that would ever be the problem.
If you mean the Intel HDA article on the Wiki, that's the reason I started this topic -- I found it quite confusing to understand. Perhaps this will fix my PCI issue too...
Perhaps this will solve my PCI issue too...
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

Nope, that didn't solve my PCI issue. Ah well, I'll worry about that later. I guess its time for me to take a hike through the HDA spec if I can... anything I should know about it while I read it (other than the fact that it's wrong about the SSYNC register offset)?
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Configuring Intel HDA

Post by DavidCooper »

Those values are the expected ones for HDA, so you can be sure that you're now looking at HDA ports.

You now have to set up CORB and RIRB so that you can send messages to widgets and receive replies from them, and your priority is to get a list of available widgets along with their connectivity to other widgets so that you can map a path through them from a DAC to the speakers. Once you've worked out that path and set it up properly (by sending commands to the widgets you want to use), you will then set up a DMA engine (which is part of the HDA hardware and is simple to use) to collect wav-like data from a buffer that you can place anywhere in memory, and it will then send that data to the DAC. The DMA engine loops back to the start of the buffer every time it reaches the end, so it will go on playing audio from that loop until you tell it to stop. You can read a port to see where it's currently reading from the buffer and you can then write new audio data up to that point for it to play on the next lap, but because the buffer can be as long as you like, there's no time pressure on the OS, so using interrupts for it isn't essential. You can have it playing silence all the time if you like and write occasional sounds to it not far ahead of the current read position, then delete those sounds from the buffer after the read position has passed them.

It doesn't take a lot of code to get HDA working - it's easy once you understand it. The main difficulty is with finding the right path through the widgets, though the top item on each widget's connectivity list may lead you on a direct path from one of the DACs to the speakers, though that isn't guaranteed.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

Let me guess... the HDA spec is the place to go to find out how to do that?
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Configuring Intel HDA

Post by DavidCooper »

Well, if you're looking for shortcuts, you can learn a lot from bigbob: viewtopic.php?f=1&t=28944
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Configuring Intel HDA

Post by Ethin »

That was actually quite helpful. Thank you.
Looking at the spec, I have a couple more questions. I have no doubt that this topic will have a lot more posts before I figure out exactly how this works. :)
First, am I correct when assuming the following memory addresses for various HDA registers (I won't list them all)?
FEBF0000 - GCAP
FEBF0002 - VMIN
FEBF0003 - VMAJ
Second, the tables for these offsets look different than a table I'm used to in my PDF reader (I wish there was an HTML version of this spec). It looks like:
3.3.2 Offset 00h: GCAP – Global Capabilities
Length: 2 bytes
Table 3.
Global Capabilities
Bit Type Description
15:12 RO
11:8 RO
7:3 RO
2:1 RO
0 RO
Number of Output Streams Supported (OSS): A value of 0000b indicates that there
are no Output Streams supported. A value of maximum 15 output streams are
supported.
0000b: No output streams supported
0001b: 1 output stream supported

1111b: 15 output streams supported
Number of Input Streams Supported (ISS): A value of 0000b indicates that there are
no Input Streams supported. A maximum of 15 input streams are supported.
0000b: No input streams supported
0001b: 1 input stream supported

1111b: 15 input streams supported
Number of Bidirectional Streams Supported (BSS): A value of 00000b indicates that
there are no Bidirectional Streams supported. A maximum of 30 bidirectional streams
are supported.
00000b: No bidirectional streams supported
00001b: 1 bidirectional stream supported

11110b: 30 bidirectional streams supported
Number of Serial Data Out Signals (NSDO): A 0 indicates that one SDO line is
supported; a 1 indicates that two SDO lines are supported. Software can enable the use
of striping by setting the appropriate bit in the Stream Buffer Descriptor.
00: 1 SDO
01: 2 SDOs
10: 4 SDOs
11: Reserved
64 Bit Address Supported (64OK): A 1 indicates that 64 bit addressing is supported by
the controller for BDL addresses, data buffer addresses, and command buffer addresses.
A 0 indicates that only 32-bit addressing is available.
There are a maximum of 30 Streams that can be supported, of which 15 may be configured as
output and 15 may be configured as input streams at any one point in time.
(I gave that hole section to give you more context.) Would anyone mind telling me if the descriptions line up with the bits?
Post Reply