biossnp16.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 2,446 行 · 第 1/5 页

C
2,446
字号
	}

	Status = EFI_SUCCESS;
	SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS(This);

	if (!SimpleNetworkDevice) {
		return EFI_DEVICE_ERROR;
	}

	EfiZeroMem(&SimpleNetworkDevice->GetNdisInfo, sizeof(PXENV_UNDI_GET_NDIS_INFO_t));

	SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS;

	Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo);

	if (EFI_ERROR(Status)) {
		return Status;
	}

	DEBUG((EFI_D_NET,"  GetNdisInfo.Status       = %d\n",SimpleNetworkDevice->GetNdisInfo.Status));
	DEBUG((EFI_D_NET,"  GetNdisInfo.IfaceType    = %a\n",SimpleNetworkDevice->GetNdisInfo.IfaceType));
	DEBUG((EFI_D_NET,"  GetNdisInfo.LinkSpeed    = %d\n",SimpleNetworkDevice->GetNdisInfo.LinkSpeed));
	DEBUG((EFI_D_NET,"  GetNdisInfo.ServiceFlags = %08x\n",SimpleNetworkDevice->GetNdisInfo.ServiceFlags));

	//
	// Check the status code from the 16 bit UNDI ROM
	//

	if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) {
		return EFI_DEVICE_ERROR;
	}

	//
	// The information has been retrieved.  Fill in Mode data.
	//

	return Status;
}


//
// Isr()
//

EFI_STATUS 
Undi16SimpleNetworkIsr (
	IN EFI_SIMPLE_NETWORK_PROTOCOL *This ,
	IN UINTN              *FrameLength,
	IN UINTN              *FrameHeaderLength,   OPTIONAL
	IN UINT8              *Frame,               OPTIONAL
	IN UINT8              *ProtType,            OPTIONAL
	IN UINT8              *PktType              OPTIONAL
)
{   
	EFI_STATUS              Status;
	EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
	BOOLEAN                 FrameReceived;

	if (!This) {
		return EFI_INVALID_PARAMETER;
	}

	Status = EFI_SUCCESS;
	SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS(This);

	if (!SimpleNetworkDevice) {
		return EFI_DEVICE_ERROR;
	}

	FrameReceived = FALSE;

	//
	// Verify that the current state of the adapter is valid for this call.
	//

	switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
	case EfiSimpleNetworkInitialized:
		break;

	case EfiSimpleNetworkStopped:
		return EFI_NOT_STARTED;

	case EfiSimpleNetworkStarted:
	default:
		return EFI_DEVICE_ERROR;
	}

	DEBUG((EFI_D_NET, "Isr() IsrValid = %d\n",SimpleNetworkDevice->IsrValid));

	if (SimpleNetworkDevice->IsrValid == FALSE) {

		//
		// Call 16 bit UNDI ROM to open the network interface
		//

		EfiZeroMem(&SimpleNetworkDevice->Isr,sizeof(PXENV_UNDI_ISR_t));
		SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
		SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
	
		DEBUG((EFI_D_NET, "Isr() START\n"));

		Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
		if (EFI_ERROR(Status)) {
			return Status;
		}

		//
		// Check the status code from the 16 bit UNDI ROM
		//

		if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
			return EFI_DEVICE_ERROR;
		}

		//
		// There have been no events on this UNDI interface, so return EFI_NOT_READY
		//

		if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) {
			return EFI_SUCCESS;
		}

		//
		// There is data to process, so call until all events processed.
		//

		EfiZeroMem(&SimpleNetworkDevice->Isr,sizeof(PXENV_UNDI_ISR_t));
		SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
		SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;

		DEBUG((EFI_D_NET, "Isr() PROCESS\n"));

		Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
		if (EFI_ERROR(Status)) {
			return Status;
		}

		SimpleNetworkDevice->IsrValid = TRUE;
	}

	//
	// Call UNDI GET_NEXT until DONE
	//

	while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) {

		//
		// Check the status code from the 16 bit UNDI ROM
		//

		if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
			return EFI_DEVICE_ERROR;
		}

		//
		// UNDI is busy.  Caller will have to call again.
		// This should never happen with a polled mode driver.
		//

		if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
			DEBUG((EFI_D_NET,"  BUSY\n"));
			return EFI_SUCCESS;
		}

		//
		// Check for invalud UNDI FuncFlag
		//

		if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE && SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT) {
			DEBUG((EFI_D_NET,"  Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n",SimpleNetworkDevice->Isr.FuncFlag));
			return EFI_DEVICE_ERROR;
		}

		//
		// Check for Transmit Event
		//

		if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
			DEBUG((EFI_D_NET,"  TRANSMIT\n"));
			SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
		} 

		//
		// Check for Receive Event
		//

		else
		if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
			// note - this code will hang on a receive interrupt in a GetStatus loop
			DEBUG((EFI_D_NET,"  RECEIVE\n"));
			SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;

			DEBUG((EFI_D_NET, "SimpleNetworkDevice->Isr.BufferLength      = %d\n",        SimpleNetworkDevice->Isr.BufferLength));
			DEBUG((EFI_D_NET, "SimpleNetworkDevice->Isr.FrameLength       = %d\n",        SimpleNetworkDevice->Isr.FrameLength));
			DEBUG((EFI_D_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n",        SimpleNetworkDevice->Isr.FrameHeaderLength));
			DEBUG((EFI_D_NET, "SimpleNetworkDevice->Isr.Frame             = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel,SimpleNetworkDevice->Isr.FrameOffset));
			DEBUG((EFI_D_NET, "SimpleNetworkDevice->Isr.ProtType          = 0x%02x\n",    SimpleNetworkDevice->Isr.BufferLength));
			DEBUG((EFI_D_NET, "SimpleNetworkDevice->Isr.PktType           = 0x%02x\n",    SimpleNetworkDevice->Isr.BufferLength));

			if (FrameReceived == TRUE) {
				return EFI_SUCCESS;
			}

			if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) {
				DEBUG((EFI_D_NET, "return EFI_BUFFER_TOO_SMALL   *FrameLength = %08x\n",*FrameLength));
				*FrameLength = SimpleNetworkDevice->Isr.FrameLength;
				return EFI_BUFFER_TOO_SMALL;
			}

			*FrameLength = SimpleNetworkDevice->Isr.FrameLength;
			if (FrameHeaderLength != NULL) {
				*FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength;
			}
			if (ProtType != NULL) {
				*ProtType = SimpleNetworkDevice->Isr.ProtType;
			}
			if (PktType != NULL) {
				*PktType = SimpleNetworkDevice->Isr.PktType;
			}
			EfiCopyMem(Frame,(VOID *)((SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset),SimpleNetworkDevice->Isr.BufferLength);
			Frame = Frame + SimpleNetworkDevice->Isr.BufferLength;
			if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) {
				FrameReceived = TRUE;
			}
		}

		//
		// There is data to process, so call until all events processed.
		//

		EfiZeroMem(&SimpleNetworkDevice->Isr,sizeof(PXENV_UNDI_ISR_t));
		SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS;
		SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;

		DEBUG((EFI_D_NET, "Isr() GET NEXT\n"));

		Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
		if (EFI_ERROR(Status)) {
			return Status;
		}

		//
		// Check the status code from the 16 bit UNDI ROM
		//

//        if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
//            return EFI_DEVICE_ERROR;
//        }
	}

	SimpleNetworkDevice->IsrValid = FALSE;
	return EFI_SUCCESS;
}

/////////////////////////////////////////////////////////////////////////////////////////
// Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs
/////////////////////////////////////////////////////////////////////////////////////////

//
// Start()
//

EFI_STATUS
Undi16SimpleNetworkStart (
	IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
)

{
	EFI_STATUS              Status;
	EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;

	if (!This) {
		return EFI_INVALID_PARAMETER;
	}

	Status = EFI_SUCCESS;
	SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS(This);

	if (!SimpleNetworkDevice) {
		return EFI_DEVICE_ERROR;
	}

	//
	// Verify that the current state of the adapter is valid for this call.
	//

	switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
	case EfiSimpleNetworkStopped:
		break;

	case EfiSimpleNetworkStarted:
	case EfiSimpleNetworkInitialized:
		return EFI_ALREADY_STARTED;

	default:
		return EFI_DEVICE_ERROR;
	}

	//
	// The UNDI interface has been started, so update the State.
	//

	SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;

	//
	//
	//

	SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0;
	SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = 0;

	return Status;
}

//
// Stop()
//

EFI_STATUS
Undi16SimpleNetworkStop (
	IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
)

{
	EFI_STATUS              Status;
	EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;

	if (!This) {
		return EFI_INVALID_PARAMETER;
	}

	Status = EFI_SUCCESS;
	SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS(This);

	if (!SimpleNetworkDevice) {
		return EFI_DEVICE_ERROR;
	}

	//
	// Verify that the current state of the adapter is valid for this call.
	//

	switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
	case EfiSimpleNetworkStarted:
		break;

	case EfiSimpleNetworkStopped:
		return EFI_NOT_STARTED;

	case EfiSimpleNetworkInitialized:
	default:
		return EFI_DEVICE_ERROR;
	}

	SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;

	return Status;
}

//
// Initialize()
//

EFI_STATUS
Undi16SimpleNetworkInitialize (
	IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
	IN UINTN               ExtraRxBufferSize  OPTIONAL,
	IN UINTN               ExtraTxBufferSize  OPTIONAL
)
{
	EFI_STATUS              Status;
	EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
	PXENV_UNDI_INITIALIZE_t Initialize; 
	PXENV_UNDI_OPEN_t       Open; 

	if (!This) {
		return EFI_INVALID_PARAMETER;
	}

	Status = EFI_SUCCESS;
	SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS(This);

	if (!SimpleNetworkDevice) {
		return EFI_DEVICE_ERROR;
	}

	//
	// Verify that the current state of the adapter is valid for this call.
	//

	switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
	case EfiSimpleNetworkStopped:
		return EFI_NOT_STARTED;

	case EfiSimpleNetworkStarted:
		break;

	case EfiSimpleNetworkInitialized:
	default:
		return EFI_DEVICE_ERROR;
	}

	//
	// Call 16 bit UNDI ROM to start the network interface
	//

	Initialize.Status = INIT_PXE_STATUS;
	Initialize.ProtocolIni = 0;

	Status = PxeUndiInitialize(SimpleNetworkDevice, &Initialize);

	if (EFI_ERROR(Status)) {
		DEBUG((EFI_D_ERROR,"ERROR : PxeUndiInitialize() - Status = %r\n",Status));
		DEBUG((EFI_D_ERROR, "Initialize.Status == %xh\n", Initialize.Status));

		if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) {
			Status = EFI_NO_MEDIA;
		}

		return Status;
	}

	//
	// Check the status code from the 16 bit UNDI ROM
	//

	if (Initialize.Status != PXENV_STATUS_SUCCESS) {
		DEBUG((EFI_D_ERROR,"ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n",Initialize.Status));
		return EFI_DEVICE_ERROR;
	}

	//
	// Call 16 bit UNDI ROM to open the network interface
	//

	Open.Status = INIT_PXE_STATUS;
	Open.OpenFlag = 0;
	Open.PktFilter = Undi16GetPacketFilterSetting(SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
	Undi16GetMCastFilters(&SimpleNetworkDevice->SimpleNetworkMode,
		&Open.McastBuffer,
		SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize);

	Status = PxeUndiOpen(SimpleNetworkDevice, &Open);

	if (EFI_ERROR(Status)) {
		DEBUG((EFI_D_ERROR,"ERROR : PxeUndiOpen() - Status = %r\n",Status));
		return Status;
	}

	//
	// Check the status code from the 16 bit UNDI ROM
	//

	if (Open.Status != PXENV_STATUS_SUCCESS) {
		DEBUG((EFI_D_ERROR,"ERROR : PxeUndiOpen() - Open.Status = %04x\n",Open.Status));
		return EFI_DEVICE_ERROR;
	}

	//
	// The UNDI interface has been initialized, so update the State.
	//

	SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized;

	//
	// If initialize succeeds, then assume that media is present.
	//

	SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE;

	//
	// Reset the recycled transmit buffer FIFO
	//

	SimpleNetworkDevice->TxBufferFifo.First = 0;
	SimpleNetworkDevice->TxBufferFifo.Last = 0;
	SimpleNetworkDevice->IsrValid = FALSE;

	return Status;
}

//
// Reset()
//

EFI_STATUS
Undi16SimpleNetworkReset (
	IN EFI_SIMPLE_NETWORK_PROTOCOL   *This,
	IN BOOLEAN              ExtendedVerification
)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?