DavidCooper wrote:
Ethin wrote:
The wiki article was extremely vague and confusing...
Do you mean this one:
https://wiki.osdev.org/Intel_High_Definition_Audio ?
I wrote most of the text on that page, though the incomplete tables were put there by the original builder of the page and aren't greatly useful, but I left them there to be extended by anyone who's keen enough to do that job (and they were subsequently extended a bit by someone). In the meantime, you'll need to find a way to work from the tables in the HDA spec. As you have a visual impairment and rely on software that can't navigate the spec's tables adequately, I would like to try to help you get the information you need so that you can get your device driver written. And yes, it is fully possible to get sound in and out without using interrupts.
If you find the wiki page vague and confusing, then work with me to improve it. I wrote it in order to make navigating the spec easier (because it took a lot of repeated reading through it before I could work out how it ever got to the point where you could send the actual audio data to it or get any back in from a microphone - it is not designed to be easy to understand). By the time I could follow the spec well enough to write a guide to it, I was unable to get my mind back into a state of knowing nothing in order to write a perfect introduction to it for a newcomer with no knowledge of it at all, so I've been waiting ever since for feedback from anyone who needed clarification. Let's discuss it and knock it into proper shape.
Bear in mind that HDA is a complex device which varies widely in form, and operating systems like Windows simply get the card manufacturers to provide drivers for each specific card rather than using a universal driver capable of solving the puzzle as to how all the widgets are arranged (and which kinds exist - manufacturers are good at finding radically different ways to provide the same functionality). The BIOS for specific machines likewise has to be programmed to handle its beeps through the specific card installed in the machine. You will thus ideally want to write something more complex than a normal HDA driver as you'll want it to be adaptable enough to work on machines with different HDA cards in them in case you suddenly have to switch to a new machine and lose your audio interface which you may have come to rely on heavily by that time, but you could get something working sooner if you write a driver for your specific sound card. The vendor ID and device ID numbers are probably 8086 and 2668, but I haven't managed to find a datasheet for it, so we may just have to interrogate the device for its widget list and draw up a map to guide the writing of a simple driver specific to that card.
Yeah, the wiki page is exactly what I'm talking about. I may be able to use interrupts if its possible to do something like 'm doing with my keyboard driver. What I do with that is I have a key queue, command queue and resend queue, all of which are used independently. The command and resend queues work together; every PIC timer tick the queue is read to determine if a command is ready to be sent and, if so, it is sent and removed from the queue. If the keyboard requires a resend, the resend queue holds the last command queued as well, so I just fetch from that and send it on its way. My interrupts module will notify the keyboard driver on an ack, resend, self test success/failure, key error, etc., by calling appropriate functions in the driver. If I could do the same with HDA that would be awesome since the interface would be as asynchronous as you can get without actual threads.
The first issue I'm having with even the simplest tasks with PCI (since that's what would be required to configure it) is sending commands to the device to (say) initiate a BIST if available. As an example, my is_bist_capable() function in my PCI module looks like this:
Code:
fn is_bist_capable(bus: u16, device: u16, function: u16) -> bool {
read_word(bus, device, function, 0x15).get_bit(7)
}
Or in C:
Code:
int is_bist_capable(uint16_t bus, uint16_t device, uint16_t function) {
return (read_word(bus, device, function, 0x15) & (1 << 7));
}
I hope I got the offsets right; I just ORed the register number and offsets together, since I'm not sure of how to actually calculate the offset, and ORing them seemed to yield the right results (when getting the vendor ID for example).
I'm still confused on how to write to the device to initialize it and control it; The PCI article on the wiki gives multiple base memory addresses, and I don't know which one to read from. Would I read from all of them?
What else do you need me to provide you? If I can get passed this hurtle, things will become much easier because I can abstract that in my PCI module.