123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- /** @file
- Implementation of reading the current interrupt status and recycled transmit
- buffer status from a network interface.
- Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Snp.h"
- /**
- Call undi to get the status of the interrupts, get the list of recycled transmit
- buffers that completed transmitting. The recycled transmit buffer address will
- be saved into Snp->RecycledTxBuf. This function will also update the MediaPresent
- field of EFI_SIMPLE_NETWORK_MODE if UNDI support it.
- @param[in] Snp Pointer to snp driver structure.
- @param[out] InterruptStatusPtr A non null pointer to contain the interrupt
- status.
- @param[in] GetTransmittedBuf Set to TRUE to retrieve the recycled transmit
- buffer address.
- @retval EFI_SUCCESS The status of the network interface was retrieved.
- @retval EFI_DEVICE_ERROR The command could not be sent to the network
- interface.
- **/
- EFI_STATUS
- PxeGetStatus (
- IN SNP_DRIVER *Snp,
- OUT UINT32 *InterruptStatusPtr,
- IN BOOLEAN GetTransmittedBuf
- )
- {
- PXE_DB_GET_STATUS *Db;
- UINT16 InterruptFlags;
- UINT32 Index;
- UINT64 *Tmp;
- Tmp = NULL;
- Db = Snp->Db;
- Snp->Cdb.OpCode = PXE_OPCODE_GET_STATUS;
- Snp->Cdb.OpFlags = 0;
- if (GetTransmittedBuf) {
- Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS;
- ZeroMem (Db->TxBuffer, sizeof (Db->TxBuffer));
- }
- if (InterruptStatusPtr != NULL) {
- Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_INTERRUPT_STATUS;
- }
- if (Snp->MediaStatusSupported) {
- Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_MEDIA_STATUS;
- }
- Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
- Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
- Snp->Cdb.DBsize = (UINT16)sizeof (PXE_DB_GET_STATUS);
- Snp->Cdb.DBaddr = (UINT64)(UINTN)Db;
- Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
- Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
- Snp->Cdb.IFnum = Snp->IfNum;
- Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
- //
- // Issue UNDI command and check result.
- //
- DEBUG ((DEBUG_NET, "\nSnp->undi.get_status() "));
- (*Snp->IssueUndi32Command)((UINT64)(UINTN)&Snp->Cdb);
- if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
- DEBUG (
- (DEBUG_NET,
- "\nSnp->undi.get_status() %xh:%xh\n",
- Snp->Cdb.StatFlags,
- Snp->Cdb.StatCode)
- );
- return EFI_DEVICE_ERROR;
- }
- //
- // report the values back..
- //
- if (InterruptStatusPtr != NULL) {
- InterruptFlags = (UINT16)(Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK);
- *InterruptStatusPtr = 0;
- if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_RECEIVE) == PXE_STATFLAGS_GET_STATUS_RECEIVE) {
- *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
- }
- if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_TRANSMIT) == PXE_STATFLAGS_GET_STATUS_TRANSMIT) {
- *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
- }
- if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_COMMAND) == PXE_STATFLAGS_GET_STATUS_COMMAND) {
- *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
- }
- if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_SOFTWARE) == PXE_STATFLAGS_GET_STATUS_SOFTWARE) {
- *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
- }
- }
- if (GetTransmittedBuf) {
- if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) == 0) {
- //
- // UNDI has written some transmitted buffer addresses into the DB. Store them into Snp->RecycledTxBuf.
- //
- for (Index = 0; Index < MAX_XMIT_BUFFERS; Index++) {
- if (Db->TxBuffer[Index] != 0) {
- if (Snp->RecycledTxBufCount == Snp->MaxRecycledTxBuf) {
- //
- // Snp->RecycledTxBuf is full, reallocate a new one.
- //
- if ((Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= SNP_MAX_TX_BUFFER_NUM) {
- return EFI_DEVICE_ERROR;
- }
- Tmp = AllocatePool (sizeof (UINT64) * (Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT));
- if (Tmp == NULL) {
- return EFI_DEVICE_ERROR;
- }
- CopyMem (Tmp, Snp->RecycledTxBuf, sizeof (UINT64) * Snp->RecycledTxBufCount);
- FreePool (Snp->RecycledTxBuf);
- Snp->RecycledTxBuf = Tmp;
- Snp->MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;
- }
- Snp->RecycledTxBuf[Snp->RecycledTxBufCount] = Db->TxBuffer[Index];
- Snp->RecycledTxBufCount++;
- }
- }
- }
- }
- //
- // Update MediaPresent field of EFI_SIMPLE_NETWORK_MODE if the UNDI support
- // returning media status from GET_STATUS command
- //
- if (Snp->MediaStatusSupported) {
- Snp->Snp.Mode->MediaPresent =
- (BOOLEAN)(((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA) != 0) ? FALSE : TRUE);
- }
- return EFI_SUCCESS;
- }
- /**
- Reads the current interrupt status and recycled transmit buffer status from a
- network interface.
- This function gets the current interrupt and recycled transmit buffer status
- from the network interface. The interrupt status is returned as a bit mask in
- InterruptStatus. If InterruptStatus is NULL, the interrupt status will not be
- read. If TxBuf is not NULL, a recycled transmit buffer address will be retrieved.
- If a recycled transmit buffer address is returned in TxBuf, then the buffer has
- been successfully transmitted, and the status for that buffer is cleared. If
- the status of the network interface is successfully collected, EFI_SUCCESS
- will be returned. If the driver has not been initialized, EFI_DEVICE_ERROR will
- be returned.
- @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
- @param InterruptStatus A pointer to the bit mask of the currently active
- interrupts (see "Related Definitions"). If this is NULL,
- the interrupt status will not be read from the device.
- If this is not NULL, the interrupt status will be read
- from the device. When the interrupt status is read, it
- will also be cleared. Clearing the transmit interrupt does
- not empty the recycled transmit buffer array.
- @param TxBuf Recycled transmit buffer address. The network interface
- will not transmit if its internal recycled transmit
- buffer array is full. Reading the transmit buffer does
- not clear the transmit interrupt. If this is NULL, then
- the transmit buffer status will not be read. If there
- are no transmit buffers to recycle and TxBuf is not NULL,
- TxBuf will be set to NULL.
- @retval EFI_SUCCESS The status of the network interface was retrieved.
- @retval EFI_NOT_STARTED The network interface has not been started.
- @retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
- EFI_SIMPLE_NETWORK_PROTOCOL structure.
- @retval EFI_DEVICE_ERROR The command could not be sent to the network
- interface.
- **/
- EFI_STATUS
- EFIAPI
- SnpUndi32GetStatus (
- IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
- OUT UINT32 *InterruptStatus OPTIONAL,
- OUT VOID **TxBuf OPTIONAL
- )
- {
- SNP_DRIVER *Snp;
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- if ((InterruptStatus == NULL) && (TxBuf == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- if (Snp == NULL) {
- return EFI_DEVICE_ERROR;
- }
- switch (Snp->Mode.State) {
- case EfiSimpleNetworkInitialized:
- break;
- case EfiSimpleNetworkStopped:
- Status = EFI_NOT_STARTED;
- goto ON_EXIT;
- default:
- Status = EFI_DEVICE_ERROR;
- goto ON_EXIT;
- }
- if ((Snp->RecycledTxBufCount == 0) && (TxBuf != NULL)) {
- Status = PxeGetStatus (Snp, InterruptStatus, TRUE);
- } else {
- Status = PxeGetStatus (Snp, InterruptStatus, FALSE);
- }
- if (TxBuf != NULL) {
- //
- // Get a recycled buf from Snp->RecycledTxBuf
- //
- if (Snp->RecycledTxBufCount == 0) {
- *TxBuf = NULL;
- } else {
- Snp->RecycledTxBufCount--;
- *TxBuf = (VOID *)(UINTN)Snp->RecycledTxBuf[Snp->RecycledTxBufCount];
- }
- }
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
|