ndismlib.c
来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C语言 代码 · 共 419 行
C
419 行
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// -----------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// -----------------------------------------------------------------------------
#include <windows.h>
#include <ndis.h>
#include "firda.h"
#include "ndisdma.h"
#include "s3c24a0_irda.h"
#include "s3c24a0_intr.h"
#include "s3c24a0_ioport.h"
#include "s3c24a0_clkpwr.h"
#include "s3c24a0_dma.h"
#include "s3c24a0_uart.h"
#include "bsp_cfg.h"
#define MINIPORT_DMA_HANDLE (NDIS_HANDLE) 0x45454545
#define IrDA_BUFLEN 128
extern volatile S3C24A0_DMA_REG *g_pDMA0regs; // DMA0 registers IRDA
extern volatile S3C24A0_DMA_REG *g_pDMA1regs; // DMA0 registers IRDA
extern volatile S3C24A0_IRDA_REG *g_pIRDAregs; // IRDA registers
extern volatile S3C24A0_INTR_REG *g_pINTregs; // INT registers
// We will map our virtual address to our dma physical buffer.
// This is used with any buffer that was mapped into our physical
// buffer.
PVOID
VirtualToPhysAddress(PVOID pvVirtual)
{
// Make sure that the given virtual address is within the range of our buffer.
ASSERT(((PUCHAR)pvVirtual >= (PUCHAR)g_pvDmaVirtualBase) &&
((PUCHAR)pvVirtual < ((PUCHAR)g_pvDmaVirtualBase + S24A0IRDA_DMA_BUFFER_LEN)));
// Physical address is the base physical address plus the offset
// in the virtual address space.
return (PVOID)((DWORD)S24A0IRDA_DMA_BUFFER_BASE_PA +
(DWORD)pvVirtual - (DWORD)g_pvDmaVirtualBase);
}
const int DmaAddrReg[4] = { 0x00, 0x02, 0x04, 0x06};
const int DmaCountReg[4] = { 0x01, 0x03, 0x05, 0x07};
const int DmaPageReg[4] = { 0x87, 0x83, 0x81, 0x82};
//
// Define the DMA mode register structure.
//
typedef struct _DMA_MODE
{
UCHAR Channel : 2;
UCHAR TransferType : 2;
UCHAR AutoInitialize : 1;
UCHAR AddressDecrement : 1;
UCHAR RequestMode : 2;
}DMA_MODE, *PDMA_MODE;
//
// Define TransferType values.
//
#define VERIFY_TRANSFER 0x00
#define READ_TRANSFER 0x01 // Read from the device.
#define WRITE_TRANSFER 0x02 // Write to the device.
//
// Define RequestMode values.
//
#define DEMAND_REQUEST_MODE 0x00
#define SINGLE_REQUEST_MODE 0x01
#define BLOCK_REQUEST_MODE 0x02
#define CASCADE_REQUEST_MODE 0x03
#define DMA_SETMASK 4
#define DMA_CLEARMASK 0
#define DMA_READ 4
#define DMA_WRITE 8
#define DMA_SINGLE_TRANSFER 0x40
#define DMA_AUTO_INIT 0x10 // Auto initialization mode
//
// Define DMA 1 address and count structure (for 8237 compatibility)
//
typedef struct _DMA1_ADDRESS_COUNT
{
UCHAR DmaBaseAddress;
UCHAR DmaBaseCount;
} DMA1_ADDRESS_COUNT, *PDMA1_ADDRESS_COUNT;
//
// Define DMA 1 control register structure (for 8237 compatibility)
//
typedef struct _DMA1_CONTROL
{
DMA1_ADDRESS_COUNT DmaAddressCount[4];
UCHAR DmaStatus;
UCHAR DmaRequest;
UCHAR SingleMask;
UCHAR Mode;
UCHAR ClearBytePointer;
UCHAR MasterClear;
UCHAR ClearMask;
UCHAR AllMask;
} DMA1_CONTROL, *PDMA1_CONTROL;
NDIS_DMA_DESCRIPTION g_DMA_Description;
BOOL g_fRegistered;
UINT g_nDmaChannel;
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
NDIS_STATUS
NdisMRegisterDmaChannel(
PNDIS_HANDLE phMiniportDmaHandle,
NDIS_HANDLE hMiniportAdapterHandle,
UINT nDmaChannel,
BOOLEAN fDma32BitAddresses,
PNDIS_DMA_DESCRIPTION pDmaDescription,
ULONG ulMaximumLength
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
RETAILMSG(DBGIRDA, (TEXT("+NdisMRegisterDmaChannel(%#x, %#x, %d, %d, %#x, %d\r\n"),phMiniportDmaHandle, hMiniportAdapterHandle, nDmaChannel, fDma32BitAddresses, pDmaDescription, ulMaximumLength));
//
// Check to make sure we're not already registered. Only allow one at a time.
//
if (g_fRegistered)
{
Status = NDIS_STATUS_RESOURCE_CONFLICT;
goto done;
}
//
// One DMA Channel per driver. Return Constant.
//
*phMiniportDmaHandle = MINIPORT_DMA_HANDLE;
//
// Store the description for later use.
//
memcpy(&g_DMA_Description, pDmaDescription, sizeof(NDIS_DMA_DESCRIPTION));
g_nDmaChannel = nDmaChannel;
if (g_nDmaChannel > 3)
{
RETAILMSG(DBGIRDA, (TEXT("Whoa! The channel is > 3. Not available in this sample driver!")));
Status = NDIS_STATUS_RESOURCES;
goto done;
}
//
// Indicate that we are registered.
//
g_fRegistered = TRUE;
done:
RETAILMSG(DBGIRDA, (TEXT("-NdisMRegisterDmaChannel --- hDma = 0x%x\r\n"), *phMiniportDmaHandle));
//RETAILMSG(DBGIRDA, (TEXT("-NdisMRegisterDmaChannel %s \r\n"), DBG_NDIS_RESULT_STR(Status)));
return (Status);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
NdisMDeregisterDmaChannel(
PNDIS_HANDLE phMiniportDmaHandle
)
{
DEBUGMSG(ZONE_INIT | ZONE_DMA,
(TEXT("+NdisMDeregisterDmaChannel(%#x)\r\n"), phMiniportDmaHandle));
if (*phMiniportDmaHandle == MINIPORT_DMA_HANDLE)
{
g_fRegistered = FALSE;
}
DEBUGMSG(ZONE_INIT | ZONE_DMA, (TEXT("-NdisMDeregisterDmaChannel\r\n")));
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
NdisMSetupDmaTransfer(
PNDIS_STATUS pStatus,
PNDIS_HANDLE phMiniportDmaHandle,
PNDIS_BUFFER pBuffer,
ULONG Offset,
ULONG Length,
BOOLEAN WriteToDevice
)
{
// int Offset2, Page;
PDMA1_CONTROL dmaControl = 0;
// DMA_MODE dmaMode;
DWORD dwPhysAddress;
// PVOID VirtualAddress;
// UINT BufferLength;
#ifdef DEBUG
unsigned int i;
unsigned char *pc;
#endif
DEBUGMSG(DBGIRDA, (TEXT("+NdisMSetupDmaTransfer %s: buf = 0x%x, offset = %d, len = %d"),
(WriteToDevice == TRUE) ? TEXT("TX") : TEXT("RX"),
pBuffer, Offset, Length));
*pStatus = NDIS_STATUS_SUCCESS;
if (phMiniportDmaHandle != MINIPORT_DMA_HANDLE)
{
*pStatus = NDIS_STATUS_RESOURCES;
goto done;
}
#if 0
NdisQueryBuffer(pBuffer, &VirtualAddress, &BufferLength);
if (Offset + Length > BufferLength)
{
RETAILMSG(DBGIRDA, (TEXT("Whoa! The offset+length is greater than the buffer length!")));
*pStatus = NDIS_STATUS_RESOURCES;
goto done;
}
// Get the physical address from virtual address.
dwPhysAddress = (DWORD)VirtualToPhysAddress(VirtualAddress) + Offset;
#endif
dwPhysAddress = S24A0IRDA_DMA_BUFFER_BASE_PA + PORTINFO_OFFSET + RCV_BUFFER_SIZE;
#if 0
RETAILMSG(DBGIRDA, (TEXT("Address = 0x%X\r\n"), (PBYTE)VirtualAddress + Offset));
RETAILMSG(DBGIRDA, (TEXT("Length = 0x%X\r\n"), BufferLength));
// RETAILMSG(DBGIRDA, (TEXT("Channel = 0x%X\r\n"), g_nDmaChannel));
RETAILMSG(DBGIRDA, (TEXT("DMA Buffer 0x%x, len %d\r\n"), dwPhysAddress + Offset, Length));
// dwPhysAddress = (DWORD)VirtualToPhysAddress(pBuffer);
#endif
//#ifdef DEBUG
#if 0
// DEBUGMSG(DBGIRDA, (TEXT("DMA Buffer 0x%x, len %d \r\n"), dwPhysAddress, Length));
if (WriteToDevice) {
int i;
char *pc;
pc =(unsigned char *) pBuffer;
RETAILMSG(DBGIRDA, (TEXT("\r\n\r\n IrDA Write Buffer Data \r\n")));
for(i=0;i<Length;i++,pc++) {
RETAILMSG(DBGIRDA, (TEXT(" 0x%x"), *pc));
if((i % 16 ) == 15)
RETAILMSG(DBGIRDA, (TEXT("\r\n")));
}
}
#endif
#if 0
//
// PROGRAM THE DMA CHIP
//
Page = (int) ((dwPhysAddress >> 16) & 0xFF);
Offset2 = (int) (dwPhysAddress & 0xFFFF);
// dmaMode.Channel = g_nDmaChannel;
dmaMode.TransferType = (WriteToDevice ? WRITE_TRANSFER : READ_TRANSFER);
dmaMode.RequestMode = DEMAND_REQUEST_MODE;
dmaMode.AutoInitialize = FALSE;
dmaMode.AddressDecrement = FALSE;
#endif
// DMA0 IrDA Rx init
// if (WriteToDevice == READ_TRANSFER)
if (!WriteToDevice) //Rx
{
// Irda_GPIO_Conf(FALSE);
g_pDMA0regs->DISRC = (unsigned int) 0x41800020; //Address of RxBUF Register
g_pDMA0regs->DISRCC = (0<<1)|(1); //AHB(IrDA), fix
g_pDMA0regs->DIDST = (unsigned int) (unsigned int)(dwPhysAddress);
g_pDMA0regs->DIDSTC = (0<<1)|(0); //AHB(Memory), inc
g_pDMA0regs->DCON = (0<<31)|(1<<30)|(1<<29)|(0<<28)|(0<<27)|(7<<24)|(1<<23)|(0<<22)|(0<<20)|(0x5);
//demand, sync HCLK, TC int, single tx, single service, IrDA, H/W request,
//off-reload, byte, IrDA_BUFLEN
// g_pINTregs->rINTMSK &= ~BIT_DMA_SBUS;
// g_pINTregs->rINTSUBMSK &= ~BIT_SUB_DMA0;
// g_pINTregs->rINTSUBMSK &= ~BIT_SUB_DMA1;
Init_Irda_Rx(Length,S24A0_IRDA_RXMODEDMA);
g_pDMA0regs->DMASKTRIG = (0<<2)|(1<<1)|(0); // Run, DMA0 channel on, no-sw trigger
}
else
{
// DMA1 IrDA Tx init
g_pDMA1regs->DISRC = (unsigned int)(dwPhysAddress);
g_pDMA1regs->DISRCC = (0<<1)|(0); //AHB(Memory), inc
g_pDMA1regs->DIDST = (unsigned int) 0x41800020; //Address of IrDA_RBR Register
g_pDMA1regs->DIDSTC = (0<<1)|(1); //AHB(IrDA), fix
g_pDMA1regs->DCON = (0<<31)|(1<<30)|(1<<29)|(0<<28)|(0<<27)|(7<<24)|(1<<23)|(1<<22)|(0<<20)|(Length);
//demand, sync HCLK, TC int, unit transfer, single tx, single service, IrDA, H/W request,
//off-reload, byte, IrDA_BUFLEN
Init_Irda_Tx(Length);
g_pDMA1regs->DMASKTRIG = (0<<2) | (1<<1) | 0;
}
// RETAILMSG(DBGIRDA, (TEXT("DMA Read Started")));
// RETAILMSG(DBGIRDA, (TEXT("ReadCount (before) = %d"), NdisMReadDmaCounter(phMiniportDmaHandle)));
done:
// RETAILMSG(DBGIRDA, (TEXT("-NdisMSetupDmaTransfer [%s]"), DBG_NDIS_RESULT_STR(*pStatus)));
return;
}
// -----------------------------------------------------------------------------
// The function disables the Rx/Tx in the IRDa module and can be used with the DMA
// and the interrupt transfers and receives. The name is a misnomer.
// -----------------------------------------------------------------------------
VOID
NdisMCompleteDmaTransfer(
PNDIS_STATUS Status,
PNDIS_HANDLE MiniportDmaHandle,
PNDIS_BUFFER Buffer,
ULONG Offset,
ULONG Length,
BOOLEAN WriteToDevice
)
{
#if 0
RETAILMSG(DBGIRDA, (TEXT("+NdisMCompleteDmaTransfer %s: buf = 0x%x, offset = %d, len = %d\r\n"),
(WriteToDevice == TRUE) ? TEXT("TX") : TEXT("RX"),
Buffer, Offset, Length));
if (WriteToDevice == WRITE_TRANSFER)
while(!(g_pIRDAregs->IRDA_LSR & 0x80)); // Wait until TX FIFO is empty
//
// Disable the RxTx
//
g_pIRDAregs->IRDA_CNT = (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<1)|(0); // Disable RXTX
#endif
g_pDMA1regs->DMASKTRIG = (1<<2)|(0<<1)|(0); // STOP,DMA0 channel off, no-sw trigger
g_pIRDAregs->IRDA_CNT &= ~(3<<6); //Resest Tx and Rx bits
// Interrupt & DMA Control Register
g_pIRDAregs->IRDA_CNF = 0x0; // Disable Interrupt & DMA
// Interrupt Enable Register
g_pIRDAregs->IRDA_IER = 0x0; // Disable All interrupts
// RETAILMSG(DBGIRDA, (TEXT("-NdisMCompleteDmaTransfer [NDIS_STATUS_SUCCESS]\r\n")));
*Status = NDIS_STATUS_SUCCESS;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
ULONG
NdisMReadDmaCounter(
NDIS_HANDLE MiniportDmaHandle
)
{
ULONG count;
count = (g_pDMA1regs->DSTAT & 0x7ffff);
return count;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?