]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Get_status.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Get_status.c
CommitLineData
75d0f44d 1/** @file\r
4140a663 2 Implementation of reading the current interrupt status and recycled transmit\r
3 buffer status from a network interface.\r
4cda7726 4\r
7b4b93a2 5Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
75d0f44d 7\r
75d0f44d 8**/\r
9\r
10#include "Snp.h"\r
11\r
75d0f44d 12/**\r
7b4b93a2
FS
13 Call undi to get the status of the interrupts, get the list of recycled transmit\r
14 buffers that completed transmitting. The recycled transmit buffer address will\r
128946c9
FS
15 be saved into Snp->RecycledTxBuf. This function will also update the MediaPresent\r
16 field of EFI_SIMPLE_NETWORK_MODE if UNDI support it.\r
f3816027 17\r
128946c9
FS
18 @param[in] Snp Pointer to snp driver structure.\r
19 @param[out] InterruptStatusPtr A non null pointer to contain the interrupt\r
20 status.\r
21 @param[in] GetTransmittedBuf Set to TRUE to retrieve the recycled transmit\r
22 buffer address.\r
c777c357 23\r
128946c9
FS
24 @retval EFI_SUCCESS The status of the network interface was retrieved.\r
25 @retval EFI_DEVICE_ERROR The command could not be sent to the network\r
26 interface.\r
75d0f44d 27\r
28**/\r
29EFI_STATUS\r
4cda7726 30PxeGetStatus (\r
128946c9
FS
31 IN SNP_DRIVER *Snp,\r
32 OUT UINT32 *InterruptStatusPtr,\r
33 IN BOOLEAN GetTransmittedBuf\r
75d0f44d 34 )\r
35{\r
4cda7726 36 PXE_DB_GET_STATUS *Db;\r
75d0f44d 37 UINT16 InterruptFlags;\r
7b4b93a2
FS
38 UINT32 Index;\r
39 UINT64 *Tmp;\r
75d0f44d 40\r
7b4b93a2 41 Tmp = NULL;\r
4cda7726 42 Db = Snp->Db;\r
43 Snp->Cdb.OpCode = PXE_OPCODE_GET_STATUS;\r
75d0f44d 44\r
4cda7726 45 Snp->Cdb.OpFlags = 0;\r
75d0f44d 46\r
7b4b93a2 47 if (GetTransmittedBuf) {\r
4cda7726 48 Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS;\r
7b4b93a2 49 ZeroMem (Db->TxBuffer, sizeof (Db->TxBuffer));\r
75d0f44d 50 }\r
51\r
52 if (InterruptStatusPtr != NULL) {\r
4cda7726 53 Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_INTERRUPT_STATUS;\r
75d0f44d 54 }\r
55\r
c777c357 56 if (Snp->MediaStatusSupported) {\r
57 Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_MEDIA_STATUS;\r
58 }\r
59\r
4cda7726 60 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
61 Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;\r
75d0f44d 62\r
f000a8c6 63 Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_GET_STATUS);\r
4cda7726 64 Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;\r
75d0f44d 65\r
4cda7726 66 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
67 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
68 Snp->Cdb.IFnum = Snp->IfNum;\r
69 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
75d0f44d 70\r
71 //\r
72 // Issue UNDI command and check result.\r
73 //\r
9cff2f8d 74 DEBUG ((EFI_D_NET, "\nSnp->undi.get_status() "));\r
75d0f44d 75\r
4cda7726 76 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
75d0f44d 77\r
3af347b3 78 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
75d0f44d 79 DEBUG (\r
9cff2f8d 80 (EFI_D_NET,\r
4cda7726 81 "\nSnp->undi.get_status() %xh:%xh\n",\r
82 Snp->Cdb.StatFlags,\r
1e7b3ef6 83 Snp->Cdb.StatCode)\r
75d0f44d 84 );\r
85\r
86 return EFI_DEVICE_ERROR;\r
87 }\r
88 //\r
89 // report the values back..\r
90 //\r
91 if (InterruptStatusPtr != NULL) {\r
4cda7726 92 InterruptFlags = (UINT16) (Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK);\r
75d0f44d 93\r
94 *InterruptStatusPtr = 0;\r
95\r
4cda7726 96 if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_RECEIVE) == PXE_STATFLAGS_GET_STATUS_RECEIVE) {\r
75d0f44d 97 *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;\r
98 }\r
99\r
4cda7726 100 if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_TRANSMIT) == PXE_STATFLAGS_GET_STATUS_TRANSMIT) {\r
75d0f44d 101 *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;\r
102 }\r
103\r
4cda7726 104 if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_COMMAND) == PXE_STATFLAGS_GET_STATUS_COMMAND) {\r
75d0f44d 105 *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;\r
106 }\r
107\r
4cda7726 108 if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_SOFTWARE) == PXE_STATFLAGS_GET_STATUS_SOFTWARE) {\r
75d0f44d 109 *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;\r
110 }\r
111\r
112 }\r
113\r
7b4b93a2
FS
114 if (GetTransmittedBuf) {\r
115 if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) == 0) {\r
116 //\r
117 // UNDI has written some transmitted buffer addresses into the DB. Store them into Snp->RecycledTxBuf.\r
118 //\r
119 for (Index = 0; Index < MAX_XMIT_BUFFERS; Index++) {\r
120 if (Db->TxBuffer[Index] != 0) {\r
121 if (Snp->RecycledTxBufCount == Snp->MaxRecycledTxBuf) {\r
122 //\r
123 // Snp->RecycledTxBuf is full, reallocate a new one.\r
124 //\r
125 if ((Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= SNP_MAX_TX_BUFFER_NUM) {\r
126 return EFI_DEVICE_ERROR;\r
127 }\r
128 Tmp = AllocatePool (sizeof (UINT64) * (Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT));\r
129 if (Tmp == NULL) {\r
130 return EFI_DEVICE_ERROR;\r
131 }\r
132 CopyMem (Tmp, Snp->RecycledTxBuf, sizeof (UINT64) * Snp->RecycledTxBufCount);\r
133 FreePool (Snp->RecycledTxBuf);\r
134 Snp->RecycledTxBuf = Tmp;\r
135 Snp->MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;\r
136 }\r
137 Snp->RecycledTxBuf[Snp->RecycledTxBufCount] = Db->TxBuffer[Index];\r
138 Snp->RecycledTxBufCount++;\r
139 }\r
140 }\r
141 }\r
75d0f44d 142 }\r
143\r
c777c357 144 //\r
145 // Update MediaPresent field of EFI_SIMPLE_NETWORK_MODE if the UNDI support\r
146 // returning media status from GET_STATUS command\r
147 //\r
148 if (Snp->MediaStatusSupported) {\r
149 Snp->Snp.Mode->MediaPresent =\r
150 (BOOLEAN) (((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA) != 0) ? FALSE : TRUE);\r
151 }\r
152\r
75d0f44d 153 return EFI_SUCCESS;\r
154}\r
155\r
75d0f44d 156/**\r
4cda7726 157 Reads the current interrupt status and recycled transmit buffer status from a\r
158 network interface.\r
c777c357 159\r
160 This function gets the current interrupt and recycled transmit buffer status\r
4cda7726 161 from the network interface. The interrupt status is returned as a bit mask in\r
162 InterruptStatus. If InterruptStatus is NULL, the interrupt status will not be\r
163 read. If TxBuf is not NULL, a recycled transmit buffer address will be retrieved.\r
164 If a recycled transmit buffer address is returned in TxBuf, then the buffer has\r
165 been successfully transmitted, and the status for that buffer is cleared. If\r
c777c357 166 the status of the network interface is successfully collected, EFI_SUCCESS\r
4cda7726 167 will be returned. If the driver has not been initialized, EFI_DEVICE_ERROR will\r
168 be returned.\r
169\r
170 @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.\r
c777c357 171 @param InterruptStatus A pointer to the bit mask of the currently active\r
4cda7726 172 interrupts (see "Related Definitions"). If this is NULL,\r
173 the interrupt status will not be read from the device.\r
174 If this is not NULL, the interrupt status will be read\r
c777c357 175 from the device. When the interrupt status is read, it\r
176 will also be cleared. Clearing the transmit interrupt does\r
4cda7726 177 not empty the recycled transmit buffer array.\r
178 @param TxBuf Recycled transmit buffer address. The network interface\r
c777c357 179 will not transmit if its internal recycled transmit\r
4cda7726 180 buffer array is full. Reading the transmit buffer does\r
181 not clear the transmit interrupt. If this is NULL, then\r
c777c357 182 the transmit buffer status will not be read. If there\r
183 are no transmit buffers to recycle and TxBuf is not NULL,\r
4cda7726 184 TxBuf will be set to NULL.\r
185\r
186 @retval EFI_SUCCESS The status of the network interface was retrieved.\r
187 @retval EFI_NOT_STARTED The network interface has not been started.\r
c777c357 188 @retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid\r
4cda7726 189 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
c777c357 190 @retval EFI_DEVICE_ERROR The command could not be sent to the network\r
4cda7726 191 interface.\r
75d0f44d 192\r
193**/\r
194EFI_STATUS\r
195EFIAPI\r
4cda7726 196SnpUndi32GetStatus (\r
197 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
198 OUT UINT32 *InterruptStatus, OPTIONAL\r
199 OUT VOID **TxBuf OPTIONAL\r
75d0f44d 200 )\r
201{\r
4cda7726 202 SNP_DRIVER *Snp;\r
75d0f44d 203 EFI_TPL OldTpl;\r
204 EFI_STATUS Status;\r
205\r
4cda7726 206 if (This == NULL) {\r
75d0f44d 207 return EFI_INVALID_PARAMETER;\r
208 }\r
209\r
4cda7726 210 if (InterruptStatus == NULL && TxBuf == NULL) {\r
75d0f44d 211 return EFI_INVALID_PARAMETER;\r
212 }\r
213\r
4cda7726 214 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
75d0f44d 215\r
216 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
217\r
4cda7726 218 if (Snp == NULL) {\r
75d0f44d 219 return EFI_DEVICE_ERROR;\r
220 }\r
221\r
4cda7726 222 switch (Snp->Mode.State) {\r
75d0f44d 223 case EfiSimpleNetworkInitialized:\r
224 break;\r
225\r
226 case EfiSimpleNetworkStopped:\r
227 Status = EFI_NOT_STARTED;\r
228 goto ON_EXIT;\r
229\r
230 default:\r
231 Status = EFI_DEVICE_ERROR;\r
232 goto ON_EXIT;\r
233 }\r
234\r
7b4b93a2
FS
235 if (Snp->RecycledTxBufCount == 0 && TxBuf != NULL) {\r
236 Status = PxeGetStatus (Snp, InterruptStatus, TRUE);\r
237 } else {\r
238 Status = PxeGetStatus (Snp, InterruptStatus, FALSE);\r
239 }\r
240\r
241 if (TxBuf != NULL) {\r
242 //\r
243 // Get a recycled buf from Snp->RecycledTxBuf\r
244 //\r
245 if (Snp->RecycledTxBufCount == 0) {\r
246 *TxBuf = NULL;\r
247 } else {\r
248 Snp->RecycledTxBufCount--;\r
249 *TxBuf = (VOID *) (UINTN) Snp->RecycledTxBuf[Snp->RecycledTxBufCount];\r
250 }\r
251 }\r
75d0f44d 252\r
253ON_EXIT:\r
254 gBS->RestoreTPL (OldTpl);\r
255\r
256 return Status;\r
257}\r