Как стать автором
Обновить

Комментарии 29

Довольно интересная статья, я так понимаю это начало цикла статей про программирование драйверов под дарвин?
Статья просто супер.
Думаю, её можно рекомендовать всем, кто интересуется архитектурой компов.
НЛО прилетело и опубликовало эту надпись здесь
Блога по системному программированию нет, а данная статья задумывалась как вторая в серии статей про системное программирование в Mac OS X. В итоге материала получилось достаточно много, решил реализацию и примеру с IOKit выделить в отдельную статью.
Мне кажется что тут нет никакой привязки к конкретной OS, поэтому лучше завести тогда отдельный блог есть нет до сих пор его.
В этой статье — нет. Убедили, создал отдельный блог :)
Отлично!
НЛО прилетело и опубликовало эту надпись здесь
У вас очень странная логика, как буд-то эти самые программы не люди пишут, а создают роботы, аля «Гамбургеры продаются в магазине».
Не реагируйте на этого тролля, минусуйте и все тут, только нервы тратить
А откуда берутся программы нужные?
НЛО прилетело и опубликовало эту надпись здесь
А кто при бабках?
да что вы спорите с toshirskij? посмотрите как он себя ведет, на его аватар… я не могу описать своего презрения к этому человеку!
Do not feed trolls
Интересно, спасибо. Только я не нашел расшифровку PPU. И опечатка в части Contiguous DMA принцим->принцип.
Спасибо, все поправил.
Очень интересно. Только возник такой вопрос касательно алгоритма работы Scatter/gather DMA:

Сначала драйвер(кстати, чей дравер? ОС?) выделяет память под DMA буферы. Далее устройства имеют доступ к буферам через указатели в дескрипторах. Но кто следит за overhead'ами? Если буферов оказывается недостаточно, кем, как и когда данная ситуация распознаётся и как/на каком этапе решается?

И ещё вопрос касательно этого: «Драйвер ОС просматривает все дескрипторы DMA буферов, определяет какие из них были заполнены контроллером устройства, пересылает данные из буфера далее по стеку устройств и помечает буфер как готовый к DMA трансферу.»

Каков обычно размер этого односвязаного списка DMA-буферов? Это ведь нерационально каждый раз просматривать его. Причём я так понимаю под «пересылает данные из буфера» имеется ввиду копирование этих данных? Т.к. иначе блок не может быть помечен как «готовый к DMA трансферу» пока на эти данные кто-то ссылается.

Заранее спасибо, надеюсь понятно изложил.
Понятно :) По порядку:

> Сначала драйвер(кстати, чей дравер? ОС?) выделяет память под DMA буферы.
Драйвер устройства, я его тут называл драйвером ОС, чтобы никто не запутался.

> Но кто следит за overhead'ами? Если буферов оказывается недостаточно, кем, как и когда данная ситуация распознаётся и как/на каком этапе решается?
Зависит от ситуации. Если у нас к примеру есть драйвер сетевой карты (я именно с ними имел достаточно много дела), то мы можем говорить о двух случаях:
1. overrun при отсылке пакета.
2. overrun при приеме.

Если имеет место первый случай, то очевидно, что overrun обнаруживает драйвер устройства в одной из своих процедур (например в Mac OS X, всмысле IOKit, это метод IOEthernetController:: outputPacket). overrun происходит из-за того, что устройство по какой-либо причине не успевает отправлять пакеты. Решение в данном случае, вернуть в процедуре драйвера код ошибки по типу output queue stalled. ОС просто перешлет этот пакет посже. Ну и если такая ситуация будет повторятся подряд на протяжении какого-либо времени, например контроллер повис, то значит нужно в драйвере это отслеживать и вовремя ресетнуть контроллер.

Если второй, то overrun обнаруживает сетевой контроллер. Он посылает прерывание и в регистре статуса прерываний выставляет какой-нибудь флажок, типа input queue overrun. Это сигнал драйверу, что нужно что-то делать. Как вариант, дропнуть старые пакеты в очереди и выставить в дескрипторе флажок, что буфер свободен, или же провести ресет контроллера.

> Каков обычно размер этого односвязаного списка DMA-буферов?
Зависит от конкретной железки. 64, 256 может быть. Может быть и больше.

> Это ведь нерационально каждый раз просматривать его.
Просмотреть 256 дескрипторов и проверить наличие установленного флага, что буфер был получен и его необходимо переслать на уровень выше — не такая уж и тяжелая задача. Есть разные методики. Например сетевые контроллеры от Realtek раньше просто писали подряд в каждый буфер в этом кольцевом списке дескрипторов, и после заполнения одного буфера давали прерывание. Посему драйвер мог хранить индекс текущего буфера и легко инкрементировать его после каждого прерывания.

> Причём я так понимаю под «пересылает данные из буфера» имеется ввиду копирование этих данных?
Верно, в случае сетевых драйверов, создается сетевой пакет (в Mac OS X — это mbuf, в линуксе — skb) и данные из буфера копируются в этот пакет.
На линуксе количество дескрипторов можно посмотреть так:
root@eva00:~# ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Current hardware settings:
RX: 256
RX Mini: 0
RX Jumbo: 0
TX: 256

Прекрасная статья! Хотя не очень интересуюсь тем, что происходит на таком низком уровне, однако, даже в обзеобразовательных целях было очень интересно почитать! Спасибо!

И, поправьте, пожалуйста: «следует передать операционной системы».
Спасибо, поправил. Что-то я не внимателен в последнее время :)
Кстати говоря, DMA используется не только для обмена данными между устройством и ОЗУ, но также между устройствами в системе, возможен DMA трансфер между двумя участками ОЗУ (хотя данный маневр не применим к x86 архитектуре)

Применим. DMA просто генерирует RD/WR запросы на шине. И, например, если в качестве места назначения указана видеопамять, то успешно можно загадить экран какими-нибудь кракозяблами. Хотя, конечно, PCI-E — это не общая шина. Возможно, там такой трюк не проходит. Но на PCI системах случалось ошибаться.

Также регистры устройства могут отображатся в ОЗУ (Memory Mapped Registers), т.е. физическую память системы. Данный метод имеет ряд преимуществ, а именно:

* Скорость доступа к физической памяти выше, нежели к IO портам.
* IO порты могут отображать не более 65535 байт регистров, в то время как размер ОЗУ современных компьютеров в разы больше.
* Читать регистры устройства из ОЗУ проще, нежели с помощью IO портов :)


Лучше написать: на физическое адресное пространство. Потому что память никуда не девается, просто host-контроллер перенаправляет запросы на чтение/запись по определённым адресам на шину PCI. На скорость доступа, кстати, это никак не влияет.
> И, например, если в качестве места назначения указана видеопамять, то успешно можно загадить экран какими-нибудь кракозяблами.
Да, можно ошибится с адресами и запортить содержимое памяти по случайному адресу, но если честно я не знаю, как можно было бы копировать участок физической памяти с одного адреса, на другой. Я так понимаю для этого нужен какой-нибудь центральный DMA контроллер или аппаратный IO MMU, но x86 этого нет, вернее в PCI нету централизированного контроллера, вместо этого bus mastering и придумали ведь ;)

> Лучше написать: на физическое адресное пространство. Потому что память никуда не девается, просто host-контроллер перенаправляет запросы на чтение/запись по определённым адресам на шину PCI.
Согласен, изменил формулировку. Правда память от этого свободной не становится, и int 15h сообщает системе, что память занята. Кстати надо будет в этом месте дополнить статью о memory remap.

> На скорость доступа, кстати, это никак не влияет.
Это только так кажется. На самом деле на IO порты обязательно вешается в SMI хендлере IO Trap, для самых разных нужд, как-то эмулирование для приложений PS/2 мыши и клавиатуры, когда вместо них — USB. Перенаправлением запросов в этом случае занимается SMI хендлер. Так что тут тоже есть определенный оверхед, хоть и небольшой :)
На самом деле на IO порты обязательно вешается в SMI хендлере IO Trap, для самых разных нужд, как-то эмулирование для приложений PS/2 мыши и клавиатуры, когда вместо них — USB.

Ну. Я про железо говорил. А на что там SMI вешается — никому не известно. Его можно и на доступ в память повешать, если железо это поддерживает. Но для того, чтобы железо с in и out работало никакого SMI не нужно.
Ну и это. +1. Аффтар, пиши ещё :)
… возможен DMA трансфер между двумя участками ОЗУ (хотя данный маневр не применим к x86 архитектуре).

Ну давно уже применим, только не для всех SoC, конечно, а только в тех, где есть DMA контроллер с поддержкой такого режима.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.