]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioNetDxe/SnpTransmit.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioNetDxe / SnpTransmit.c
CommitLineData
b6dfc654
LE
1/** @file\r
2\r
3 Implementation of the SNP.Transmit() 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
b6dfc654 7\r
b26f0cf9 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
b6dfc654
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 Places a packet in the transmit queue of 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 to be filled in by\r
23 the Transmit() function. If HeaderSize is non-zero, then\r
24 it must be equal to This->Mode->MediaHeaderSize and the\r
25 DestAddr and Protocol parameters must not be NULL.\r
26 @param BufferSize The size, in bytes, of the entire packet (media header and\r
27 data) to be transmitted through the network interface.\r
28 @param Buffer A pointer to the packet (media header followed by data) to\r
29 be transmitted. This parameter cannot be NULL. If\r
30 HeaderSize is zero, then the media header in Buffer must\r
31 already be filled in by the caller. If HeaderSize is\r
32 non-zero, then the media header will be filled in by the\r
33 Transmit() function.\r
34 @param SrcAddr The source HW MAC address. If HeaderSize is zero, then\r
35 this parameter is ignored. If HeaderSize is non-zero and\r
36 SrcAddr is NULL, then This->Mode->CurrentAddress is used\r
37 for the source HW MAC address.\r
38 @param DestAddr The destination HW MAC address. If HeaderSize is zero,\r
39 then this parameter is ignored.\r
40 @param Protocol The type of header to build. If HeaderSize is zero, then\r
41 this parameter is ignored. See RFC 1700, section "Ether\r
42 Types", for examples.\r
43\r
44 @retval EFI_SUCCESS The packet was placed on the transmit queue.\r
45 @retval EFI_NOT_STARTED The network interface has not been started.\r
46 @retval EFI_NOT_READY The network interface is too busy to accept\r
47 this transmit request.\r
48 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
49 @retval EFI_INVALID_PARAMETER One or more of the parameters has an\r
50 unsupported value.\r
51 @retval EFI_DEVICE_ERROR The command could not be sent to the network\r
52 interface.\r
53 @retval EFI_UNSUPPORTED This function is not supported by the network\r
54 interface.\r
55\r
56**/\r
b6dfc654
LE
57EFI_STATUS\r
58EFIAPI\r
59VirtioNetTransmit (\r
ac0a286f
MK
60 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
61 IN UINTN HeaderSize,\r
62 IN UINTN BufferSize,\r
63 IN /* +OUT! */ VOID *Buffer,\r
64 IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
65 IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
66 IN UINT16 *Protocol OPTIONAL\r
b6dfc654
LE
67 )\r
68{\r
8fa54a8a
BS
69 VNET_DEV *Dev;\r
70 EFI_TPL OldTpl;\r
71 EFI_STATUS Status;\r
72 UINT16 DescIdx;\r
73 UINT16 AvailIdx;\r
74 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
b6dfc654 75\r
ac0a286f 76 if ((This == NULL) || (BufferSize == 0) || (Buffer == NULL)) {\r
b6dfc654
LE
77 return EFI_INVALID_PARAMETER;\r
78 }\r
79\r
ac0a286f 80 Dev = VIRTIO_NET_FROM_SNP (This);\r
b6dfc654
LE
81 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
82 switch (Dev->Snm.State) {\r
ac0a286f
MK
83 case EfiSimpleNetworkStopped:\r
84 Status = EFI_NOT_STARTED;\r
85 goto Exit;\r
86 case EfiSimpleNetworkStarted:\r
87 Status = EFI_DEVICE_ERROR;\r
88 goto Exit;\r
89 default:\r
90 break;\r
b6dfc654
LE
91 }\r
92\r
93 if (BufferSize < Dev->Snm.MediaHeaderSize) {\r
94 Status = EFI_BUFFER_TOO_SMALL;\r
95 goto Exit;\r
96 }\r
ac0a286f 97\r
b6dfc654
LE
98 if (BufferSize > Dev->Snm.MediaHeaderSize + Dev->Snm.MaxPacketSize) {\r
99 Status = EFI_INVALID_PARAMETER;\r
100 goto Exit;\r
101 }\r
102\r
103 //\r
104 // check if we have room for transmission\r
105 //\r
106 ASSERT (Dev->TxCurPending <= Dev->TxMaxPending);\r
107 if (Dev->TxCurPending == Dev->TxMaxPending) {\r
108 Status = EFI_NOT_READY;\r
109 goto Exit;\r
110 }\r
111\r
112 //\r
113 // the caller may want us to fill in the media header:\r
114 // dst MAC, src MAC, Ethertype\r
115 //\r
116 if (HeaderSize != 0) {\r
ac0a286f 117 UINT8 *Ptr;\r
b6dfc654 118\r
ac0a286f
MK
119 if ((HeaderSize != Dev->Snm.MediaHeaderSize) ||\r
120 (DestAddr == NULL) || (Protocol == NULL))\r
121 {\r
b6dfc654
LE
122 Status = EFI_INVALID_PARAMETER;\r
123 goto Exit;\r
124 }\r
ac0a286f 125\r
b6dfc654 126 Ptr = Buffer;\r
56f65ed8 127 ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS));\r
b6dfc654 128\r
56f65ed8
OM
129 CopyMem (Ptr, DestAddr, SIZE_OF_VNET (Mac));\r
130 Ptr += SIZE_OF_VNET (Mac);\r
b6dfc654 131\r
ac0a286f
MK
132 CopyMem (\r
133 Ptr,\r
b6dfc654 134 (SrcAddr == NULL) ? &Dev->Snm.CurrentAddress : SrcAddr,\r
ac0a286f
MK
135 SIZE_OF_VNET (Mac)\r
136 );\r
56f65ed8 137 Ptr += SIZE_OF_VNET (Mac);\r
b6dfc654 138\r
ac0a286f
MK
139 *Ptr++ = (UINT8)(*Protocol >> 8);\r
140 *Ptr++ = (UINT8)*Protocol;\r
b6dfc654 141\r
ac0a286f 142 ASSERT ((UINTN)(Ptr - (UINT8 *)Buffer) == Dev->Snm.MediaHeaderSize);\r
b6dfc654
LE
143 }\r
144\r
8fa54a8a
BS
145 //\r
146 // Map the transmit buffer system physical address to device address.\r
147 //\r
148 Status = VirtioNetMapTxBuf (\r
149 Dev,\r
150 Buffer,\r
151 BufferSize,\r
152 &DeviceAddress\r
153 );\r
154 if (EFI_ERROR (Status)) {\r
155 Status = EFI_DEVICE_ERROR;\r
156 goto Exit;\r
157 }\r
158\r
b6dfc654
LE
159 //\r
160 // virtio-0.9.5, 2.4.1 Supplying Buffers to The Device\r
161 //\r
ac0a286f
MK
162 DescIdx = Dev->TxFreeStack[Dev->TxCurPending++];\r
163 Dev->TxRing.Desc[DescIdx + 1].Addr = DeviceAddress;\r
164 Dev->TxRing.Desc[DescIdx + 1].Len = (UINT32)BufferSize;\r
b6dfc654
LE
165\r
166 //\r
167 // the available index is never written by the host, we can read it back\r
168 // without a barrier\r
169 //\r
ac0a286f 170 AvailIdx = *Dev->TxRing.Avail.Idx;\r
b6dfc654
LE
171 Dev->TxRing.Avail.Ring[AvailIdx++ % Dev->TxRing.QueueSize] = DescIdx;\r
172\r
173 MemoryFence ();\r
174 *Dev->TxRing.Avail.Idx = AvailIdx;\r
175\r
176 MemoryFence ();\r
56f65ed8 177 Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_TX);\r
b6dfc654
LE
178\r
179Exit:\r
180 gBS->RestoreTPL (OldTpl);\r
181 return Status;\r
182}\r