[SnpInitialize.c] | | [SnpShutdown.c]\r
VirtioNetInitialize | | VirtioNetShutdown\r
VirtioNetInitRing {Rx, Tx} | | VirtioNetShutdownRx [SnpSharedHelpers.c]\r
- VirtioRingInit | | VirtioNetShutdownTx [SnpSharedHelpers.c]\r
- VirtioNetInitTx | | VirtioNetUninitRing [SnpSharedHelpers.c]\r
- VirtioNetInitRx | | {Tx, Rx}\r
+ VirtioRingInit | | VirtIo->UnmapSharedBuffer\r
+ VirtioRingMap | | VirtIo->FreeSharedPages\r
+ VirtioNetInitTx | | VirtioNetShutdownTx [SnpSharedHelpers.c]\r
+ VirtIo->AllocateShare... | | VirtIo->UnmapSharedBuffer\r
+ VirtioMapAllBytesInSh... | | VirtIo->FreeSharedPages\r
+ VirtioNetInitRx | | VirtioNetUninitRing [SnpSharedHelpers.c]\r
+ VirtIo->AllocateShare... | | {Tx, Rx}\r
+ VirtioMapAllBytesInSh... | | VirtIo->UnmapSharedBuffer\r
| | VirtioRingUninit\r
v |\r
+-----------------------------+\r
Area, which accommodates all packets delivered asynchronously by the host. To\r
each packet, a slice of this area is dedicated; each slice is further\r
subdivided into virtio-net request header and network packet data. The\r
-(guest-physical) addresses of these sub-slices are denoted with A2, A3, A4 and\r
+(device-physical) addresses of these sub-slices are denoted with A2, A3, A4 and\r
so on. Importantly, an even-subscript "A" always belongs to a virtio-net\r
request header, while an odd-subscript "A" always belongs to a packet\r
sub-slice.\r
that is shared by all of the head descriptors. This virtio-net request header\r
is never modified by the host.\r
\r
-- Each tail descriptor is re-pointed to the caller-supplied packet buffer\r
- whenever VirtioNetTransmit places the corresponding head descriptor on the\r
- Available Ring. The caller is responsible to hang on to the unmodified buffer\r
- until it is reported transmitted by VirtioNetGetStatus.\r
+- Each tail descriptor is re-pointed to the device-mapped address of the\r
+ caller-supplied packet buffer whenever VirtioNetTransmit places the\r
+ corresponding head descriptor on the Available Ring. A reverse mapping, from\r
+ the device-mapped address to the caller-supplied packet address, is saved in\r
+ an associative data structure that belongs to the driver instance.\r
+\r
+- Per spec, the caller is responsible to hang on to the unmodified packet\r
+ buffer until it is reported transmitted by VirtioNetGetStatus.\r
\r
Steps of packet transmission:\r
\r
- Client code calls VirtioNetGetStatus. In case the Used Ring is empty, the\r
function reports no Tx completion. Otherwise, a head descriptor's index is\r
consumed from the Used Ring and recycled to the private stack. The client\r
- code's original packet buffer address is fetched from the tail descriptor\r
- (where it has been stored at VirtioNetTransmit time) and returned to the\r
- caller.\r
+ code's original packet buffer address is calculated by fetching the\r
+ device-mapped address from the tail descriptor (where it has been stored at\r
+ VirtioNetTransmit time), and by looking up the device-mapped address in the\r
+ associative data structure. The reverse-mapped packet buffer address is\r
+ returned to the caller.\r
\r
- The Len field of the Used Ring Element is not checked. The host is assumed to\r
have transmitted the entire packet -- VirtioNetTransmit had forced it below\r