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