www.pudn.com > CEWifiDriverAR6000-21374.zip > ar6000_cf.c


//------------------------------------------------------------------------------ 
//  
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved. 
//    Copyright (c) 2006 Atheros Corporation.  All rights reserved. 
// 
//    The use and distribution terms for this software are covered by the 
//    Microsoft Limited Permissive License (Ms-LPL)  
//    http://www.microsoft.com/resources/sharedsource/licensingbasics/limitedpermissivelicense.mspx  
//    which can be found in the file MS-LPL.txt at the root of this distribution. 
//    By using this software in any fashion, you are agreeing to be bound by 
//    the terms of this license. 
// 
//    The software is licensed “as-is.”  
//    You must not remove this notice, or any other, from this software. 
//  
//  
//  
//    Windows CE Wifi Driver for AR-6000 
//  
//------------------------------------------------------------------------------ 
//============================================================================== 
// AR6000 HIF CF source 
// 
// Author(s): ="Atheros" 
//============================================================================== 
 
#include  
#include  
#include "giisr.h" 
#include "ar6000_cf.h" 
#include "ar6000_cf_internal.h" 
#include "bus_driver.h" 
#include "osapi.h" 
 
CF_DEVICE   *cfDevice = NULL; 
CF_FUNCTION  cfFunction; 
#ifdef SHARED_INTERRUPTS 
HANDLE       isrHandler; 
GIISR_INFO   Info; 
PVOID	     giisrMappedAddress; 
#endif // SHARED_INTERRUPTS   
 
extern void InterruptDone(DWORD); 
extern boolean printMask; 
 
NDIS_STATUS 
busDriverInit (NDIS_HANDLE miniportHandle,  
               NDIS_HANDLE wrapperConfigurationContext,  
               A_UINT32   sysIntr, 
               BUS_DRIVER_HANDLE *busDriverHandle) 
{ 
    PNDIS_RESOURCE_LIST pNdisResourceList; 
    PCM_PARTIAL_RESOURCE_DESCRIPTOR pResourceDesc; 
    NDIS_PHYSICAL_ADDRESS           physicalAddress; 
    A_UINT32						bufferSize; 
    A_UINT32						dwResourceCount; 
    NDIS_STATUS                     status=NDIS_STATUS_FAILURE; 
    A_UINT32						addressSpace; 
 
    *busDriverHandle = NULL; 
     
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, 
                        "ar6000CFBusInit: Enter \n"); 
 
    cfDevice = A_MALLOC(sizeof(CF_DEVICE)); 
    if (cfDevice == NULL) { 
        HIF_DEBUG_PRINTF(ATH_LOG_ERR, 
            "ar6000CFBusInit: Allocate Memory for CF_DEVICE failed\n"); 
        return status;  
	} 
    A_MEMZERO(cfDevice,sizeof(CF_DEVICE)); 
 
    cfDevice->miniportHandle = miniportHandle; 
    cfDevice->wrapperConfigurationContext=wrapperConfigurationContext; 
 
	pNdisResourceList = NULL; 
	bufferSize = 0; 
 
	//	First call is just to determine buffer size 
    NdisMQueryAdapterResources( 
            &status, 
            wrapperConfigurationContext, 
            pNdisResourceList, 
            &bufferSize); 
 
    pNdisResourceList = A_MALLOC(bufferSize); 
 
    if (pNdisResourceList == NULL) { 
        HIF_DEBUG_PRINTF(ATH_LOG_ERR,  
            "ar6000CFBusInit: AllocateMemory for NDIS_RESOURCE_LIST failed\n"); 
        A_FREE(cfDevice); 
        return NDIS_STATUS_FAILURE; 
    } 
 
    NdisMQueryAdapterResources( 
            &status, 
            wrapperConfigurationContext, 
            pNdisResourceList, 
            &bufferSize); 
 
    if (status != NDIS_STATUS_SUCCESS) { 
        HIF_DEBUG_PRINTF(ATH_LOG_ERR,  
            "ar6000CFBusInit: NdisMQueryAdapterResources failed \n"); 
        A_FREE(pNdisResourceList); 
        A_FREE(cfDevice); 
        return status;  
    } 
 
    /* Search for I/O address and IRQ in assigned resources. */ 
     
    dwResourceCount = pNdisResourceList->Count; 
    pResourceDesc = &(pNdisResourceList->PartialDescriptors[0]); 
 
    while (dwResourceCount--) { 
        switch(pResourceDesc->Type) { 
            case CmResourceTypeInterrupt: 
                cfDevice->interruptNumber =  
                    pResourceDesc->u.Interrupt.Vector; 
                HIF_DEBUG_PRINTF(ATH_LOG_INF, 
                    "ar6000CFBusInit: Interrupt Number = %u\n", cfDevice->interruptNumber); 
                break; 
 
            case CmResourceTypeMemory: 
                cfDevice->memLen = pResourceDesc->u.Memory.Length; 
                cfDevice->deviceMemBase = pResourceDesc->u.Memory.Start.LowPart; 
                HIF_DEBUG_PRINTF(ATH_LOG_INF, 
				    "ar6000CFBusInit: Physical Address = %x Length = %x\n",  
                        cfDevice->deviceMemBase,cfDevice->memLen); 
                break; 
         
            default: 
                HIF_DEBUG_PRINTF(ATH_LOG_ERR, 
                    "ar6000CFBusInit: Unexpected assigned resource type %u\n",  
                    pResourceDesc->Type); 
                break; 
        } 
        pResourceDesc++; 
    } 
 
    A_FREE(pNdisResourceList); 
 
    cfDevice->sysIntr =  sysIntr; 
    HIF_DEBUG_PRINTF(ATH_LOG_INF, 
        "ar6000CFBusInit: sysIntr = %u\n", cfDevice->sysIntr); 
     
    NdisSetPhysicalAddressLow(physicalAddress, cfDevice->deviceMemBase); 
    NdisSetPhysicalAddressHigh(physicalAddress, 0); 
 
    cfDevice->ndisMapped = 1; 
    status = NdisMMapIoSpace((PVOID *)&cfDevice->mappedMemBase, 
                            cfDevice->miniportHandle, 
                            physicalAddress, 
                            cfDevice->memLen); 
    if (status != NDIS_STATUS_SUCCESS) { 
		HIF_DEBUG_PRINTF(ATH_LOG_ERR, 
				"ar6000CFBusInit: NdisMmapIoSpace failed.. Trying MmMapIoSpace \n"); 
        /* NdisMmapIoSpace fails sometimes in WINCE, type MmMapIoSpace */ 
	    cfDevice->mappedMemBase = (A_UINT32) MmMapIoSpace(physicalAddress, 
                                                          cfDevice->memLen, 
                                                          FALSE); 
        if (!cfDevice->mappedMemBase) { 
            HIF_DEBUG_PRINTF(ATH_LOG_ERR, 
                "ar6000CFBusInit: MmMapIoSpace failed \n"); 
            A_FREE(cfDevice); 
            return NDIS_STATUS_FAILURE; 
        }  
        cfDevice->ndisMapped = 0; 
    }  
 
	 addressSpace = 0; 
#ifdef SHARED_INTERRUPTS 
#if (UNDER_CE==600)  
	giisrMappedAddress = (PVOID)cfDevice->mappedMemBase; 
#else 
    if (!TransBusAddrToStatic(PCIBus, 
						 0, 
						 physicalAddress, 
						 cfDevice->memLen, 
						 &addressSpace, 
						 &giisrMappedAddress))  
    { 
        HIF_DEBUG_PRINTF(ATH_LOG_ERR, 
                "ar6000CFBusInit : TransBusAddrToStatic failed \n"); 
        A_FREE(cfDevice); 
        return NDIS_STATUS_FAILURE; 
    } 
#endif //UNDER_CE 
#endif //SHARED_INTERRUPTS 
 
    *busDriverHandle = (BUS_DRIVER_HANDLE)cfDevice; 
     
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, 
                        "ar6000CFBusInit: Exit \n"); 
    return NDIS_STATUS_SUCCESS; 
} 
 
 
void 
busDriverIsr (BUS_DRIVER_HANDLE busDriverHandle,A_BOOL *callDsr) 
{ 
    CF_DEVICE *cfDevice; 
 
    cfDevice = (CF_DEVICE *)busDriverHandle; 
#ifdef DEBUG 
    printMask = FALSE; 
#endif 
    if (cfDevice->interruptRegistered == FALSE) { 
        InterruptDone(cfDevice->sysIntr); 
        *callDsr = FALSE; 
    } else { 
	    cfFunction.pIsr((CF_DEVICE_HANDLE)cfDevice,callDsr); 
    } 
#ifdef DEBUG 
    printMask = TRUE; 
#endif 
    return; 
} 
 
void 
busDriverDsr (BUS_DRIVER_HANDLE busDriverHandle) 
{ 
    CF_DEVICE *cfDevice; 
 
    cfDevice = (CF_DEVICE *)busDriverHandle; 
    cfFunction.pDsr((CF_DEVICE_HANDLE)cfDevice); 
    return; 
} 
 
void 
busDriverShutdown (BUS_DRIVER_HANDLE busDriverHandle) 
{ 
    CF_DEVICE *cfDevice; 
 
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "ar6000CFShutdown: Enter \n"); 
     
    cfDevice = (CF_DEVICE *)busDriverHandle; 
     
    // Remove the mapped space 
    if (cfDevice->ndisMapped) { 
        NdisMUnmapIoSpace(cfDevice->miniportHandle, 
                          (PVOID)cfDevice->mappedMemBase, 
                          cfDevice->memLen); 
    } else { 
        MmUnmapIoSpace((PVOID)cfDevice->mappedMemBase, 
                       cfDevice->memLen); 
    } 
    A_FREE(cfDevice); 
    cfDevice = NULL; 
     
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "ar6000CFShutdown: Exit \n"); 
	return; 
} 
 
#ifdef POLL 
 
A_UINT32 poll; 
 
DWORD cfPollThread(LPVOID Context) 
{ 
    CF_DEVICE    *cfDevice; 
    A_BOOL       callDsr; 
 
    cfDevice = (CF_DEVICE *)Context; 
 
	while (poll) { 
        busDriverIsr((BUS_DRIVER_HANDLE)cfDevice, &callDsr); 
        if (callDsr) { 
            busDriverDsr((BUS_DRIVER_HANDLE)cfDevice); 
        } 
        Sleep(1); 
	}  
 
    return 0; 
} 
 
void startPollThread(CF_DEVICE *cfDevice) 
{ 
    HANDLE hThread; 
 
    poll = 1; 
    hThread = CreateThread(NULL, 0,  
		        cfPollThread, (LPVOID)cfDevice, 0, NULL); 
    CeSetThreadPriority(hThread, 200); 
    CloseHandle(hThread); 
     
    return; 
} 
 
void stopPollThread(CF_DEVICE *cfDevice) 
{ 
    poll = 0; 
} 
#endif 
 
A_STATUS 
CF_MaskInterrupt(CF_DEVICE_HANDLE cfHandle) { 
    CF_DEVICE    *cfDevice; 
 
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, 
                        "CF_MaskInterrupt \n"); 
 
    cfDevice = (CF_DEVICE *)cfHandle; 
#ifdef POLL 
    stopPollThread(cfDevice); 
#else 
    NdisMDeregisterInterrupt(&cfDevice->interruptObject); 
 
#ifdef SHARED_INTERRUPTS 
    if (isrHandler) { 
        FreeIntChainHandler(isrHandler); 
    } 
#endif // SHARED_INTERRUPTS 
#endif 
     
    return A_OK; 
} 
 
A_STATUS 
CF_UnMaskInterrupt(CF_DEVICE_HANDLE cfHandle) { 
    CF_DEVICE    *cfDevice; 
#ifndef POLL 
    NDIS_STATUS   ndisStatus; 
#endif 
     
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, 
				"CF_UnMaskInterrupt \n"); 
	cfDevice = (CF_DEVICE *)cfHandle; 
	 
#ifdef POLL 
    startPollThread(cfDevice); 
#else 
#ifdef SHARED_INTERRUPTS 
    isrHandler = LoadIntChainHandler(TEXT("giisr.dll"),TEXT("ISRHandler"),(BYTE)cfDevice->interruptNumber); 
    if (!isrHandler) { 
        HIF_DEBUG_PRINTF(ATH_LOG_ERR,"CF_UnMaskInterrupt: Load int chain handler failed \n"); 
        return A_ERROR; 
	} 
	memset (&Info,0,sizeof(Info)); 
    Info.SysIntr = cfDevice->sysIntr; 
    Info.CheckPort = TRUE; 
    Info.PortIsIO = FALSE; 
    Info.UseMaskReg = TRUE; 
    Info.PortSize = sizeof(BYTE); 
 
	Info.PortAddr = (DWORD)giisrMappedAddress + 0x00000400; 
	Info.MaskAddr = (DWORD)giisrMappedAddress + 0x00000418; 
 
	if (!KernelLibIoControl(isrHandler,IOCTL_GIISR_INFO,&Info,sizeof(Info),NULL,0,NULL))  { 
        HIF_DEBUG_PRINTF(ATH_LOG_ERR,"CF_UnMaskInterrupt: KernelLibIoControl failed  \n"); 
		return A_ERROR; 
    } 
	 
#endif // SHARED_INTERRUPTS 
    ndisStatus = NdisMRegisterInterrupt(&cfDevice->interruptObject, 
                                    cfDevice->miniportHandle, 
                                    cfDevice->interruptNumber, 
                                    0, TRUE, TRUE, 0); 
 
    if (ndisStatus != NDIS_STATUS_SUCCESS) {  
        return A_ERROR; 
    } 
     
#endif 
    cfDevice->interruptRegistered= TRUE; 
 
    return A_OK; 
} 
 
A_STATUS 
CF_RegisterFunction (CF_FUNCTION *function) 
{ 
    cfFunction.pName = function->pName; 
    cfFunction.pProbe = function->pProbe; 
    cfFunction.pRemove = function->pRemove; 
    cfFunction.pIsr = function->pIsr; 
    cfFunction.pDsr = function->pDsr; 
    cfFunction.pInterruptPending = function->pInterruptPending; 
     
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, 
            "CF_RegisterFunction \n"); 
 
    if (cfDevice == NULL) return A_ERROR; 
 
    cfFunction.pProbe((CF_DEVICE_HANDLE)cfDevice); 
 
    return A_OK; 
} 
 
A_STATUS 
CF_UnregisterFunction (CF_FUNCTION *function) 
{ 
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, 
            "CF_UnregisterFunction \n"); 
 
    AR_DEBUG_ASSERT(cfDevice != NULL); 
    cfFunction.pRemove((CF_DEVICE_HANDLE)cfDevice); 
 
    return A_OK; 
} 
 
static A_STATUS  
CF_BusRequest_8(CF_DEVICE_HANDLE cfHandle, CF_REQUEST *pReq) 
{ 
    volatile A_UCHAR     *data, *base; 
    A_UINT32     len, i; 
    CF_DEVICE    *device; 
 
    device = (CF_DEVICE *)cfHandle; 
 
    if (device == NULL || pReq == NULL) { 
        return A_ERROR; 
    } 
 
    data = (A_UCHAR *)pReq->pDataBuffer; 
    base = (A_UCHAR *)(device->mappedMemBase + pReq->address); 
    len = pReq->length; 
 
    HIF_DEBUG_PRINTF(ATH_LOG_TRC,"CF_BusRequest_8 \n"); 
 
    if (pReq->flags & CFREQ_FLAGS_DATA_WRITE) { 
        if (pReq->flags & CFREQ_FLAGS_FIXED_ADDRESS) { 
            for (i = 0; i < len; i++) { 
                *base = *data; 
                data++; 
            } 
        }  else { 
            for (i = 0; i < len; i++) { 
                *base = *data; 
                base++; 
                data++; 
            } 
        } 
    } else { 
        if (pReq->flags & CFREQ_FLAGS_FIXED_ADDRESS) { 
            for (i = 0; i < len; i++) { 
                *data = *base; 
                data++; 
            } 
        } else { 
            for (i = 0; i < len; i++) { 
                *data = *base; 
                base++; 
                data++; 
            } 
        } 
    } 
     
    return A_OK; 
} 
 
static A_STATUS  
CF_BusRequest_16(CF_DEVICE_HANDLE cfHandle, CF_REQUEST *pReq) 
{ 
    volatile A_UINT16     *data, *base; 
    A_UINT32     len, i; 
    CF_DEVICE    *device; 
 
    device = (CF_DEVICE *)cfHandle; 
 
    if (device == NULL || pReq == NULL) { 
        return A_ERROR; 
    } 
 
    HIF_DEBUG_PRINTF(ATH_LOG_TRC,"CF_BusRequest_16 \n"); 
 
    data = (A_UINT16 *)pReq->pDataBuffer; 
    base = (A_UINT16 *)(device->mappedMemBase + pReq->address); 
    len = pReq->length; 
 
    /* 
     * Assert on odd address and odd length  
     */ 
     
    AR_DEBUG_ASSERT(!(((A_UINT32)data)%2)); 
    AR_DEBUG_ASSERT(!(((A_UINT32)base)%2)); 
    AR_DEBUG_ASSERT(!(len%2)); 
     
    len = len/2; 
 
    if (pReq->flags & CFREQ_FLAGS_DATA_WRITE) { 
        if (pReq->flags & CFREQ_FLAGS_FIXED_ADDRESS) { 
            for (i = 0; i < len; i++) { 
                *base = *data; 
                data++; 
            } 
        }  else { 
            for (i = 0; i < len; i++) { 
                *base = *data; 
                base++; 
                data++; 
            } 
        } 
 
    } else { 
        if (pReq->flags & CFREQ_FLAGS_FIXED_ADDRESS) { 
            for (i = 0; i < len; i++) { 
                *data = *base; 
                data++; 
            } 
        } else { 
            for (i = 0; i < len; i++) { 
                *data = *base; 
                base++; 
                data++; 
            } 
        } 
    } 
    return A_OK; 
} 
 
A_STATUS 
CF_BusRequest(CF_DEVICE_HANDLE cfHandle, CF_REQUEST *pReq,A_UINT32 bits) 
{ 
    A_STATUS status = A_ERROR; 
     
    switch (bits) { 
    case 8: 
        status = CF_BusRequest_8(cfHandle, pReq); 
        break; 
    case 16: 
        status = CF_BusRequest_16(cfHandle, pReq); 
        break; 
    default: 
        AR_DEBUG_ASSERT(0); 
        break; 
    } 
    return status; 
}