Група мініпорт

Функції цієї групи займаються обробкою потоку даних і подій, що відбуваються в верхньому рівні драйвера, і викликаються зверненням до NDIS TCP / IP стека.

Якщо подивитися на схеми з другої частини, то видно, що в нижній частині знаходяться функції протоколу, а у верхній мініпорт. Чому? Кожен драйвер виступає в двох іпостасях. Спілкуючись з верхнім рівнем драйверів він ставати для нього драйвером мініпорт, а для нижнього рівня, драйвером протоколу.

Список функцій мініпорт:

MPInitialize - ініціалізація групи.

Функції відповідають за пересилку пакетів даних.

Функції роботи з харчуванням станом системи і системою PlagNPlay. Сказати особливо нема чого. Стандартне відстеження внутрішніх подій системи прописане Microsoft.

MPHalt - відпрацювання вивантаження і де реєстрації драйвера при аварійному.

MPReset - як написано у Microsoft - ми не повинні нічого робити :)

Робота з системою - необхідність відпрацьовувати події важливі для сервісу коректно.

В системі може бути не один адаптер і відповідно не один драйвер до якого доводиться звертатися. У разі такого використовуються ці функції.

У нашому випадку основними функціями з цієї групи - є функції пересилання даних. Всі інші ми можемо не розглядати, їх призначення - обслуговувати правильно системні зв'язки, вся основна частина яких написана Microsoft.

Основна функція викликається завжди, при проходженні даних. За правилами роботи з даними в NDIS необхідно написати (що в прикладі і зроблено) re-wrap пакету.

Для цього спочатку пакет треба захопити, перекопіювати вміст пакета в свою пам'ять і переслати його далі, після чого звільнити пакет. Ось як буде це виглядати в коді:

PADAPT pAdapt = (PADAPT) MiniportAdapterContext;

Контекст адаптера приходить в якості параметра. Дамо його своєму типізовану вказівником.

Наш пакет - поки тільки покажчик.

PVOID MediaSpecificInfo = NULL;

Тип адаптера з яким будемо працювати.

ULONG MediaSpecificInfoSize = 0;

Розмір типу адаптера.

Перевірка наявності другого мережевого адаптера. Вгорі я говорив, що його наявність необхідно передбачати.

if (IsIMDeviceStateOn (pAdapt) == FALSE)

Перевірка наявності та стану.

NdisAllocatePacket (Status, MyPacket, pAdapt-> SendPacketPoolHandle);

Виділення місця під розмір отриманого пакета (Pool) даних.

if (Status == NDIS_STATUS_SUCCESS)

PNDIS_PACKET_EXTENSION Old, New;

Установка її в наш внутрішній буфер.

NdisMoveMemory (NDIS_OOB_DATA_FROM_PACKET (MyPacket), NDIS_OOB_DATA_FROM_PACKET (Packet), sizeof (NDIS_PACKET_OOB_DATA));

Перенесення даних в сам пакет.

NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO (Packet, MediaSpecificInfo, MediaSpecificInfoSize);

if (MediaSpecificInfo || MediaSpecificInfoSize)

NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO (MyPacket, MediaSpecificInfo, MediaSpecificInfoSize);

Власне пересилання наявних даних в NDIS, що викличе нормальне проходження пакета далі по ланцюжку драйверів.

NdisSend (Status, pAdapt-> BindingHandle, MyPacket);

if (Status! = NDIS_STATUS_PENDING)

Якщо немає затримки на відсилання звільнити пакет.

Це говорить про відсутність пакету в системі - нічого не треба робити.

Повернення значення SUCCESS або код помилки.

Варто зупинитися ще на одному моменті. Коли система відповіла, що посилка даних закінчена кодом затримки пакета - NDIS_STATUS_PENDING.

В цьому випадку ми пакет не звільнимо, блокувавши таким чином всю систему NDIS з пересилання даних. Таке трапляється при посилці по повільній мережі великого числа пакетів.

Як нам звільнити пакет? Система передбачає таке і при звільненні ресурсу після звільнення пакета викличе функцію з групи протоколу PtSendComplete. Зміна на протокольну групу викликана тим, що система отримає повідомлення від низлежащего драйвера, що викликає звернення саме до цієї групи.

У даній функції, код якої йде слідом ми побачимо параметри в яких нам передадуть контекст операції Send і адаптера, в результаті чого ми отримаємо можливість викликати функцію NdisMSendComplete після NdisDprFreePacket і звільнити NDIS для передачі нам наступних пакетів.

PADAPT pAdapt = (PADAPT) ProtocolBindingContext;

Схожі статті