]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioNetDxe/SnpReceive.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioNetDxe / SnpReceive.c
CommitLineData
e12fadc3
LE
1/** @file\r
2\r
3 Implementation of the SNP.Receive() function and its private helpers if any.\r
4\r
5 Copyright (C) 2013, Red Hat, Inc.\r
8258c4e6 6 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
e12fadc3 7\r
b26f0cf9 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e12fadc3
LE
9\r
10**/\r
11\r
12#include <Library/BaseLib.h>\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/UefiBootServicesTableLib.h>\r
15\r
16#include "VirtioNet.h"\r
17\r
18/**\r
19 Receives a packet from a network interface.\r
20\r
21 @param This The protocol instance pointer.\r
22 @param HeaderSize The size, in bytes, of the media header received on the\r
23 network interface. If this parameter is NULL, then the\r
24 media header size will not be returned.\r
25 @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the\r
26 size, in bytes, of the packet that was received on the\r
27 network interface.\r
28 @param Buffer A pointer to the data buffer to receive both the media\r
29 header and the data.\r
30 @param SrcAddr The source HW MAC address. If this parameter is NULL, the\r
31 HW MAC source address will not be extracted from the media\r
32 header.\r
33 @param DestAddr The destination HW MAC address. If this parameter is NULL,\r
34 the HW MAC destination address will not be extracted from\r
35 the media header.\r
36 @param Protocol The media header type. If this parameter is NULL, then the\r
37 protocol will not be extracted from the media header. See\r
38 RFC 1700 section "Ether Types" for examples.\r
39\r
40 @retval EFI_SUCCESS The received data was stored in Buffer, and\r
41 BufferSize has been updated to the number of\r
42 bytes received.\r
43 @retval EFI_NOT_STARTED The network interface has not been started.\r
44 @retval EFI_NOT_READY The network interface is too busy to accept\r
45 this transmit request.\r
46 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
47 @retval EFI_INVALID_PARAMETER One or more of the parameters has an\r
48 unsupported value.\r
49 @retval EFI_DEVICE_ERROR The command could not be sent to the network\r
50 interface.\r
51 @retval EFI_UNSUPPORTED This function is not supported by the network\r
52 interface.\r
53\r
54**/\r
e12fadc3
LE
55EFI_STATUS\r
56EFIAPI\r
57VirtioNetReceive (\r
ac0a286f
MK
58 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
59 OUT UINTN *HeaderSize OPTIONAL,\r
60 IN OUT UINTN *BufferSize,\r
61 OUT VOID *Buffer,\r
62 OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
63 OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
64 OUT UINT16 *Protocol OPTIONAL\r
e12fadc3
LE
65 )\r
66{\r
ac0a286f
MK
67 VNET_DEV *Dev;\r
68 EFI_TPL OldTpl;\r
69 EFI_STATUS Status;\r
70 UINT16 RxCurUsed;\r
71 UINT16 UsedElemIdx;\r
72 UINT32 DescIdx;\r
73 UINT32 RxLen;\r
74 UINTN OrigBufferSize;\r
75 UINT8 *RxPtr;\r
76 UINT16 AvailIdx;\r
77 EFI_STATUS NotifyStatus;\r
78 UINTN RxBufOffset;\r
79\r
80 if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {\r
e12fadc3
LE
81 return EFI_INVALID_PARAMETER;\r
82 }\r
83\r
ac0a286f 84 Dev = VIRTIO_NET_FROM_SNP (This);\r
e12fadc3
LE
85 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
86 switch (Dev->Snm.State) {\r
ac0a286f
MK
87 case EfiSimpleNetworkStopped:\r
88 Status = EFI_NOT_STARTED;\r
89 goto Exit;\r
90 case EfiSimpleNetworkStarted:\r
91 Status = EFI_DEVICE_ERROR;\r
92 goto Exit;\r
93 default:\r
94 break;\r
e12fadc3
LE
95 }\r
96\r
97 //\r
98 // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
99 //\r
100 MemoryFence ();\r
101 RxCurUsed = *Dev->RxRing.Used.Idx;\r
dc9447bd 102 MemoryFence ();\r
e12fadc3
LE
103\r
104 if (Dev->RxLastUsed == RxCurUsed) {\r
105 Status = EFI_NOT_READY;\r
106 goto Exit;\r
107 }\r
108\r
109 UsedElemIdx = Dev->RxLastUsed % Dev->RxRing.QueueSize;\r
ac0a286f
MK
110 DescIdx = Dev->RxRing.Used.UsedElem[UsedElemIdx].Id;\r
111 RxLen = Dev->RxRing.Used.UsedElem[UsedElemIdx].Len;\r
e12fadc3
LE
112\r
113 //\r
114 // the virtio-net request header must be complete; we skip it\r
115 //\r
116 ASSERT (RxLen >= Dev->RxRing.Desc[DescIdx].Len);\r
117 RxLen -= Dev->RxRing.Desc[DescIdx].Len;\r
118 //\r
119 // the host must not have filled in more data than requested\r
120 //\r
121 ASSERT (RxLen <= Dev->RxRing.Desc[DescIdx + 1].Len);\r
122\r
123 OrigBufferSize = *BufferSize;\r
ac0a286f 124 *BufferSize = RxLen;\r
e12fadc3
LE
125\r
126 if (OrigBufferSize < RxLen) {\r
127 Status = EFI_BUFFER_TOO_SMALL;\r
128 goto Exit; // keep the packet\r
129 }\r
130\r
131 if (RxLen < Dev->Snm.MediaHeaderSize) {\r
132 Status = EFI_DEVICE_ERROR;\r
133 goto RecycleDesc; // drop useless short packet\r
134 }\r
135\r
136 if (HeaderSize != NULL) {\r
137 *HeaderSize = Dev->Snm.MediaHeaderSize;\r
138 }\r
139\r
46b11f00
BS
140 RxBufOffset = (UINTN)(Dev->RxRing.Desc[DescIdx + 1].Addr -\r
141 Dev->RxBufDeviceBase);\r
142 RxPtr = Dev->RxBuf + RxBufOffset;\r
e12fadc3
LE
143 CopyMem (Buffer, RxPtr, RxLen);\r
144\r
145 if (DestAddr != NULL) {\r
56f65ed8 146 CopyMem (DestAddr, RxPtr, SIZE_OF_VNET (Mac));\r
e12fadc3 147 }\r
ac0a286f 148\r
56f65ed8 149 RxPtr += SIZE_OF_VNET (Mac);\r
e12fadc3
LE
150\r
151 if (SrcAddr != NULL) {\r
56f65ed8 152 CopyMem (SrcAddr, RxPtr, SIZE_OF_VNET (Mac));\r
e12fadc3 153 }\r
ac0a286f 154\r
56f65ed8 155 RxPtr += SIZE_OF_VNET (Mac);\r
e12fadc3
LE
156\r
157 if (Protocol != NULL) {\r
ac0a286f 158 *Protocol = (UINT16)((RxPtr[0] << 8) | RxPtr[1]);\r
e12fadc3 159 }\r
ac0a286f 160\r
e12fadc3
LE
161 RxPtr += sizeof (UINT16);\r
162\r
163 Status = EFI_SUCCESS;\r
164\r
165RecycleDesc:\r
166 ++Dev->RxLastUsed;\r
167\r
168 //\r
169 // virtio-0.9.5, 2.4.1 Supplying Buffers to The Device\r
170 //\r
ac0a286f 171 AvailIdx = *Dev->RxRing.Avail.Idx;\r
9f3acbb5 172 Dev->RxRing.Avail.Ring[AvailIdx++ % Dev->RxRing.QueueSize] =\r
ac0a286f 173 (UINT16)DescIdx;\r
e12fadc3
LE
174\r
175 MemoryFence ();\r
176 *Dev->RxRing.Avail.Idx = AvailIdx;\r
177\r
178 MemoryFence ();\r
56f65ed8 179 NotifyStatus = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);\r
ac0a286f
MK
180 if (!EFI_ERROR (Status)) {\r
181 // earlier error takes precedence\r
e12fadc3
LE
182 Status = NotifyStatus;\r
183 }\r
184\r
185Exit:\r
186 gBS->RestoreTPL (OldTpl);\r
187 return Status;\r
188}\r