sound, SB, AC97 и другое

Drivers for sound cards
  • Решил немного потрассировать твой драйвер, чтоб понять где именно он виснет. На входе в процедуру service_proc в infinity.asm поставил вывод сообщения "service_proc enter", а на выходе (конкретно: после stdcall wave_out, [ebx],eax,[ebx+8]) - "service_proc leave". Вот что вывалилось в доске отладки при первом вызове SND_OUT:

    service_proc enter
    start play
    service_proc leave ; <- тут он должен вернуть управление в код плеера, ан нет!
    service_proc enter ; 8-( !
    service_proc leave
    service_proc enter
    и т.д. пока система окончательно не зависает.

    Кстати, судя по более детальному логу, wave_out работает нормально. Во всяком случае, ничего подозрительного там внутри я не обнаручил. Короче, баг связан с тем, что обработчик прерывания на выходе просто не возвращает управление, т.е. прерывание самозацикливается. Может быть, при обращении к кодеку что-то происходит с флагом I? Или занчение возврата перезаписывается, но это слишком маловероятно. В общем, одно из двух, IMHO.

    Потом я ещё поменял int 40h на sysenter, но уже в коде своего тестового приложения, а не в твоём плеере. Вот что получилось:
    service_proc enter
    start play
    service_proc leave ; <- и тут система повисла

    Зацикливания уже нет, т.к. нет прерывания, но всё равно виснет :( Возможно, я просто не совсем корректно использую sysenter или он в данном случае не совсем корректно поддерживается...
  • Quantum

    Проверь номер IRQ у ICH6, обработчик не вызывается если это irq 3 . Обработчик прерывания устанавливается только на 5,7,9,10 и 11, irq 3 и 4 оставлены за СОМ портами если они отключены БИОС могла назначить эту линию.
    Я исправил проверку зарезервированных линий и залил на SVN (#565). И ещё посмотри PCIDEV в Колибри может БИОС расшарила прерывание.

    ICH0 заработал или нет ? Проверь с обновлённым драйвером, он теперь ругается на неправильный IRQ.

    Все функции работающме с буферами возвращают 0 в случае успеха и ненулевое значение в случае ошибки. Сейчас это -1 для обозначения любой ошибки, остальные коды ошибок не определены.

    Если нужна синхронизация лучше создать кольцевой буфер. Вот код из DOOM

    Code: Select all

    typedef struct
    {
      unsigned int  code;      RT_INPUT_EMPTY = 0xFF000001
      unsigned int  sender;    unused
      unsigned int  stream;    buffer handle
      unsigned int  offset;
      unsigned int  size;      unused
      unsigned int  unused;
    }SND_EVENT;     
    
    void GetNotify( SND_EVENT *event)
    {
     _asm
     {
       mov eax, 68
       mov ebx, 14
       mov ecx, [event]
       int 0x40
    }
    
    SND_EVENT evnt;
    
      if (err = CreateBuffer(PCM_2_16_11|PCM_RING,0, &hMixBuff))
      {
        printf("Error %x sound not available\n\r", err);
        exit();
      }
      
      if(err = GetBufferSize(hMixBuff, &mix_size))
      {
        printf("Error %x get buffer size\n\r", err);
        printf("size = %x\n\r", mix_size);
        exit();
      };
      mix_size= mix_size/2;      //буфер поделён на две половины
          
      printf("mixer size %d\n\r", mix_size);
    
      if(err=PlayBuffer(hMixBuff, 0))
      {
        printf("Error %x play buffer\n\r", err);
        exit()
      }
      
      mixbuffer = malloc(mix_size);
      
      while(sound_state)
      {
         GetNotify(&evnt);
    
         if(evnt.code != 0xFF000001)
         {
           printf("invalid code %d\n\r", evnt.code);
           continue; 
         }    
         
         if(evnt.stream != hMixBuff)
         {
           printf("invalid stream %d hMixBuff= %d\n\r", evnt.stream, hMixBuff);
           continue; 
         };
         mix_offset= evnt.offset;
         I_UpdateSound();
      };
     
    I_UpdateSound()
    {
      //заполняем mixbuffer семплами
      ...
      ...
      ...
      //
      SetBuffer(hMixBuff,mixbuffer,mix_offset,mix_size);
    }
    SND_EVENT.offset - смещение по которому надо записать семплы (0 или mix_size).

    void GetNotify( SND_EVENT *event) - блокирующая функция, возвращает управление после каждого прерывания
  • Да, ICH6 висит либо на IRQ 3, либо на IRQ 4, в зависимости от включенных в настройках биоса встроенных устройств. В лог отладки выводится "IRQ line not supported". Кажется, я знаю как его сместить на IRQ 5, но не факт что получится, т.к. в этой версии прошивки биоса нельзя явно задавать IRQ. Кстати, если одно IRQ назначено 2м разным устройствам, твой драйвер тоже не будет работать? У меня на этой машине больше 10 разных PCI устройств, так что расшаривание IRQ - явление нормальное.

    Сейчас пойду тестить на ICH0.

    Так что ты мне можешь сказать по поводу размера буфера? 64К - это фиксированное значение и меняться не будет?

    Темы синхронизации через события ты коснулся рановато :)

    Забыл спросить: что плохого в 3м и 4м прерываниях? У меня на этом компе оба COM висят гораздо выше.
    Last edited by Quantum on Wed Jul 04, 2007 8:11 pm, edited 1 time in total.
  • Потестил на ICH. На доске вот что:
    ...
    Cirrus Logic ; ага, это уже что-то новое!
    CS4299D
    create primary buffer
    device not found
    Sound service not loaded

    ПОСЛЕ ЭТОГО я запускаю pcidev и вижу, что встроенная звуковуха, как бедная родственница, как была без IRQ... В общем, там продолжает висеть IRQ 00.

    Драйвер я пересобрал в этот раз под IRQ 7 и заранее отключил LPT, который раньше висел на этом прерывании, зарезервировал 7е прерывание в настройках биоса (хотя, судя по pcidev, на него всё равно никто больше не претендовал). И всё равно прерывание не хочет устанавливаться! Никаких сообщений об ошибке по поводу IRQ не возникает... Мне кажется, что в твоём коде назначения прерывания чего-то не хватает.
  • Мржет стоит добавить в драйвер установку IRQ ? Что бы драйвер приннудительно вписывал в PCI CFG нужный ему IRQ ?
  • Quantum

    Наверное пошла путаница в исходниках. Я их проверю, сделаю версию для IRQ5 и выложу.

    Pavia

    Значение в PCI CFG только для справки, на работу устройства оно не влияет. Реально ISA линия IRQ для PCI устройств устанавливается программирование моста LPC в чипсете. Для упрощения жизни есть функция PCI BIOS выполняющая всю работу, но внедрение доступа к PCI BIOS в Колибри затянулось... Кроме того свободную линию надо ещё найти.
  • Quantum

    Раньше на IRQ3 можно было устанавливать обработчик но оказалось что ещё есть компьютеры только с СОМ мышами и именно на СОМ2 так что пришлось линию оставить за портом. Надо включить в БИОС оба порта, тогда она назначит им irq 3 и 4 по традиции.

    Я не проверял драйвер на расшаренных прерываниях. Обработчик написан так, что считает все прерывания своими. Вообще случайное прерывание от PCI устройства может подвесить систему потому что они не сбрасываются посылкой EOI в PIC. Надо считать регистры устройства и сбросить прерывание вручную.
    Так что ты мне можешь сказать по поводу размера буфера? 64К - это фиксированное значение и меняться не будет?
    Пока никаких изменений не планируется но надо учесть что waveout вернёт управление как только в буфере появится свободное место. Объём данных прокачиваемых за внутренний цикл зависит от битрейта и опреляется в таблице как r_size
    resampler_params:
    ;r_size r_dt resampler_func
    dd 0,0,0 ; 0 PCM_ALL
    dd 16384, 0, copy_stream ; 1 PCM_2_16_48
    dd 16384, 0, m16_stereo ; 2 PCM_1_16_48

    dd 16384, 30109, resample_2 ; 3 PCM_2_16_44
    dd 8192, 30109, resample_1 ; 4 PCM_1_16_44
  • А я уже нашёл баг в переназначении прерывания :) Возможно, удасться самостоятельно его исправить...

    2 Pavia:
    Я тоже так считаю. Надеяться, что биос сама всё правильно настроит... Винда и Линукс ведь первым делом переназначают все прерывания по своему усмотрению, AFAIK.

    2 Serge:
    У меня только один COM и он отключен. Перепробовал все комбинации - аудио назначается только IRQ 3 и 4. Видимо, эта версия биос сначала устанавливает IRQ для сетевухи и звуковухи, а потом уже вешает USB/FD/COM/LPT и т.д. на свободные линии. Когда я убрал из драйвера проверку на валидность 3го и 4го прерывания, опять получил зависание системы.
  • Serge
    Не знал об этом. Надо подумать. Должен же быть способ или стандарт.
    2 Pavia:
    Я тоже так считаю. Надеяться, что биос сама всё правильно настроит... Винда и Линукс ведь первым делом переназначают все прерывания по своему усмотрению, AFAIK.
    Они APIC используют. Да и переназначены они у меня как указано в мануэли от интел. Только одному безхозному выставлен был свой.
    А с сетевухой, это ясно. Я уже забыл, но была там одна документированная странность для встроенных сетевух.
  • 2 Pavia:
    > Они APIC используют.
    Если он есть. В любом случае я не улавливаю концептуальную разницу между APIC и PIC с точки зрения настройки IRQ на старте системы. Например, биос моего старого компа с ICH по умолчанию вообще только дисплею и флопику назначает прерывания, а всё остальное настраивает уже винда или линукс.

    2 Serge:
    sound.asm

    Вот этот код:
    ; call get_LPC_bus ;проверка на интелловский чипсет
    возвращает ошибку. Поэтому я его обратно закомментировал.

    Потом этот (в remap_irq):
    out dx, aX

    При некоторых значениях (IRQ 7, IRQ 6 и др.) просто моментально подвешивает систему и в доску сообщений ничего не успевает отобразиться. Если маску не менять, т.е. подобрать такой IRQ, чтобы после bts маска осталась прежней, зависания не происходит. Есть такие значения (кажется, только IRQ 10 и 11), которые меняют маску и при этом на этом этапе ничего не виснет, но потом идёт это:

    stdcall PciWrite8, dword 0, dword 0xF8, dword 0x61, dword IRQ_LINE

    В тех редких случаях, когда управление сюда вообще доходит, IRQ всё равно не изменяется. В pcidev продолжает висеть IRQ 3 или 4, т.е. новый номер прерывания не назначается. Следующей строчкой ты присваиваешь ctrl.int_line новый номер прерывания, хотя на самом деле всё ещё назначен старый. Поэтому где-то дальше драйвер всё равно виснет, если прямо на этом этапе запуска не вернуть ошибку.

    На моём старом компе с ICH происходит тоже самое.
  • После винта решил занятся звуком, оказывается у меня с этим тоже проблемы.
    Звуковуха: C-Media CMI9739A
    Никаких дополнительных манипуляций не делал. Настройка порта звукового устройства в BOIS отсутствует.

    Попытка воспроизведения wav 8bit mono с помощью sb (релиз 0.7) приводит к завершению приложения:

    Code: Select all

    Process - forced terminate INT: 0000000E
    Process - forced terminate PID: 0000002F
    Process - forced terminate EIP: 8001F866
    Запуск ac97snd (релиз 0.7) приводит к немедленному завершению приложения, без вывода окна приложения:
    1. Ядро и драйвера из релиза:

    Code: Select all

    detect hardware...
    MENUET01 NForce 2
    init codec
    global control 00000008
    global status  00310000
    cold reset
    reset complete
    C-Media Electronics
    CMI9739
    create primary buffer
    2. Ядро и драйвера из svn 565:

    Code: Select all

    NVidiaNForce 2
    PCI command 00000007
    PCI status  000000B0
    code io base       0000D001
    controller io base 0000D401
    codec mmio base      DB000000
    controller mmio base 00000000
    global control 00000008
    global status  00310000
    cold reset
    global control 00000002
    global status  00310100
    reset complete
    C-Media Electronics
    CMI9739
    create primary buffer
    В чем дело, что я опять не так делаю?

    ..bw
  • Очень интересный разговор пошёл... У меня такая проблема была, когда мне поставили новую сетевуху - до этого была одна, встроенная.
    Как я уже писал, после этого встроенная звуковая карта и встроенная сетевая разделили прерывание 11. После этого система стала виснуть при попытке запуска проигрывателя (и звукового драйвера). По совету Serge я отключил в биосе встроенную сетевую карту, звуковая подсистема снова начала нормально запускаться.
    Вчера я получил новый звуковой драйвер и протестировал его, снова включив встроенную сетевуху. Теперь зависания не происходит, вместо этого звуковой драйвер просто завершает работу. Это уже лучше.
    Но хотелось бы всё-таки, чтобы звуковой драйвер запускался и работал независимо от проблем с IRQ...
  • Последнее достижение технической мысли
    http://infinity-sound.narod.ru/remap.7z
    Драйвер назначает контроллеру IRQ5. Подходит для любого
    интеловского чипсета в том числе ICH6. PCI CFG не обновляется, так что PCIDEV покажет
    линию назначенную БИОС.
  • На ICH0 запускаю твой плеер без командных аргументов. После строчки global status 00000100 происходит полное зависание системы (не текущего потока, а всей системы). Как я понимаю, в данном случае, т.к. файл не указан, плеер просто загружает драйвер и всё.

    На ICH6 теперь драйвер нормально загружается, создаёт буфер, появляется сообщение "start play". Далее поток виснет (не система целиком, а только поток).

    В обоих случаях я поотключал всё лишнее оборудование, чтобы 5ое прерывание было свободно.

    Кстати, у меня теперь тоже 2 сетевухи на том компе, где ICH6. Раньше, когда твой драйвер исправно работал, была только встроенная сетевуха. Но отключение обеих сетевух проблему не решило. Просто я думаю, что раньше (старая версия прошивки биоса) назначала кодеку другое прерывание... Мне кажется, что баг всё равно в том коде, который назначает/переназначает IRQ.
    Last edited by Quantum on Thu Jul 05, 2007 3:47 am, edited 1 time in total.
  • Who is online

    Users browsing this forum: No registered users and 22 guests