Hi,
I, myself, have not done much with the AC97, but have started looking over it, and am curious to what you have found.
I did see a few things in your code though:
Code:
//NABM offsets
#define AC97_NABM_PORT_POBDBAR 0x10
#define AC97_NABM_PORT_POLVI 0x15
#define AC97_NABM_PORT_POCONTROL 0x1B
#define AC97_NABM_PORT_GLB_CTRL_STAT 0x60
I don't think that last one is at offset 0x60. Did you mean the Global Control and Global Status registers? They are at 0x2C and 0x30 respectively, and each are 32-bits in size.
Code:
//BUFFERS
struct buffer_desc{
void *buffer;
unsigned short length;
int reserved : 14;
unsigned int bup : 1;
unsigned int ioc : 1;
} __attribute__((packed));
I don't like...I can't even remember...oh bit-fields like this. It all depends on the compiler whether it places them in big-endian or little-endian order, and whether it actually only uses the said amount of bits or not. It is best to not use bit-fields and do the read/write yourself.
Code:
void wait(int miliseconds) {
while(miliseconds>0) {
for(int i=0; i<10000; i++) {
inb(0x3F6); //wait
}
miliseconds--;
}
}
As mentioned before, this may or may not wait for very long. In fact, it could wait for an extremely long time if the hardware you are reading from faults due to the consecutive fast reading of the same register over and over.... Does happen....
Code:
//reset
outw(sound_card_nam_bar + AC97_NAM_PORT_RESET, 42);
outb(sound_card_nabm_bar + AC97_NABM_PORT_GLB_CTRL_STAT, 2);
The specs say any write to the reset register is a reset. Why 42?
Also, writing 2 to 0x60 is probably not where you think it should be.
Code:
void ac97_play_buffer(void) {
BufDescList[0].buffer=((uint32_t)(sound_buffer));
BufDescList[0].length=0xFFFE;
BufDescList[0].bup=1;
Again, I would not rely upon the fact that the compiler did or did not create these bit-fields like you think it should have.
Anyway, I am just curious to see what you have found. Does your code continue to see an interrupt continuously afterward?
The specs say that you can clear the IOC and RUN bits in that channel's Control register (x_CR, offset 0x[channel]B) or simply "empty" the descriptor table.
Ben
-
http://www.fysnet.net/osdesign_book_series.htm