7 #include <drv/audio/ac97.h>
11 #include "lib/stdio.h"
14 uint8_t ac97_busnum, ac97_slot, ac97_func;
16 bool ac97_initialized =
false;
17 bool ac97_varibale_sample_rate =
false;
19 uint16_t native_audio_mixer = 0;
20 uint16_t native_audio_bus_master = 0;
22 uint8_t ac97_bar0_type = 0;
23 uint8_t ac97_bar1_type = 0;
25 size_t currently_pages_count = 0;
27 uint32_t current_sample_rate = 44100;
31 char* ac97_audio_buffer = 0;
32 size_t ac97_audio_buffer_phys;
36 #define AUDIO_BUFFER_SIZE (128 * KB)
39 void ac97_set_master_volume(uint8_t left, uint8_t right,
bool mute) {
40 const uint16_t value = (right & 63) << 0
42 | (uint8_t)mute << 15;
43 outw(native_audio_mixer + NAM_SET_MASTER_VOLUME, value);
47 void ac97_set_pcm_volume(uint8_t right, uint8_t left,
bool mute) {
48 uint16_t value = (right & 31) << 0
51 outw(native_audio_mixer + NAM_SET_PCM_VOLUME, value);
54 void ac97_set_pcm_sample_rate(uint16_t sample_rate) {
55 if(!ac97_varibale_sample_rate
56 || sample_rate > AC97_MAX_RATE
57 || sample_rate < AC97_MIN_RATE)
60 outw(native_audio_mixer + NAM_SAMPLE_RATE, sample_rate);
77 void ac97_reset_channel() {
78 outb(native_audio_bus_master + 0x1b, inb(native_audio_bus_master + 0x1B) | 0x02);
81 void ac97_clear_status_register() {
82 outb(native_audio_bus_master + 0x16, 0x1C);
85 void _ac97_update_bdl(uint32_t address) {
86 outl(native_audio_bus_master + NABM_PCM_OUT, address);
89 void ac97_update_bdl() {
90 _ac97_update_bdl((uint32_t) ac97_buffer);
93 void ac97_update_lvi(uint8_t index) {
94 outb(native_audio_bus_master + NABM_PCM_OUT + 0x05, index);
97 void ac97_set_play_sound(
bool play) {
99 outb(native_audio_bus_master + 0x1b, (uint8_t)play);
104 pci_find_device(AC97_VENDOR, AC97_DEVICE, &ac97_busnum, &ac97_slot, &ac97_func);
106 const uint16_t devnum =
pci_get_device(ac97_busnum, ac97_slot, ac97_func);
108 qemu_log(
"AC'97 ID: %d (%x)", devnum, devnum);
110 if(devnum == PCI_VENDOR_NO_DEVICE) {
111 qemu_log(
"AC'97 not connected!");
114 qemu_log(
"Detected AC'97");
120 qemu_log(
"Command register is: %x", command_register);
122 command_register |= 0x05;
124 qemu_log(
"Command register now is: %x", command_register);
125 pci_write(ac97_busnum, ac97_slot, ac97_func, 4, command_register);
133 native_audio_mixer--;
134 native_audio_bus_master--;
140 qemu_log(
"NAM: %x; NABM: %x", native_audio_mixer, native_audio_bus_master);
142 const uint16_t extended_id = inw(native_audio_mixer + NAM_EXTENDED_ID);
144 const size_t rev = (extended_id >> 10) & 0b11;
145 const char* rev_strs[] = {
"r < 21",
"r22",
"r23"};
146 qemu_log(
"Codec revision: (%d) %s", rev, rev_strs[rev]);
148 uint32_t gc = inl(native_audio_bus_master + NABM_GLOBAL_CONTROL);
149 qemu_log(
"Received global control: (%d) %x", gc, gc);
151 outl(native_audio_bus_master + NABM_GLOBAL_CONTROL, gc);
152 outw(native_audio_mixer + NAM_RESET, 1);
153 qemu_log(
"Cold reset");
159 const uint32_t status = inl(native_audio_bus_master + NABM_GLOBAL_STATUS);
161 qemu_log(
"Status: %d (%x)\n", status, status);
168 uint16_t extended_audio = inw(native_audio_mixer + NAM_EXTENDED_AUDIO);
169 qemu_log(
"Status: %d", extended_audio);
171 if((extended_id & 1) != 0) {
172 qemu_log(
"AC'97 supports variable sample rate!!!\n");
174 ac97_varibale_sample_rate =
true;
177 outw(native_audio_mixer + NAM_EXTENDED_AUDIO, extended_audio);
179 ac97_set_pcm_sample_rate(ac97_varibale_sample_rate ? 44100 : 48000);
181 ac97_set_master_volume(0, 0,
false);
182 ac97_set_pcm_volume(0, 0,
false);
184 ac97_audio_buffer = kmalloc_common(AUDIO_BUFFER_SIZE, PAGE_SIZE);
185 ac97_audio_buffer_phys = virt2phys(get_kernel_page_directory(),
186 (virtual_addr_t)ac97_audio_buffer);
188 qemu_log(
"Updated capabilities\n");
192 ac97_initialized =
true;
194 qemu_log(
"AC'97 initialized successfully!");
197 bool ac97_is_initialized() {
198 return ac97_initialized;
201 void ac97_FillBDLs() {
202 size_t sample_divisor = 2;
208 size_t bdl_span = AUDIO_BUFFER_SIZE / 32;
211 for (
size_t j = 0; j < AUDIO_BUFFER_SIZE; j += bdl_span) {
212 ac97_buffer[filled].memory_pos = (
void*)(ac97_audio_buffer_phys + j);
213 ac97_buffer[filled].sample_count = (bdl_span / sample_divisor) + 2;
219 qemu_log(
"Fills: %d", filled);
223 ac97_buffer[filled].flags = (1 << 14) | (1 << 15);
226 ac97_update_lvi(filled);
231 void ac97_WriteAll(
void* buffer,
size_t size) {
236 for(; loaded < size; loaded += AUDIO_BUFFER_SIZE) {
237 size_t block_size = MIN(size - loaded, AUDIO_BUFFER_SIZE);
240 (
char*)buffer + loaded,
243 if (block_size < AUDIO_BUFFER_SIZE) {
244 memset((
char *) ac97_audio_buffer + block_size,
246 AUDIO_BUFFER_SIZE - block_size);
249 ac97_update_lvi(ac97_lvi);
251 ac97_set_play_sound(
true);
252 ac97_clear_status_register();
254 while ((inb(native_audio_bus_master + 0x16) & (1 << 1)) == 0) {
255 __asm__
volatile(
"nop");
264 FILE* file =
fopen(
"R:\\Sayori\\a.wav",
"rb");
265 fseek(file, 0, SEEK_END);
269 fseek(file, 0xae, SEEK_SET);
278 ac97_set_master_volume(2, 2,
false);
279 ac97_set_pcm_volume(2, 2,
false);
284 ac97_reset_channel();
Основные определения ядра
struct registers __attribute__((packed))
Структура данных пакета от мыши
size_t filesize(const char *Path)
[FileIO] Возвращает размер указанного файла
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset)
[PCI] Чтение 16-битных полей из пространства механизма конфигураций 1
void pci_find_device(uint16_t vendor, uint16_t device, uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret)
[PCI] Поиск устройства по ID-поставшика и устройства
uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение ID-Устройства
ssize_t fseek(FILE *stream, ssize_t offset, uint8_t whence)
Установка позиции в потоке данных относительно текущей позиции
void fclose(FILE *stream)
Закончить работу с файлом
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
int ftell(FILE *stream)
Текущая позиция считывания в файле
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Структура файла. Требуется для работы с VFS.