SubFn62-DA/ru

From KolibriOS wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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