OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Sep 23, 2019 11:29 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 55 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject: Re: Configuring Intel HDA
PostPosted: Thu Jun 27, 2019 9:42 pm 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1065
I'm going to save you a ton of work, and give you the answer you are looking for.

In QEMU, the HDAudio base address is 0xFEBF0000. You can simply hard-code this address for your Intel HD Audio logic, for now.

Just promise that you will come back later and replace it with working PCI device enumeration logic. :)

You will know it's working properly when the PCI device address you get for the HD Audio device matches this value.

You're welcome.

_________________
Project: OZone
Source: GitHub
Current Task: DOSBox Compatibility
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Fri Jun 28, 2019 10:35 am 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 56
The problem is that I feel like I'm missing something. I wonder if we're going about this the wrong way, so might someone start from the beginning and explain the offset calculation method? I'm sorry, I'm just struggling to understand how I would go about actually implementing this. If I have a 32-bit integer of all zeros, and set bits 0-7 to 4 (100b), than the number becomes '4h' and not, say' 'Ah'. There's a disconnect between me and you guys and I'm trying to close the gap but I feel like its not being explained clearly enough and the explanations just raise more questions. :(
Edit: I figured it out, thanks to the code example provided by Klakap. Thanks! :)


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Sun Jun 30, 2019 2:46 pm 
Offline
Member
Member
User avatar

Joined: Mon May 22, 2017 5:56 am
Posts: 142
Binary operations take some getting used to! "Or" just merges the bits without carrying over the excess to higher bits. It will act like addition if there are no ones in the same positons in both numbers. To illustrate:

Acting the same, in decimal: 4 + 2 = 6; 4 or 2 = 6. Acting the same, in binary: 1 0 0 + 1 0 = 1 1 0; 1 0 0 or 1 0 = 1 1 0.

Acting different, in decimal: 6 + 2 = 8; 6 or 2 = 6. Acting different, in binary: 1 1 0 + 1 0 = 1 0 0 0; 1 1 0 or 1 0 = 1 1 0.

_________________
Wir mussen wissen, wir werden wissen.


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Sun Jun 30, 2019 5:10 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 56
eekee wrote:
Binary operations take some getting used to! "Or" just merges the bits without carrying over the excess to higher bits. It will act like addition if there are no ones in the same positons in both numbers. To illustrate:

Acting the same, in decimal: 4 + 2 = 6; 4 or 2 = 6. Acting the same, in binary: 1 0 0 + 1 0 = 1 1 0; 1 0 0 or 1 0 = 1 1 0.

Acting different, in decimal: 6 + 2 = 8; 6 or 2 = 6. Acting different, in binary: 1 1 0 + 1 0 = 1 0 0 0; 1 1 0 or 1 0 = 1 1 0.

Thanks! I'm now using the offsets in the PCI article but am still getting zeros in all five BARs. Not really sure what I'm messing up now...


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Tue Jul 02, 2019 4:32 pm 
Online
Member
Member
User avatar

Joined: Wed Oct 27, 2010 4:53 pm
Posts: 1032
Location: Scotland
What are you getting for the four bytes at offset 8 then? I want to see what you're getting for the bytes at A and B, because A should contain the value 3 and B should hold a 4, if you're looking at an HDA device.

_________________
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


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Wed Jul 03, 2019 12:48 am 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 56
Offset 8 is 1. (Bits 0-3 are 1 -- bits 4-31 are unset.)


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Wed Jul 03, 2019 11:17 am 
Online
Member
Member
User avatar

Joined: Wed Oct 27, 2010 4:53 pm
Posts: 1032
Location: Scotland
Ethin wrote:
Offset 8 is 1. (Bits 0-3 are 1 -- bits 4-31 are unset.)

Well, your problem is in finding the HDA device, because you're looking in the wrong place for it. You say in your first post "My OS detects the audio controller:"

Quote:
PCI: probe: found Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (Multimedia controller)

I don't know how you did that probe to find that information. How are you finding PCI devices? My OS currently uses the "brute fore" method described on the PCI page to find out what's there, then it checks the class and subclass codes of anything that's present to see if it's a device which my OS can handle, specifically looking for USB controllers and HDA. In each case, that involves looking at offset 8 to see the values held by offsets A and B. That means that the four bytes I send to the PCI CONFIG_ADDRESS port go through all 256 possible bus numbers (using bits 16-23) and using each one 32 times so that I can go through all possible device numbers for each (using bits 11-15). If you aren't doing something of that kind and successfully finding the right class and subclass values, I don't know how you're identifying the HDA device to look for its BAR 0. Clearly you're not finding it if you aren't finding the right class and subclass values there. You need to post your code for finding PCI devices and identifying HDA.

_________________
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


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Wed Jul 03, 2019 7:08 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 56
My code for finding PCI devices is as follows, in rust:
Code:
fn get_vendor_id(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 0)
}

fn get_device_id(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 2)
}

fn get_class_id(bus: u16, device: u16, function: u16) -> u32 {
    (read_word(bus, device, function, 0xA) & !0x00FF) >> 8
}

fn get_prog_if(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 0x8).get_bits(8..15)
}

fn get_header_type(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 0x0C).get_bits(16..23)
}

fn get_subclass_id(bus: u16, device: u16, function: u16) -> u32 {
    (read_word(bus, device, function, 0x08) & !0xFF00)
}

fn get_status(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 0x04).get_bits(24..31)
}

fn get_command(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 0x04).get_bits(16..23)
}

fn get_rev(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 0x08).get_bits(0..7)
}

This roughly translates to (in C):
Code:
// This code is only provided to make the C code work properly. The syntax is a bit different in rust
int32_t get_bit(int32_t num, uint8_t bit) {
    if (bit < 32) {
        return (num & (1 << bit));
    } else {
        return -1;
    }
}

int32_t get_bits(int32_t number, uint8_t start, uint8_t end) {
    if (start < 32 && end <= 32 && start < end) {
        // shift away high bits
        int32_t bits = number << (32 - end) >> (32 - end);
        // shift away low bits
        return bits >> start;
    } else {
        return -1;
    }
}

// The typedefs u8, u16, u32, u64, i8, ... map to their equivalent C types

u32 get_vendor_id(u16 bus, u16 device, u16 function) {
    return read_word(bus, device, function, 0);
}

u32 get_device_id(u16 bus, u16 device, u16 function) {
    return read_word(bus, device, function, 2);
}

u32 get_class_id(u16 bus, u16 device, u16 function) {
    return (read_word(bus, device, function, 0xA) & !0x00FF) >> 8;
}

u32 get_prog_if(u16 bus, u16 device, u16 function) {
    return get_bits(read_word(bus, device, function, 0x08), 8, 15);
}

u32 get_header_type(u16 bus, u16 device, u16 function) {
    return get_bits(read_word(bus, device, function, 0x0C), 16, 23);
}

u32 get_subclass_id(u16 bus, u16 device, u16 function) {
    return (read_word(bus, device, function, 0x08) & !0xFF00);
}

u32 get_status(u16 bus, u16 device, u16 function) {
    return get_bits(read_word(bus, device, function, 0x04), 24, 31);
}

u32 get_command(u16 bus, u16 device, u16 function) {
    return get_bits(read_word(bus, device, function, 0x04), 16, 23);
}

u32 get_rev(u16 bus, u16 device, u16 function) {
    return get_bits(read_word(bus, device, function, 0x08), 0, 7);
}

I'm doing the brute-force method to find PCI devices as well. My kernel loops through the buses, slots and functions:
Code:
// C (original is rust)
void probe() {
    for (int bus = 0; bus < 256; bus++) {
        for (int slot = 0; slot < 32; slot++) {
            for (int function = 0; function < 8; function++) {
                // Get vendor, device, class and subclass codes.
                u32 vendor = get_vendor_id(bus, slot, function);
                if (vendor == 0xFFFF) {
                    continue;
                }
                u32 device = get_device_id(bus, slot, function);
                u32 class = get_class_id(bus, slot, function);
                u32  subclass = get_subclass_id(bus, slot, function);
                // Assumed printf function
                printf(
                    "PCI: probe: found %s %s (%s)",
                    get_vendor_string(vendor),
                    get_device_string(device),
                    get_subclass_string(class, subclass)
                );
// continue probe...

I get vendor strings and so on by doing something majorly inefficient, but it works for now. I'll definitely change it later though! My kernel has a file, pcidb.rs, which embeds the entire PCI ID repository as a giant switch statement. (In rust its called a match statement, and each "case" in a switch statement is called an "arm".) I know, its majorly inefficient and disgusting, which is why I'll definitely change it later! :) Modifying the printf statement (in my kernel its printkln) to print device data, I get this for the HDA device:
Quote:
PCI: probe: found Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (Multimedia audio controller)
PCI: probe: codes: vendor = 8086h, device = 2668h, class = 4h, subclass = 1h, bus = 0h, slot = 3h, function = 0h
PCI: probe: Offset 8: 1, bits (4 each): 1, 0, 0, 0, 0, 0, 0, 0


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Wed Jul 03, 2019 9:28 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 241
Ethin wrote:
Code:
fn get_vendor_id(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 0)
}

fn get_device_id(bus: u16, device: u16, function: u16) -> u32 {
    read_word(bus, device, function, 2)
}
So what is that last argument to read_word()? Usually, it would be an offset in bytes or in words, depending on your use. So get_device_id() doesn't really make sense to me, but it seems to work for you. I would have thought that last argument needs to be 0 in both cases, only you cut out different bits from the result.


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Wed Jul 03, 2019 10:25 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 56
The last argument to read_word is the offset (in words). Its pretty much taken directly from the wiki.


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Thu Jul 04, 2019 11:12 am 
Online
Member
Member
User avatar

Joined: Wed Oct 27, 2010 4:53 pm
Posts: 1032
Location: Scotland
Quote:
class = 4h, subclass = 1h

That's a step forward. The PCI wiki page says that's a multimedia audio controller, while subclass 3h is an audio device (and can be AC97 or HDA). I've only ever encountered the latter, but it now looks as if there are two different subclass values that can lead to an HDA device. The puzzle now is why the BAR 0 address is zero. I'd try going through all eight function numbers to see if the device is actually made available in one of those. Spyder probably knows the answer to this though.

_________________
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


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Thu Jul 04, 2019 12:33 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 56
My PCI code may be broken somehow. Could that be the case?


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Sat Jul 06, 2019 4:41 pm 
Online
Member
Member
User avatar

Joined: Wed Oct 27, 2010 4:53 pm
Posts: 1032
Location: Scotland
Ethin wrote:
My PCI code may be broken somehow. Could that be the case?

I don't know, but you are getting a class and subclass that look viable. Have you tried looking through the other seven function numbers (bits 8 to 10) at that location (without changing the bus number and device number) to see if the HDA device is made available on one of those. If there's nothing at any of them, then I don't know what else to try, but people may be holding back from making suggestions until you've confirmed that you've checked those other function numbers.

_________________
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


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Sat Jul 06, 2019 10:43 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 56
If you mean the prog if, status, and command offsets, I have those, which may answer your question:
I added extra codes after the existing ones in the kernel PCI debug output. Here they are now:
Quote:
PCI: probe: codes: vendor = 8086h, device = 2668h, class = 4h, subclass = 1h, prog if=0h, rev=1h, status=0h, command=0h, bus = 0h, slot = 3h, function = 0h

Here is the other information from the kernel:
* BIST is 0
* The header type is 00h.
* Latency timer is 0h.
* Cache line size is 0h.
In the register table for header type 00h (I called it the "General Device Table"):
* BARS0-5, cis PTR, subsystem ID, subsystem vendor ID, expansion ROM address, max latency, min grant, and caps PTR are all 0h.
* Interrupt pin is 01h.
* Interrupt line is 11 (43 in my case).
Does that answer your question?


Top
 Profile  
 
 Post subject: Re: Configuring Intel HDA
PostPosted: Sun Jul 07, 2019 6:56 am 
Offline
Member
Member
User avatar

Joined: Mon May 22, 2017 5:56 am
Posts: 142
If this doesn't work out, I've got a little suggestion I'm putting out here while I remember: USB audio. It's not a magic pill, USB can be trouble too, but once you've got the host controller working there's a standard protocol for USB audio, and the hardware can be cheap.

_________________
Wir mussen wissen, wir werden wissen.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 55 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group