60 Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, Selector);
61 if (EFI_ERROR (Status)) {
65 Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
66 if (EFI_ERROR (Status)) {
75 return EFI_UNSUPPORTED;
79 if (EFI_ERROR (Status)) {
86 Status =
VirtioRingMap (Dev->VirtIo, Ring, &RingBaseShift, &MapInfo);
87 if (EFI_ERROR (Status)) {
95 Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
96 if (EFI_ERROR (Status)) {
100 Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
101 if (EFI_ERROR (Status)) {
108 Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, RingBaseShift);
109 if (EFI_ERROR (Status)) {
118 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, MapInfo);
158 UINTN TxSharedReqSize;
162 VOID *TxSharedReqBuffer;
164 Dev->TxMaxPending = (UINT16)
MIN (
165 Dev->TxRing.QueueSize / 2,
168 Dev->TxCurPending = 0;
171 sizeof *Dev->TxFreeStack
173 if (Dev->TxFreeStack ==
NULL) {
174 return EFI_OUT_OF_RESOURCES;
181 if (Dev->TxBufCollection ==
NULL) {
182 Status = EFI_OUT_OF_RESOURCES;
183 goto FreeTxFreeStack;
190 Status = Dev->VirtIo->AllocateSharedPages (
195 if (EFI_ERROR (Status)) {
196 goto UninitTxBufCollection;
199 ZeroMem (TxSharedReqBuffer,
sizeof *Dev->TxSharedReq);
203 VirtioOperationBusMasterCommonBuffer,
205 sizeof *(Dev->TxSharedReq),
209 if (EFI_ERROR (Status)) {
210 goto FreeTxSharedReqBuffer;
213 Dev->TxSharedReq = TxSharedReqBuffer;
219 TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?
220 sizeof (Dev->TxSharedReq->V0_9_5) :
221 sizeof *Dev->TxSharedReq;
223 for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {
226 DescIdx = (UINT16)(2 * PktIdx);
227 Dev->TxFreeStack[PktIdx] = DescIdx;
233 Dev->TxRing.Desc[DescIdx].Addr = DeviceAddress;
234 Dev->TxRing.Desc[DescIdx].Len = (UINT32)TxSharedReqSize;
235 Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;
236 Dev->TxRing.Desc[DescIdx].Next = (UINT16)(DescIdx + 1);
242 Dev->TxRing.Desc[DescIdx + 1].Flags = 0;
248 Dev->TxSharedReq->V0_9_5.Flags = 0;
249 Dev->TxSharedReq->V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;
254 Dev->TxSharedReq->NumBuffers = 0;
260 Dev->TxLastUsed = *Dev->TxRing.Used.Idx;
261 ASSERT (Dev->TxLastUsed == 0);
266 *Dev->TxRing.Avail.Flags = (UINT16)VRING_AVAIL_F_NO_INTERRUPT;
270FreeTxSharedReqBuffer:
271 Dev->VirtIo->FreeSharedPages (
277UninitTxBufCollection:
316 UINTN VirtioNetReqSize;
318 UINT16 RxAlwaysPending;
329 VirtioNetReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?
339 RxBufSize = VirtioNetReqSize +
340 (Dev->Snm.MediaHeaderSize + Dev->Snm.MaxPacketSize);
346 RxAlwaysPending = (UINT16)
MIN (Dev->RxRing.QueueSize / 2, VNET_MAX_PENDING);
354 NumBytes = RxAlwaysPending * RxBufSize;
356 Status = Dev->VirtIo->AllocateSharedPages (
361 if (EFI_ERROR (Status)) {
369 VirtioOperationBusMasterCommonBuffer,
372 &Dev->RxBufDeviceBase,
375 if (EFI_ERROR (Status)) {
376 goto FreeSharedBuffer;
379 Dev->RxBuf = RxBuffer;
385 Dev->RxLastUsed = *Dev->RxRing.Used.Idx;
386 ASSERT (Dev->RxLastUsed == 0);
393 *Dev->RxRing.Avail.Flags = (UINT16)VRING_AVAIL_F_NO_INTERRUPT;
400 RxBufDeviceAddress = Dev->RxBufDeviceBase;
401 for (PktIdx = 0; PktIdx < RxAlwaysPending; ++PktIdx) {
406 Dev->RxRing.Avail.Ring[PktIdx] = DescIdx;
411 Dev->RxRing.Desc[DescIdx].Addr = RxBufDeviceAddress;
412 Dev->RxRing.Desc[DescIdx].Len = (UINT32)VirtioNetReqSize;
413 Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
414 Dev->RxRing.Desc[DescIdx].Next = (UINT16)(DescIdx + 1);
415 RxBufDeviceAddress += Dev->RxRing.Desc[DescIdx++].Len;
417 Dev->RxRing.Desc[DescIdx].Addr = RxBufDeviceAddress;
418 Dev->RxRing.Desc[DescIdx].Len = (UINT32)(RxBufSize - VirtioNetReqSize);
419 Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;
420 RxBufDeviceAddress += Dev->RxRing.Desc[DescIdx++].Len;
427 *Dev->RxRing.Avail.Idx = RxAlwaysPending;
438 Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);
439 if (EFI_ERROR (Status)) {
440 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
441 goto UnmapSharedBuffer;
447 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
450 Dev->VirtIo->FreeSharedPages (
491 IN UINTN ExtraRxBufferSize OPTIONAL,
492 IN UINTN ExtraTxBufferSize OPTIONAL
502 return EFI_INVALID_PARAMETER;
505 if ((ExtraRxBufferSize > 0) || (ExtraTxBufferSize > 0)) {
506 return EFI_UNSUPPORTED;
509 Dev = VIRTIO_NET_FROM_SNP (This);
510 OldTpl =
gBS->RaiseTPL (TPL_CALLBACK);
511 if (Dev->Snm.
State != EfiSimpleNetworkStarted) {
512 Status = EFI_NOT_STARTED;
525 NextDevStat = VSTAT_ACK;
526 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
527 if (EFI_ERROR (Status)) {
531 NextDevStat |= VSTAT_DRIVER;
532 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
533 if (EFI_ERROR (Status)) {
540 Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
541 if (EFI_ERROR (Status)) {
549 Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
550 if (EFI_ERROR (Status)) {
554 ASSERT (Features & VIRTIO_NET_F_MAC);
557 !!(Features & VIRTIO_NET_F_STATUS)
560 Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_F_VERSION_1 |
561 VIRTIO_F_IOMMU_PLATFORM;
567 if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {
569 if (EFI_ERROR (Status)) {
583 if (EFI_ERROR (Status)) {
593 if (EFI_ERROR (Status)) {
600 if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
601 Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);
602 Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
603 if (EFI_ERROR (Status)) {
611 NextDevStat |= VSTAT_DRIVER_OK;
612 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
613 if (EFI_ERROR (Status)) {
618 if (EFI_ERROR (Status)) {
626 if (EFI_ERROR (Status)) {
630 Dev->Snm.
State = EfiSimpleNetworkInitialized;
631 gBS->RestoreTPL (OldTpl);
635 VirtioNetShutdownTx (Dev);
638 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
650 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
653 gBS->RestoreTPL (OldTpl);
VOID EFIAPI MemoryFence(VOID)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID EFIAPI OrderedCollectionUninit(IN ORDERED_COLLECTION *Collection)
ORDERED_COLLECTION *EFIAPI OrderedCollectionInit(IN ORDERED_COLLECTION_USER_COMPARE UserStructCompare, IN ORDERED_COLLECTION_KEY_COMPARE KeyCompare)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_STATUS EFIAPI VirtioNetInitialize(IN EFI_SIMPLE_NETWORK_PROTOCOL *This, IN UINTN ExtraRxBufferSize OPTIONAL, IN UINTN ExtraTxBufferSize OPTIONAL)
STATIC EFI_STATUS EFIAPI VirtioNetInitTx(IN OUT VNET_DEV *Dev)
STATIC EFI_STATUS EFIAPI VirtioNetInitRing(IN OUT VNET_DEV *Dev, IN UINT16 Selector, OUT VRING *Ring, OUT VOID **Mapping)
STATIC EFI_STATUS EFIAPI VirtioNetInitRx(IN OUT VNET_DEV *Dev)
INTN EFIAPI VirtioNetTxBufMapInfoCompare(IN CONST VOID *UserStruct1, IN CONST VOID *UserStruct2)
INTN EFIAPI VirtioNetTxBufDeviceAddressCompare(IN CONST VOID *StandaloneKey, IN CONST VOID *UserStruct)
VOID EFIAPI VirtioNetUninitRing(IN OUT VNET_DEV *Dev, IN OUT VRING *Ring, IN VOID *RingMap)
UINT64 EFI_PHYSICAL_ADDRESS
#define EFI_SIZE_TO_PAGES(Size)
EFI_STATUS EFIAPI VirtioMapAllBytesInSharedBuffer(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN VIRTIO_MAP_OPERATION Operation, IN VOID *HostAddress, IN UINTN NumberOfBytes, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping)
EFI_STATUS EFIAPI VirtioRingMap(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN VRING *Ring, OUT UINT64 *RingBaseShift, OUT VOID **Mapping)
EFI_STATUS EFIAPI Virtio10WriteFeatures(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN UINT64 Features, IN OUT UINT8 *DeviceStatus)
EFI_STATUS EFIAPI VirtioRingInit(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN UINT16 QueueSize, OUT VRING *Ring)
VOID EFIAPI VirtioRingUninit(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN OUT VRING *Ring)
BOOLEAN MediaPresentSupported