В принципе - просто спецификацию PCI можно почитать,

В принципе - просто спецификацию PCI можно почитать, IMHO. Нативный - это PCI. Где контроллер DMA - не в чипсете, а на плате.
А в чипсете - арбитр шины.
Википедия:


"В шинах MicroChannel, SBus, разработанной под их большим влиянием PCI и её концептуальных производных AGP и PCI-X, используется иная реализация DMA. Эти шины позволяют любому устройству заявить о возникновении потребности к захвату шины, таковая потребность удовлетворяется т. н. арбитром при первой возможности. Устройство, успешно осуществившее захват шины, самостоятельно выставляет на шину сигналы адреса и управления и исполняет в течение какого-то времени ту же ведущую роль на шине, что и ЦП. Доступ ЦП к шине при этом кратковременно блокируется"

Т.е. для DMA-трансфера я программирую не "имитацию 8237", а регистры своей платы, имеющей контроллер DMA. Грубо говоря - инициализирую регистр базового физического(!) адреса в ОЗУ компа (откуда или куда), регистр размера трансфера и ставлю в контрол-регистре битики направления и "ДАВАЙ DMA!".
Далее либо ловлю прерывание от платы по окончании трансфера (и анализирую бит готовности/окончания трансфера и бит ошибки типа ABORT), либо могу поразвлекаться поллингом бита готовности/окончания трансфера в контрол-регистре.

А заморочки с VT-d - это уже следующий шаг, для "продвинутых".;)

Вот, кстати.
habrahabr.ru/post/37455/
Т.е. я работаю по Contiguous DMA (у меня всего 8 Кб максимальный трансфер и входящего/исходящего потока нет как такового),
а тот же USB-контроллер, как я понимаю - по Scatter/gather.