//\r
// step 4c -- report GPFN (guest-physical frame number) of queue\r
//\r
- Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
- (UINT32) ((UINTN) Ring->Base >> EFI_PAGE_SHIFT));\r
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
IN OUT VNET_DEV *Dev\r
)\r
{\r
+ UINTN TxSharedReqSize;\r
UINTN PktIdx;\r
\r
Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
+ //\r
+ // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
+ // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.\r
+ //\r
+ TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?\r
+ sizeof Dev->TxSharedReq.V0_9_5 :\r
+ sizeof Dev->TxSharedReq;\r
+\r
for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {\r
UINT16 DescIdx;\r
\r
// (unmodified by the host) virtio-net request header.\r
//\r
Dev->TxRing.Desc[DescIdx].Addr = (UINTN) &Dev->TxSharedReq;\r
- Dev->TxRing.Desc[DescIdx].Len = sizeof Dev->TxSharedReq;\r
+ Dev->TxRing.Desc[DescIdx].Len = (UINT32) TxSharedReqSize;\r
Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;\r
Dev->TxRing.Desc[DescIdx].Next = (UINT16) (DescIdx + 1);\r
\r
//\r
// virtio-0.9.5, Appendix C, Packet Transmission\r
//\r
- Dev->TxSharedReq.Flags = 0;\r
- Dev->TxSharedReq.GsoType = VIRTIO_NET_HDR_GSO_NONE;\r
+ Dev->TxSharedReq.V0_9_5.Flags = 0;\r
+ Dev->TxSharedReq.V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;\r
+\r
+ //\r
+ // For VirtIo 1.0 only -- the field exists, but it is unused\r
+ //\r
+ Dev->TxSharedReq.NumBuffers = 0;\r
\r
//\r
// virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
)\r
{\r
EFI_STATUS Status;\r
+ UINTN VirtioNetReqSize;\r
UINTN RxBufSize;\r
UINT16 RxAlwaysPending;\r
UINTN PktIdx;\r
UINT16 DescIdx;\r
UINT8 *RxPtr;\r
\r
+ //\r
+ // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
+ // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.\r
+ //\r
+ VirtioNetReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?\r
+ sizeof (VIRTIO_NET_REQ) :\r
+ sizeof (VIRTIO_1_0_NET_REQ);\r
+\r
//\r
// For each incoming packet we must supply two descriptors:\r
// - the recipient for the virtio-net request header, plus\r
// - the recipient for the network data (which consists of Ethernet header\r
// and Ethernet payload).\r
//\r
- RxBufSize = sizeof (VIRTIO_NET_REQ) +\r
+ RxBufSize = VirtioNetReqSize +\r
(Dev->Snm.MediaHeaderSize + Dev->Snm.MaxPacketSize);\r
\r
//\r
// virtio-0.9.5, 2.4.1.1 Placing Buffers into the Descriptor Table\r
//\r
Dev->RxRing.Desc[DescIdx].Addr = (UINTN) RxPtr;\r
- Dev->RxRing.Desc[DescIdx].Len = sizeof (VIRTIO_NET_REQ);\r
+ Dev->RxRing.Desc[DescIdx].Len = (UINT32) VirtioNetReqSize;\r
Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;\r
Dev->RxRing.Desc[DescIdx].Next = (UINT16) (DescIdx + 1);\r
RxPtr += Dev->RxRing.Desc[DescIdx++].Len;\r
\r
Dev->RxRing.Desc[DescIdx].Addr = (UINTN) RxPtr;\r
- Dev->RxRing.Desc[DescIdx].Len = (UINT32) (RxBufSize -\r
- sizeof (VIRTIO_NET_REQ));\r
+ Dev->RxRing.Desc[DescIdx].Len = (UINT32) (RxBufSize - VirtioNetReqSize);\r
Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;\r
RxPtr += Dev->RxRing.Desc[DescIdx++].Len;\r
}\r
EFI_TPL OldTpl;\r
EFI_STATUS Status;\r
UINT8 NextDevStat;\r
- UINT32 Features;\r
+ UINT64 Features;\r
\r
if (This == NULL) {\r
return EFI_INVALID_PARAMETER;\r
ASSERT (Dev->Snm.MediaPresentSupported ==\r
!!(Features & VIRTIO_NET_F_STATUS));\r
\r
+ Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_F_VERSION_1;\r
+\r
+ //\r
+ // In virtio-1.0, feature negotiation is expected to complete before queue\r
+ // discovery, and the device can also reject the selected set of features.\r
+ //\r
+ if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+ Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto DeviceFailed;\r
+ }\r
+ }\r
+\r
//\r
// step 4b, 4c -- allocate and report virtqueues\r
//\r
//\r
// step 5 -- keep only the features we want\r
//\r
- Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS;\r
- Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
- if (EFI_ERROR (Status)) {\r
- goto ReleaseTxRing;\r
+ if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+ Features &= ~(UINT64)VIRTIO_F_VERSION_1;\r
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseTxRing;\r
+ }\r
}\r
\r
//\r