TianoCore EDK2 master
Loading...
Searching...
No Matches
SnpGetStatus.c
Go to the documentation of this file.
1
13#include <Library/BaseLib.h>
15
16#include "VirtioNet.h"
17
50EFIAPI
53 OUT UINT32 *InterruptStatus OPTIONAL,
54 OUT VOID **TxBuf OPTIONAL
55 )
56{
57 VNET_DEV *Dev;
58 EFI_TPL OldTpl;
59 EFI_STATUS Status;
60 UINT16 RxCurUsed;
61 UINT16 TxCurUsed;
62 EFI_PHYSICAL_ADDRESS DeviceAddress;
63
64 if (This == NULL) {
65 return EFI_INVALID_PARAMETER;
66 }
67
68 Dev = VIRTIO_NET_FROM_SNP (This);
69 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
70 switch (Dev->Snm.State) {
71 case EfiSimpleNetworkStopped:
72 Status = EFI_NOT_STARTED;
73 goto Exit;
74 case EfiSimpleNetworkStarted:
75 Status = EFI_DEVICE_ERROR;
76 goto Exit;
77 default:
78 break;
79 }
80
81 //
82 // update link status
83 //
84 if (Dev->Snm.MediaPresentSupported) {
85 UINT16 LinkStatus;
86
87 Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);
88 if (EFI_ERROR (Status)) {
89 goto Exit;
90 }
91
92 Dev->Snm.MediaPresent =
93 (BOOLEAN)((LinkStatus & VIRTIO_NET_S_LINK_UP) != 0);
94 }
95
96 //
97 // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
98 //
99 MemoryFence ();
100 RxCurUsed = *Dev->RxRing.Used.Idx;
101 TxCurUsed = *Dev->TxRing.Used.Idx;
102 MemoryFence ();
103
104 if (InterruptStatus != NULL) {
105 //
106 // report the receive interrupt if there is data available for reception,
107 // report the transmit interrupt if we have transmitted at least one buffer
108 //
109 *InterruptStatus = 0;
110 if (Dev->RxLastUsed != RxCurUsed) {
111 *InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
112 }
113
114 if (Dev->TxLastUsed != TxCurUsed) {
115 ASSERT (Dev->TxCurPending > 0);
116 *InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
117 }
118 }
119
120 if (TxBuf != NULL) {
121 if (Dev->TxLastUsed == TxCurUsed) {
122 *TxBuf = NULL;
123 } else {
124 UINT16 UsedElemIdx;
125 UINT32 DescIdx;
126
127 //
128 // fetch the first descriptor among those that the hypervisor reports
129 // completed
130 //
131 ASSERT (Dev->TxCurPending > 0);
132 ASSERT (Dev->TxCurPending <= Dev->TxMaxPending);
133
134 UsedElemIdx = Dev->TxLastUsed++ % Dev->TxRing.QueueSize;
135 DescIdx = Dev->TxRing.Used.UsedElem[UsedElemIdx].Id;
136 ASSERT (DescIdx < (UINT32)(2 * Dev->TxMaxPending - 1));
137
138 //
139 // get the device address that has been enqueued for the caller's
140 // transmit buffer
141 //
142 DeviceAddress = Dev->TxRing.Desc[DescIdx + 1].Addr;
143
144 //
145 // now this descriptor can be used again to enqueue a transmit buffer
146 //
147 Dev->TxFreeStack[--Dev->TxCurPending] = (UINT16)DescIdx;
148
149 //
150 // Unmap the device address and perform the reverse mapping to find the
151 // caller buffer address.
152 //
153 Status = VirtioNetUnmapTxBuf (
154 Dev,
155 TxBuf,
156 DeviceAddress
157 );
158 if (EFI_ERROR (Status)) {
159 //
160 // VirtioNetUnmapTxBuf should never fail, if we have reached here
161 // that means our internal state has been corrupted
162 //
163 ASSERT (FALSE);
164 Status = EFI_DEVICE_ERROR;
165 goto Exit;
166 }
167 }
168 }
169
170 Status = EFI_SUCCESS;
171
172Exit:
173 gBS->RestoreTPL (OldTpl);
174 return Status;
175}
VOID EFIAPI MemoryFence(VOID)
Definition: CpuBreakpoint.c:42
#define NULL
Definition: Base.h:319
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS EFIAPI VirtioNetGetStatus(IN EFI_SIMPLE_NETWORK_PROTOCOL *This, OUT UINT32 *InterruptStatus OPTIONAL, OUT VOID **TxBuf OPTIONAL)
Definition: SnpGetStatus.c:51
EFI_STATUS EFIAPI VirtioNetUnmapTxBuf(IN VNET_DEV *Dev, OUT VOID **Buffer, IN EFI_PHYSICAL_ADDRESS DeviceAddress)
VOID EFIAPI Exit(IN EFI_STATUS Status)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS