"Гром. Как писать драйвера (fb2) " - читать интересную книгу автора

Группа протокол.

Протокольные функции несколько отличаются от функций минипорта, но имеют схожую функциональную нагрузку, обратную функциям минипорта по направлению передачи пакетов.

PtOpenAdapterComplete

PtCloseAdapterComplete

PtBindAdapter

PtUnbindAdapter

Функции работы с адаптером – в нашем случае адаптером является драйвер модема или сетевой карты. Адаптер соответственно при запуске надо открыть и при окончании работы – закрыть. При обращении к нему привязать (bind) адаптер, захватить ресурс. В конце работы – освободить.

PtResetComplete

Абсолютно пустая функция – она должна быть но мы сюда не приходим.

PtRequestComplete

Функция вызываемая из PtPnPNetEventSetPower.

PtStatus

Функция отвечающая за проверку статуса нижестоящего адаптера, вернее статуса взаимодействия с ним нашего уровня.

PtStatusComplete

Завершение в случае невозможности быстрого ответа, примерно как и в случае MPSend.

PtSendComplete

Описана в секции минипорт

PtTransferDataComplete

PtReceive

PtReceiveComplete

PtReceivePacket

Функции работы с данными – аналогичны функциям минипорта. Одну из функций мы уже разбирали. Функции остальных – чуть позже.

PtUnload

Функция заведующая выгрузкой драйвера при выходе.

PtPNPHandler

PtPnPNetEventReconfigure

PtPnPNetEventSetPower

Работа с PnP.

Вновь обратим внимание на симметричную функцию PtReceive.

PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

Контекст адаптера

PNDIS_PACKET MyPacket, Packet; Пакеты.

NDIS_STATUS Status = NDIS_STATUS_SUCCESS;

Статус

if (!pAdapt-gt;MiniportHandle) {

 Status = NDIS_STATUS_FAILURE;

} else do {

 Эта часть работает при наличии второго адаптера :)

 if (pAdapt-gt;isSecondary) {

  DBGPRINT("PASSTHRU GETTING RECIEVES ON SECONDARY\n");

  ASSERT(0);

 }

Забираем указатель на пакет в NDIS.

Packet = NdisGetReceivedPacket(pAdapt-gt;BindingHandle, MacReceiveContext);

Если пакета нет то мы выходим иначе продолжаем как и в случае с отправкой.

if (Packet != NULL) {

Резервируем пакет для себя.

NdisDprAllocatePacket(amp;Status, amp;MyPacket, pAdapt-gt;RecvPacketPoolHandle);

if (Status == NDIS_STATUS_SUCCESS) {

Копируем данные, как служебные, так и сами данные передаваемые наверх.

MyPacket-gt;Private.Head = Packet-gt;Private.Head;

MyPacket-gt;Private.Tail = Packet-gt;Private.Tail;

NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));

NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);

NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);

В этом случае мы не посылаем пакет как при отправке, а просто указываем NDIS что MyPacket готов к передаче наверх.

NdisMIndicateReceivePacket(pAdapt-gt;MiniportHandle, amp;MyPacket, 1);

ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);

Освобождение пакета при нормальной передаче.

  NdisDprFreePacket(MyPacket);

  break;

 }

}

Выбор типа адаптера внизу дает возможность применить для индикации готовности к передаче в случае ошибки стандартного сообщения NDIS. Это происходит в случае специфичных сетей и обрабатывается функциями связанными с этими типами.

pAdapt-gt;IndicateRcvComplete = TRUE;

switch (pAdapt-gt;Medium) {

case NdisMedium802_3:

 NdisMEthIndicateReceive(pAdapt-gt;MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize);

 break;

case NdisMedium802_5:

 NdisMTrIndicateReceive(pAdapt-gt;MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize);

 break;

case NdisMediumFddi:

 NdisMFddiIndicateReceive(pAdapt-gt;MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize);

 break;

default:

Это в случае если тип сети неизвестен.

 ASSERT(0);

  break;

 }

} while(FALSE);

return Status;

Выход с статусом завершения.

Некоторое пояснение.

Когда тип адаптера и сети специфичен и отличается от стандарта LAN, нам нужно сообщить о пакете и его отправке соответствующей части сервиса NDIS. Именно в связи с этим и появляется выбор типа адаптера. При получении возможно наличие одновременного запроса на прием пакета с разных адаптеров.

В случае с операцией Send этого не происходит, так как NDIS сама по контексту определяет к какому адаптеру предназначен пакет.

Оставшиеся функции аналогичны по назначению с группой функций минипорта.