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 + -
显示快捷键?