SubFn62-DA/ru

From KolibriOS wiki
Jump to navigation Jump to search

Bus Master DMA service

Один из важных элементов Embedded-версий системы - возможность высокоскоростной бездрайверной передачи больших блоков данных между пользовательским приложением и устройством в режиме захвата системной шины (Bus Master DMA). В этом режиме PCI-устройство получает временный контроль над шиной и, как следствие,- доступ (практически) ко всем ресурсам компьютера.

"Башковитые" устройства могут использовать захват шины для:

  • максимально быстрой пересылки больших блоков данных в определенное место памяти (собственно DMA = direct memory access);
  • непосредственного опроса/установки системных семафоров и обмена сообщениями с другими устройствами;
  • диагностики дохлых системных плат;
  • загрузки/выгрузки/отладки операционной системы;
  • акселерации/распараллеливания математических вычислений (GPU, фурье-процессоры);
  • выполнения сисфункций без переключения задач;

и ещё много для чего...

Здесь мы ограничимся только первой из перечисленных задач.

Для PCI-устройств нет единого, четко определенного стандарта DMA-операций,- на аппаратном уровне каждое устройство имеет свою регистровую модель и свой контроль процесса (см. техническую документацию к конкретному железу). Однако в любом устройстве должен быть (по крайней мере один) регистр адреса буфера DMA-чтения и/или записи - иначе железо не будет знать откуда/куда нужно пересылать данные. В "нормальных" системах этот адрес устройству предоставляет драйвер, предварительно запросив у системы подходящий буфер.

В Колибри-А пользовательское приложение может организовать полноценный DMA-обмен с одним устройством напрямую, без драйвера. Для этого в системе зарезервирована программно-доступная статическая область памяти размером 8Мбайт. Физический адрес (необходимый для программирования адресного регистра DMA) возвращает функция 62-11; линейный адрес в пользовательском пространстве формируется специальной подподфункцией 62.12-0xDA.


Параметры:

  • eax = 62 - номер функции
  • bx = 0xDA0C - номер под+подфункции
  • ecx = размер запрашиваемого DMA-блока (в байтах)
  • edx = смещение (в 4K-страницах!) относительно начала системной области STATIC_DMA_BUFFER

Возвращаемое значение:

  • eax = -1 - доступ к PCI запрещён;
  • eax = -2 - пользовательский ПДП не поддерживается в этой версии ядра;
  • eax = -3 - недопустимое смещение (попытка доступа к "закрытой" странице ядерной памяти);
  • eax = -4 - недопустимый размер блока (пересекает верхнюю границу области STATIC_DMA_BUFFER);
  • eax = -5 - ошибка аллокации; иначе
  • eax = начальный адрес DMA-блока в адресном пространстве приложения.

Замечания:

  • Пользовательский ПДП-сервис не включен в стандартное ядро KolibriOS.
  • Предоставленный диапазон линейных адресов должен освобождаться посредством вызова подфункции 13

Пример кода:

   mcall 62,11,0x0500          ; init user-accessible MMIO/DMA: bus=5, device=0, fn=0
   mov [dma],eax               ; store phys.addr of the DMA buffer: 
   mcall 62,0+12,4096,0        ; map MMIO access to BAR0-space
   mov [mio],eax               ; store MMIO linear address
   mcall 62,0xDA0C,4096,0      ; 0x0da0c = create user DMA channel
   mov [mem],eax               ; store DMA buffer: linear @
   mov eax, [dma]
   or  eax, DMA_FLAGS
   mov dword[mio+4], eax       ; program device-specific DMA-address register
;  ....
   mov ecx, [mem]
   mov eax, [index]
   mov edx, dword[ecx+eax*4]   ; load the fresh data from DMA-buffer to edx