📄 xsmsl.c
字号:
/******************************************************************************
**
** COPYRIGHT (C) 2000, 2001 Intel Corporation.
**
** This software as well as the software described in it is furnished under
** license and may only be used or copied in accordance with the terms of the
** license. The information in this file is furnished for informational use
** only, is subject to change without notice, and should not be construed as
** a commitment by Intel Corporation. Intel Corporation assumes no
** responsibility or liability for any errors or inaccuracies that may appear
** in this document or any software that may be provided in association with
** this document.
** Except as permitted by such license, no part of this document may be
** reproduced, stored in a retrieval system, or transmitted in any form or by
** any means without the express written consent of Intel Corporation.
**
** FILENAME: XsMsl.c
**
** PURPOSE: This is the MSL baseband device driver.
**
** LAST MODIFIED: $Modtime: 7/17/03 1:01p $
******************************************************************************/
/*
*******************************************************************************
* HEADER FILES
*******************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include "systypes.h"
#include "dm_errors.h"
#include "DM_Debug.h"
#include "timedelays.h"
#include "XsClkMgr.h"
#include "xsost.h"
#include "mallocx.h"
#include "XsGpioApi.h"
#include "boardcontrol.h"
#include "XsIntCtrlApi.h"
#include "XsDmaApi.h"
#include "XsMsl.h"
#include "XsMslApi.h"
#define XSMSL_GLOBALS 1
#include "XsMslDcs.h"
/*
*******************************************************************************
* LOCAL DEFINITIONS
*******************************************************************************
*/
static OSTContextT *ostCtxP = &Ost;
static MslCfgT gMslCfg = {
DEFAULT_CHANNEL, // Channel number 1-7, 0 = ALL
DEFAULT_TX_WAIT, // Number of cycles before retransmit (1-1023)
DEFAULT_CLOCK_COUNT, // Number of extra clock cycles (0-14, 15 - never stops)
DEFAULT_FREQ_DIV, // The frequency divider
IF_4BITS, // The number of bits.
RX_DEFAULT_LENGTH, // Size of the receive packet
TX_DEFAULT_LENGTH, // Size of the transmit packet
BLOCKSIZE_32B, // Size of the transmit block
FIFO_SERVICE_POLL, // Receive FIFO service
FIFO_SERVICE_POLL, // Transmit FIFO service
THRESHOLD_16B, // Receive threshold
THRESHOLD_32B, // Transmit threshold
DFC, // Receive flow control
DFC, // Transmit flow control
};
/*
*******************************************************************************
*
* FUNCTION:
* MslDumpFrame
*
* DESCRIPTION:
* Display the contents of the specified frame.
*
* INPUT PARAMETERS:
* PUCHAR_T frame - a pointer to the frame.
* UINT32 length - length of the frame.
*
* RETURNS:
* None.
*
* GLOBAL EFFECTS:
* None.
*
* ASSUMPTIONS:
* None.
*
* CALLS:
* printf.
*
* CALLED BY:
* This test code.
*
* PROTOTYPE:
* VOID MslDumpFrame(PUCHAR frame, UINT32 length);
*
*******************************************************************************
*/
static VOID MslDumpFrame(PUCHAR frame, UINT32 length)
{
UINT32 x;
// DM_FUNC("MslDumpFrame");
// DM_ENTER(DM_CW_MSL_1);
for (x = 0; x < length; x += 8)
{
DM_CwDbgPrintf(DM_CW_MSL_1," %02x %02x %02x %02x %02x %02x %02x %02x",
// printf(" %02x %02x %02x %02x %02x %02x %02x %02x\r\n",
frame[x],
frame[x + 1],
frame[x + 2],
frame[x + 3],
frame[x + 4],
frame[x + 5],
frame[x + 6],
frame[x + 7]);
}
// DM_LEAVE(DM_CW_MSL_1);
}
/*
*******************************************************************************
*
* FUNCTION:
* PrepareReceive
*
* DESCRIPTION:
* Prepare to receive. Should only be set once per shutdown.
*
* INPUT PARAMETERS:
* XsMslContextT ctxP
* UINT32 channel_offset channel to configure
*
* RETURNS:
* SUCCESS: ERR_S_MSL_NONE (0)
* FAILURE: Non-Zero
*
* GLOBAL EFFECTS:
* Device Context Structure initialized and prepared to handle transmit.
*
* ASSUMPTIONS:
* Called from XsMslHWSetup.
*
* CALLS:
* XsDmaConfigureMemToMem, XsDmaConfigureDevice, free, malloc,
* XsDmaLoadFirstDescriptorAddr, XsDmaCloseChain
*
* CALLED BY:
* Tests
*
* PROTOTYPE:
* UINT32 ConfigureMslRxChannel(XsMslContextT *ctxP, UINT32 channel_offset)
*
* NOTES:
* In my DMA implementation, I use a 2 descriptor closed chain so there can be
* only 1 outstanding data packet (i.e. each transmit must be followed by a
* receive before the next transmit). I'm using a closed chain instead of an
* open chain because many more operations must be done in the interrupt handler
* resulting in a higher probability of data loss from the rx_fifo filling up.
*
* To Change Modes (POLL/DMA/INT), need to shutdown and startup again.
*
*******************************************************************************
*/
static
UINT32 PrepareReceive(XsMslContextT *ctxP, UINT32 channel_offset)
{
UINT32 status;
DM_FUNC("PrepareReceive");
DM_ENTER(DM_CW_MSL_1);
DM_CwDbgPrintf(DM_CW_MSL_1, "channel_offset: %d", channel_offset+1);
switch(ctxP->rx_fifoservice[channel_offset])
{
case RXSERVICE_NONE:
DM_CwDbgPrintf(DM_CW_MSL_1, "FIFO_SERVICE_POLL");
break;
case RXSERVICE_INT:
DM_CwDbgPrintf(DM_CW_MSL_1, "FIFO_SERVICE_INT");
ctxP->rx_llfirst[channel_offset] = NULL;
ctxP->rx_lllast[channel_offset] = NULL;
// install interrupt handler if it hasn't been installed yet
if (!ctxP->handler_installed)
{
DM_CwDbgPrintf(DM_CW_MSL_1, "XsIcRegisterHandler");
ctxP->handler_installed = 1;
status = XsIcRegisterHandler (XSIC_BASEBAND_SGNL,
(XsIcL1IntHandlerFnPT) XsMslInterruptHandler,
ctxP);
if (status != ERR_NONE)
{
LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RX_CONFIG,
1, ERR_T_NO_HANDLER, 0, 0, 0);
DM_LEAVE(DM_CW_MSL_1);
return (ctxP->loggedError);
}
DM_CwDbgPrintf(DM_CW_MSL_1, "XsIcEnableIrqDeviceInt");
// Enable first level MSL interrupt
status = XsIcEnableIrqDeviceInt (XSIC_BASEBAND_SGNL);
if (status)
{
LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RX_CONFIG,
2, ERR_T_ILLPARAM, 0, 0, 0);
DM_LEAVE(DM_CW_MSL_1);
return (ctxP->loggedError);
}
}
break;
case RXSERVICE_DMA:
DM_CwDbgPrintf(DM_CW_MSL_1, "FIFO_SERVICE_DMA");
// Initialize receive flag
ctxP->xferRxComplete[channel_offset] = FALSE;
ctxP->dmaRxStatus[channel_offset].busErrorIntCount = 0;
ctxP->dmaRxStatus[channel_offset].endIntCount = 0;
ctxP->dmaRxStatus[channel_offset].startIntCount = 0;
ctxP->dmaRxStatus[channel_offset].stopIntCount = 0;
DM_CwDbgPrintf(DM_CW_MSL_1, "Calling XsDmaConfigureDevice for receive");
// MSL to Queue DMA config
status = XsDmaConfigureDevice(
XSDMA_CH_PR_LOW,
XSDMA_DN_BASEBAND_1 + channel_offset,
FALSE,
&ctxP->rx1_firstDescVtP[channel_offset],
MSL_RX_NUM_DEV_DESC,
ctxP->rx_length,
XsMslBgDmaReceivePacket,
ctxP,
DCSR_ENDINTR,
&ctxP->dma_rx_channel1[channel_offset]);
if (status != ERR_NONE)
{
// DMA channel or source memory can not be allocated
LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RX_CONFIG,
5, ERR_T_ILLPARAM, 0, 0, 0);
// Cleanup the allocated resources
XsDmaFreeChannel (ctxP->dma_rx_channel1[channel_offset]);
XsDmaDestroyChain (ctxP->rx1_firstDescVtP[channel_offset]);
DM_LEAVE(DM_CW_MSL_1);
return (ctxP->loggedError);
}
// Stop the DMA channel.
XsDmaStop(ctxP->dma_rx_channel1[channel_offset]);
// Create an endless loop.
XsDmaCloseChain (ctxP->rx1_firstDescVtP[channel_offset]);
// Clear the stop bit to keep the DMA channel running.
XsDmaOperateOnChain (ctxP->rx1_firstDescVtP[channel_offset],
XsDmaDescrClrStopBit);
// Reload the receive descriptor.
XsDmaLoadFirstDescriptorAddr(ctxP->dma_rx_channel1[channel_offset],
ctxP->rx1_firstDescVtP[channel_offset]);
// Restart the DMA channel.
status = XsDmaStart(ctxP->dma_rx_channel1[channel_offset]);
if (status != ERR_NONE)
{
LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RECEIVE,
40, ERR_T_ILLPARAM, 0, 0, 0);
// Cleanup the allocated resources
XsDmaFreeChannel (ctxP->dma_rx_channel1[channel_offset]);
XsDmaDestroyChain (ctxP->rx1_firstDescVtP[channel_offset]);
DM_LEAVE(DM_CW_MSL_1);
return (ctxP->loggedError);
}
DM_CwDbgPrintf(DM_CW_MSL_1, "Calling XsDmaConfigureMemToMem for receive");
// Queue to Memory DMA config
status = XsDmaConfigureMemToMem(
XSDMA_CH_PR_HIGH,
XSDMA_DN_MEMORY,
&ctxP->rx2_firstDescVtP[channel_offset],
MSL_RX_NUM_MEM_DESC,
ctxP->rx_length,
NULL,
NULL,
0,
&ctxP->dma_rx_channel2[channel_offset]);
if (status != ERR_NONE)
{
LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RX_CONFIG,
6, ERR_T_ILLPARAM, 0, 0, 0);
// Cleanup the allocated resources
XsDmaFreeChannel (ctxP->dma_rx_channel2[channel_offset]);
XsDmaDestroyChain (ctxP->rx2_firstDescVtP[channel_offset]);
DM_LEAVE(DM_CW_MSL_1);
return (ctxP->loggedError);
}
DM_CwDbgPrintf(DM_CW_MSL_1, "Free descriptors");
// Throw away the allocated buffers.
free(ctxP->rx2_firstDescVtP[channel_offset]->sourceVirtualAddr);
free(ctxP->rx2_firstDescVtP[channel_offset]->targetVirtualAddr);
DM_CwDbgPrintf(DM_CW_MSL_1, "Calling XsMslEnableRxService");
// Enable the receive channel
XsMslEnableRxService(ctxP, channel_offset);
break;
}
DM_LEAVE(DM_CW_MSL_1);
return (ERR_S_MSL_NONE);
}
/*
*******************************************************************************
*
* FUNCTION:
* PrepareTransmit
*
* DESCRIPTION:
* Prepare to transmit. Should only be set once per shutdown.
*
* INPUT PARAMETERS:
* XsMslContextT ctxP
* UINT32 channel_offset channel to configure
*
* RETURNS:
* SUCCESS: ERR_S_MSL_NONE (0)
* FAILURE: Non-Zero
*
* GLOBAL EFFECTS:
* Device Context Structure initialized and prepared to handle transmit.
*
* ASSUMPTIONS:
* Called from XsMslHWSetup.
*
* CALLS:
* XsDmaConfigureMemToMem, XsDmaConfigureDevice, free, LOGERRORX
*
* CALLED BY:
* Tests
*
* PROTOTYPE:
* UINT32 PrepareTransmit(XsMslContextT *ctxP,
* UINT32 channel_offset)
*
* NOTES:
* In my dma implementation, i start out by creating a dummy linked list
* element so my interrupt can delete memory without worrying about special
* cases in the linked list.
*
* To Change Modes (POLL/DMA/INT), need to shutdown and startup again.
*
*******************************************************************************
*/
static
UINT32 PrepareTransmit(XsMslContextT *ctxP, UINT32 channel_offset)
{
UINT32 status;
DM_FUNC("PrepareTransmit");
DM_ENTER(DM_CW_MSL_1);
DM_CwDbgPrintf(DM_CW_MSL_1, "channel_offset: %d", channel_offset+1);
switch(ctxP->tx_fifoservice[channel_offset])
{
case TXSERVICE_NONE:
DM_CwDbgPrintf(DM_CW_MSL_1, "FIFO_SERVICE_POLL");
break;
case TXSERVICE_INT:
DM_CwDbgPrintf(DM_CW_MSL_1, "FIFO_SERVICE_INT");
ctxP->tx_llfirst[channel_offset] = NULL;
ctxP->tx_lllast[channel_offset] = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -