SubFn62-DA/ru
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 [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