A_STATUS
ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
{
    A_INT32 i;
    struct forceROM_s {
        A_UINT32 addr;
        A_UINT32 data;
    };
    struct forceROM_s *ForceROM;
    A_INT32 szForceROM;
    A_STATUS status = A_OK;
    A_UINT32 address;
    A_UINT32 data;

    static struct forceROM_s ForceROM_NEW[] = {
        {0x52df80, 0x20f31c07},
        {0x52df84, 0x92374420},
        {0x52df88, 0x1d120c03},
        {0x52df8c, 0xff8216f0},
        {0x52df90, 0xf01d120c},
        {0x52df94, 0x81004136},
        {0x52df98, 0xbc9100bd},
        {0x52df9c, 0x00bba100},

        {0x00008000|MC_TCAM_TARGET_ADDRESS, 0x0012dfe0}, /* Use remap entry 0 */
        {0x00008000|MC_TCAM_COMPARE_ADDRESS, 0x000e2380},
        {0x00008000|MC_TCAM_MASK_ADDRESS, 0x00000000},
        {0x00008000|MC_TCAM_VALID_ADDRESS, 0x00000001},

        {0x00018000|(LOCAL_COUNT_ADDRESS+0x10), 0}, /* clear BMI credit counter */

        {0x00004000|AR6002_RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
    };

    address = 0x004ed4b0; /* REV1 target software ID is stored here */
    status = ar6000_ReadRegDiag(hifDevice, &address, &data);
    if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) {
        return A_ERROR; /* Not AR6002 REV1 */
    }

    ForceROM = ForceROM_NEW;
    szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);

    ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Force Target to recognize Host....\n"));
    for (i = 0; i < szForceROM; i++)
    {
        if (ar6000_WriteRegDiag(hifDevice,
                                &ForceROM[i].addr,
                                &ForceROM[i].data) != A_OK)
        {
            ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target to recognize Host!\n"));
            return A_ERROR;
        }
    }

    A_MDELAY(1000);

    return A_OK;
}
A_STATUS ar6000_get_core_clock_config(HIF_DEVICE *hifDevice, A_UINT32 *data)
{
    A_UINT32 regAddress;
    A_STATUS status;

    regAddress = WLAN_RTC_BASE_ADDRESS | WLAN_CPU_CLOCK_ADDRESS;
    /* read CPU clock settings*/
    status = ar6000_ReadRegDiag(hifDevice, &regAddress, data);

    return status;
}
int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data)
{
    u32 regAddress;
    int status;

    regAddress = WLAN_RTC_BASE_ADDRESS | WLAN_CPU_CLOCK_ADDRESS;
    /* read CPU clock settings*/
    status = ar6000_ReadRegDiag(hifDevice, &regAddress, data);

    return status;
}
Beispiel #4
0
A_STATUS
ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
                    A_UCHAR *data, A_UINT32 length)
{
    A_UINT32 count;
    A_STATUS status = A_OK;

    for (count = 0; count < length; count += 4, address += 4) {
        if ((status = ar6000_ReadRegDiag(hifDevice, &address,
                                         (A_UINT32 *)&data[count])) != A_OK)
        {
            break;
        }
    }

    return status;
}
Beispiel #5
0
static A_STATUS
_delay_until_target_alive(HIF_DEVICE *hifDevice, A_INT32 wait_msecs, A_UINT32 TargetType)
{
    A_INT32 actual_wait;
    A_INT32 i;
    A_UINT32 address;

    actual_wait = 0;

    /* Hardcode the address of LOCAL_COUNT_ADDRESS based on the target type */
    if (TargetType == TARGET_TYPE_AR6001) {
        address = AR6001_LOCAL_COUNT_ADDRESS;
    } else if (TargetType == TARGET_TYPE_AR6002) {
       address = AR6002_LOCAL_COUNT_ADDRESS;
    } else if (TargetType == TARGET_TYPE_AR6003) {
       address = AR6003_LOCAL_COUNT_ADDRESS;
    } else {
       A_ASSERT(0);
    }
    address += 0x10;
    for (i=0; actual_wait < wait_msecs; i++) {
        A_UINT32 data;

        A_MDELAY(100);
        actual_wait += 100;

        data = 0;
        if (ar6000_ReadRegDiag(hifDevice, &address, &data) != A_OK) {
            return A_ERROR;
        }

        if (data != 0) {
            /* No need to wait longer -- we have a BMI credit */
            return A_OK;
        }
    }
    return A_ERROR; /* timed out */
}
Beispiel #6
0
void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
{
    A_UINT32 address;
    A_UINT32 regDumpArea = 0;
    A_STATUS status;
    A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
    A_UINT32 regDumpCount = 0;
    A_UINT32 i;

    do {

            /* the reg dump pointer is copied to the host interest area */
        address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);

        if (TargetType == TARGET_TYPE_AR6001) {
                /* for AR6001, this is a fixed location because the ptr is actually stuck in cache,
                 * this may be fixed in later firmware versions */
            address = 0x18a0;
            regDumpCount = REG_DUMP_COUNT_AR6001;

        } else  if (TargetType == TARGET_TYPE_AR6002) {

            regDumpCount = REG_DUMP_COUNT_AR6002;

        } else {
            A_ASSERT(0);
        }

            /* read RAM location through diagnostic window */
        status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);

        if (A_FAILED(status)) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
            break;
        }

        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));

        if (regDumpArea == 0) {
                /* no reg dump */
            break;
        }

        if (TargetType == TARGET_TYPE_AR6001) {
            regDumpArea &= 0x0FFFFFFF;  /* convert to physical address in target memory */
        }

            /* fetch register dump data */
        status = ar6000_ReadDataDiag(hifDevice,
                                     regDumpArea,
                                     (A_UCHAR *)&regDumpValues[0],
                                     regDumpCount * (sizeof(A_UINT32)));

        if (A_FAILED(status)) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
            break;
        }

        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));

        for (i = 0; i < regDumpCount; i++) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d :  0x%8.8X \n",i, regDumpValues[i]));
        }

    } while (FALSE);

}
Beispiel #7
0
/* reset device */
A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
{

#if !defined(DWSIM)
    A_STATUS status = A_OK;
    A_UINT32 address;
    A_UINT32 data;

    do {

        // address = RESET_CONTROL_ADDRESS;
        data = RESET_CONTROL_COLD_RST_MASK;

          /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
        if (TargetType == TARGET_TYPE_AR6001) {
            address = 0x0C000000;
        } else {
            if (TargetType == TARGET_TYPE_AR6002) {
                address = 0x00004000;
            } else {
                A_ASSERT(0);
            }
        }

        status = ar6000_WriteRegDiag(hifDevice, &address, &data);

        if (A_FAILED(status)) {
            break;
        }

        /*
         * Read back the RESET CAUSE register to ensure that the cold reset
         * went through.
         */
        msleep(2000); /* 2 second delay to allow things to settle down */


        // address = RESET_CAUSE_ADDRESS;
        /* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type */
        if (TargetType == TARGET_TYPE_AR6001) {
            address = 0x0C0000CC;
        } else {
            if (TargetType == TARGET_TYPE_AR6002) {
                address = 0x000040C0;
            } else {
                A_ASSERT(0);
            }
        }

        data = 0;
        status = ar6000_ReadRegDiag(hifDevice, &address, &data);

        if (A_FAILED(status)) {
            break;
        }

        AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
        data &= RESET_CAUSE_LAST_MASK;
        if (data != 2) {
            AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
        }

    } while (FALSE);

    if (A_FAILED(status)) {
        AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
    }
#endif
    return A_OK;
}
Beispiel #8
0
/*
 * Call this function just before the call to BMIInit
 * in order to force* AR6002 rev 1.x firmware to detect a Host.
 * THIS IS FOR USE ONLY WITH AR6002 REV 1.x.
 * TBDXXX: Remove this function when REV 1.x is desupported.
 */
A_STATUS
ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
{
    A_INT32 i;
    struct forceROM_s {
        A_UINT32 addr;
        A_UINT32 data;
    };
    struct forceROM_s *ForceROM;
    A_INT32 szForceROM;
    A_STATUS status = A_OK;
    A_UINT32 address;
    A_UINT32 data;

    /* Force AR6002 REV1.x to recognize Host presence.
     *
     * Note: Use RAM at 0x52df80..0x52dfa0 with ROM Remap entry 0
     * so that this workaround functions with AR6002.war1.sh.  We
     * could fold that entire workaround into this one, but it's not
     * worth the effort at this point.  This workaround cannot be
     * merged into the other workaround because this must be done
     * before BMI.
     */

    static struct forceROM_s ForceROM_NEW[] = {
        {0x52df80, 0x20f31c07},
        {0x52df84, 0x92374420},
        {0x52df88, 0x1d120c03},
        {0x52df8c, 0xff8216f0},
        {0x52df90, 0xf01d120c},
        {0x52df94, 0x81004136},
        {0x52df98, 0xbc9100bd},
        {0x52df9c, 0x00bba100},

        {0x00008000|MC_TCAM_TARGET_ADDRESS, 0x0012dfe0}, /* Use remap entry 0 */
        {0x00008000|MC_TCAM_COMPARE_ADDRESS, 0x000e2380},
        {0x00008000|MC_TCAM_MASK_ADDRESS, 0x00000000},
        {0x00008000|MC_TCAM_VALID_ADDRESS, 0x00000001},

        {0x00018000|(LOCAL_COUNT_ADDRESS+0x10), 0}, /* clear BMI credit counter */

        {0x00004000|AR6002_RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
    };

    address = 0x004ed4b0; /* REV1 target software ID is stored here */
    status = ar6000_ReadRegDiag(hifDevice, &address, &data);
    if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) {
        return A_ERROR; /* Not AR6002 REV1 */
    }

    ForceROM = ForceROM_NEW;
    szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);

    ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Force Target to recognize Host....\n"));
    for (i = 0; i < szForceROM; i++)
    {
        if (ar6000_WriteRegDiag(hifDevice,
                                &ForceROM[i].addr,
                                &ForceROM[i].data) != A_OK)
        {
            ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target to recognize Host!\n"));
            return A_ERROR;
        }
    }

    A_MDELAY(1000);

    return A_OK;
}
Beispiel #9
0
void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
{
    A_UINT32 address;
    A_UINT32 regDumpArea = 0;
    A_STATUS status;
    A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
    A_UINT32 regDumpCount = 0;
    A_UINT32 i;

    do {

            /* the reg dump pointer is copied to the host interest area */
        address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);
        address = TARG_VTOP(TargetType, address);

        if (TargetType == TARGET_TYPE_AR6001) {
                /* for AR6001, this is a fixed location because the ptr is actually stuck in cache,
                 * this may be fixed in later firmware versions */
            address = 0x18a0;
            regDumpCount = REG_DUMP_COUNT_AR6001;
        } else  if (TargetType == TARGET_TYPE_AR6002) {
            regDumpCount = REG_DUMP_COUNT_AR6002;
        } else  if (TargetType == TARGET_TYPE_AR6003) {
            regDumpCount = REG_DUMP_COUNT_AR6003;
        } else {
            A_ASSERT(0);
        }

            /* read RAM location through diagnostic window */
        status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);

        if (A_FAILED(status)) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
            break;
        }

        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));

        if (regDumpArea == 0) {
                /* no reg dump */
            break;
        }

        regDumpArea = TARG_VTOP(TargetType, regDumpArea);

            /* fetch register dump data */
        status = ar6000_ReadDataDiag(hifDevice,
                                     regDumpArea,
                                     (A_UCHAR *)&regDumpValues[0],
                                     regDumpCount * (sizeof(A_UINT32)));

        if (A_FAILED(status)) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
            break;
        }
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));

        for (i = 0; i < regDumpCount; i++) {
            //ATHR_DISPLAY_MSG (_T(" %d :  0x%8.8X \n"), i, regDumpValues[i]);
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d :  0x%8.8X \n",i, regDumpValues[i]));

#ifdef UNDER_CE
        /*
         * For Every logPrintf() Open the File so that in case of Crashes
         * We will have until the Last Message Flushed on to the File
         * So use logPrintf Sparingly..!!
         */
        tgtassertPrintf (ATH_DEBUG_TRC," %d:  0x%8.8X \n",i, regDumpValues[i]);
#endif
        }

    } while (FALSE);

}
Beispiel #10
0
/* reset device */
A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL waitForCompletion, A_BOOL coldReset)
{
    A_STATUS status = A_OK;
    A_UINT32 address;
    A_UINT32 data;

    do {
// Workaround BEGIN
        // address = RESET_CONTROL_ADDRESS;
    	
    	if (coldReset) {
            data = RESET_CONTROL_COLD_RST_MASK;
    	}
    	else {
            data = RESET_CONTROL_MBOX_RST_MASK;
    	}

          /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
        if (TargetType == TARGET_TYPE_AR6001) {
            address = AR6001_RESET_CONTROL_ADDRESS;
        } else if (TargetType == TARGET_TYPE_AR6002) {
            address = AR6002_RESET_CONTROL_ADDRESS;
        } else if (TargetType == TARGET_TYPE_AR6003) {
            address = AR6003_RESET_CONTROL_ADDRESS;
        } else {
            A_ASSERT(0);
        }


        status = ar6000_WriteRegDiag(hifDevice, &address, &data);

        if (A_FAILED(status)) {
            break;
        }

        if (!waitForCompletion) {
            break;
        }

#if 0
        /* Up to 2 second delay to allow things to settle down */
        (void)_delay_until_target_alive(hifDevice, 2000, TargetType);

        /*
         * Read back the RESET CAUSE register to ensure that the cold reset
         * went through.
         */

        // address = RESET_CAUSE_ADDRESS;
        /* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type */
        if (TargetType == TARGET_TYPE_AR6001) {
            address = 0x0C0000CC;
        } else if (TargetType == TARGET_TYPE_AR6002) {
            address = 0x000040C0;
        } else if (TargetType == TARGET_TYPE_AR6003) {
            address = 0x000040C0;
        } else {
            A_ASSERT(0);
        }

        data = 0;
        status = ar6000_ReadRegDiag(hifDevice, &address, &data);

        if (A_FAILED(status)) {
            break;
        }

        AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
        data &= RESET_CAUSE_LAST_MASK;
        if (data != 2) {
            AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
        }
#endif
// Workaroud END

    } while (FALSE);

    if (A_FAILED(status)) {
        AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
    }

    return A_OK;
}
Beispiel #11
0
static int ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
                                           struct hci_transport_properties *pProps, 
                                           void                     *pContext)
{
    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
    int              status;
    u32 address, hci_uart_pwr_mgmt_params;
//    struct ar3k_config_info      ar3kconfig;
    
    pHcidevInfo->pHCIDev = HCIHandle;
    
    memcpy(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
    
    AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", 
            (unsigned long)HCIHandle, 
            pHcidevInfo->HCIProps.HeadRoom, 
            pHcidevInfo->HCIProps.TailRoom,
            pHcidevInfo->HCIProps.IOBlockPad));
    
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len);
#else
    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= pHcidevInfo->ar->arNetDev->hard_header_len);
#endif
                             
        /* provide buffers */
    RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS);
    RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS);
   
    do {
            /* start transport */
        status = HCI_TransportStart(pHcidevInfo->pHCIDev);
         
        if (status) {
            break;    
        }
        
        if (!pHcidevInfo->HciNormalMode) {
                /* in test mode, no need to go any further */
            break;    
        }

        // The delay is required when AR6K is driving the BT reset line
        // where time is needed after the BT chip is out of reset (HCI_TransportStart)
        // and before the first HCI command is issued (AR3KConfigure)
        // FIXME
        // The delay should be configurable and be only applied when AR6K driving the BT
        // reset line. This could be done by some module parameter or based on some HW config
        // info. For now apply 100ms delay blindly
        A_MDELAY(100);
        
        A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig));
        ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev;
        ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps;
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
        ar3kconfig.pHIFDevice = (struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice);
#else
        ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice;
#endif
        ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev;
        
        if (ar3khcibaud != 0) {
                /* user wants ar3k baud rate change */
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD;
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY;
            ar3kconfig.AR3KBaudRate = ar3khcibaud;    
        }
        
        if ((hciuartscale != 0) || (hciuartstep != 0)) {   
                /* user wants to tune HCI bridge UART scale/step values */
            ar3kconfig.AR6KScale = (u16)hciuartscale;
            ar3kconfig.AR6KStep = (u16)hciuartstep;
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP;
        }
        
        /* Fetch the address of the hi_hci_uart_pwr_mgmt_params instance in the host interest area */
        address = TARG_VTOP(pHcidevInfo->ar->arTargetType, 
                            HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar, hi_hci_uart_pwr_mgmt_params));
        status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
        if (0 == status) {
            ar3kconfig.PwrMgmtEnabled = (hci_uart_pwr_mgmt_params & 0x1);
            ar3kconfig.IdleTimeout = (hci_uart_pwr_mgmt_params & 0xFFFF0000) >> 16;
            ar3kconfig.WakeupTimeout = (hci_uart_pwr_mgmt_params & 0xFF00) >> 8;
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to read hci_uart_pwr_mgmt_params! \n"));
        }
        /* configure the AR3K device */         
		memcpy(ar3kconfig.bdaddr,pHcidevInfo->ar->bdaddr,6);
        status = AR3KConfigure(&ar3kconfig);
        if (status) {
            break; 
        }

        /* Make sure both AR6K and AR3K have power management enabled */
        if (ar3kconfig.PwrMgmtEnabled) {
            status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, true);
            if (status) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n"));
            }
        }
        
        status = bt_register_hci(pHcidevInfo);
        
    } while (false);
static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle, 
                                           HCI_TRANSPORT_PROPERTIES *pProps, 
                                           void                     *pContext)
{
    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
    A_STATUS              status;
    AR_SOFTC_DEV_T *arDev = pHcidevInfo->ar->arDev[0];

    
    pHcidevInfo->pHCIDev = HCIHandle;
    
    A_MEMCPY(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
    
    AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", 
            (unsigned long)HCIHandle, 
            pHcidevInfo->HCIProps.HeadRoom, 
            pHcidevInfo->HCIProps.TailRoom,
            pHcidevInfo->HCIProps.IOBlockPad));
    
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len);
#else
    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= arDev->arNetDev->hard_header_len);
#endif
                             
        /* provide buffers */
    RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS);
    RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS);
   
    do {
            /* start transport */
        status = HCI_TransportStart(pHcidevInfo->pHCIDev);
         
        if (A_FAILED(status)) {
            break;    
        }
        
        if (!pHcidevInfo->HciNormalMode) {
                /* in test mode, no need to go any further */
            break;    
        }

        /* The delay is required when AR6K is driving the BT reset line */
        /* where time is needed after the BT chip is out of reset (HCI_TransportStart) */
        /* and before the first HCI command is issued (AR3KConfigure) */
        /* FIXME */
        /* The delay should be configurable and be only applied when AR6K driving the BT */
        /* reset line. This could be done by some module parameter or based on some HW config */
        /* info. For now apply 100ms delay blindly */
        A_MDELAY(100);
        
        A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig));
        ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev;
        ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps;
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
        ar3kconfig.pHIFDevice = (HIF_DEVICE *)(pHcidevInfo->HCITransHdl.hifDevice);
#else
        ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice;
#endif
        ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev;
        
        if (ar3khcibaud != 0) {
                /* user wants ar3k baud rate change */
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD;
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY;
            ar3kconfig.AR3KBaudRate = ar3khcibaud;    
        }
        
        if ((hciuartscale != 0) || (hciuartstep != 0)) {   
                /* user wants to tune HCI bridge UART scale/step values */
            ar3kconfig.AR6KScale = (A_UINT16)hciuartscale;
            ar3kconfig.AR6KStep = (A_UINT16)hciuartstep;           
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP;
        }
        
            /* configure the AR3K device */  
		memcpy(ar3kconfig.bdaddr,arDev->bdaddr,6);       
        status = AR3KConfigure(&ar3kconfig);
        if (A_FAILED(status)) {
            extern unsigned int setuphci;
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Fail to configure AR3K. No device? Cleanup HCI\n"));
            pHcidevInfo->ar->exitCallback = NULL;
            ar6000_cleanup_hci(pHcidevInfo->ar);
            setuphci = 0;
            pHcidevInfo->ar->arBTSharing = 0;
            break; 
        }

        /* Make sure both AR6K and AR3K have power management enabled */
        if (ar3kconfig.PwrMgmtEnabled) {
            A_UINT32 address, hci_uart_pwr_mgmt_params;
            /* Fetch the address of the hi_hci_uart_pwr_mgmt_params instance in the host interest area */
            address = TARG_VTOP(pHcidevInfo->ar->arTargetType, 
                                HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar->arTargetType, hi_hci_uart_pwr_mgmt_params));
            status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
            hci_uart_pwr_mgmt_params &= 0xFFFF;
            /* wakeup timeout is [31:16] */
            hci_uart_pwr_mgmt_params |= (ar3kconfig.WakeupTimeout << 16);
            status |= ar6000_WriteRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
            if (A_OK != status) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to write hci_uart_pwr_mgmt_params!\n"));
            }

            /* Fetch the address of the hi_hci_uart_pwr_mgmt_params_ext instance in the host interest area */
            address = TARG_VTOP(pHcidevInfo->ar->arTargetType, 
                                HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar->arTargetType, hi_hci_uart_pwr_mgmt_params_ext));
            status = ar6000_WriteRegDiag(pHcidevInfo->ar->arHifDevice, &address, &ar3kconfig.IdleTimeout);
            if (A_OK != status) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to write hci_uart_pwr_mgmt_params_ext!\n"));
            }
        
            status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, TRUE);
            if (A_FAILED(status)) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n"));
            }
        }
        
        status = bt_register_hci(pHcidevInfo);
        
    } while (FALSE);

    return status; 
}
void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
{
    A_UINT32 address;
    A_UINT32 regDumpArea = 0;
    A_STATUS status;
    A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
    A_UINT32 regDumpCount = 0;
    A_UINT32 i;

    do {

        address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);
        address = TARG_VTOP(TargetType, address);

        if (TargetType == TARGET_TYPE_AR6001) {
            address = 0x18a0;
            regDumpCount = REG_DUMP_COUNT_AR6001;
        } else  if (TargetType == TARGET_TYPE_AR6002) {
            regDumpCount = REG_DUMP_COUNT_AR6002;
        } else  if (TargetType == TARGET_TYPE_AR6003) {
            regDumpCount = REG_DUMP_COUNT_AR6003;
        } else {
            A_ASSERT(0);
        }

        status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);

        if (A_FAILED(status)) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
            break;
        }

        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));

        if (regDumpArea == 0) {
                /* no reg dump */
            break;
        }

        regDumpArea = TARG_VTOP(TargetType, regDumpArea);

            /* fetch register dump data */
        status = ar6000_ReadDataDiag(hifDevice,
                                     regDumpArea,
                                     (A_UCHAR *)&regDumpValues[0],
                                     regDumpCount * (sizeof(A_UINT32)));

        if (A_FAILED(status)) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
            break;
        }
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));

        for (i = 0; i < regDumpCount; i++) {
            ATHR_DISPLAY_MSG (_T(" %d :  0x%8.8X \n"), i, regDumpValues[i]);
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d :  0x%8.8X \n",i, regDumpValues[i]));
#ifdef UNDER_CE
            logPrintf(ATH_DEBUG_ERR," %d:  0x%8.8X \n",i, regDumpValues[i]);
#endif
        }

    } while (FALSE);

}
/* reset device */
A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL waitForCompletion)
{
    A_STATUS status = A_OK;
    A_UINT32 address;
    A_UINT32 data;

    do {

        data = RESET_CONTROL_COLD_RST_MASK;

        if (TargetType == TARGET_TYPE_AR6001) {
            address = AR6001_RESET_CONTROL_ADDRESS;
        } else if (TargetType == TARGET_TYPE_AR6002) {
            address = AR6002_RESET_CONTROL_ADDRESS;
        } else if (TargetType == TARGET_TYPE_AR6003) {
            address = AR6003_RESET_CONTROL_ADDRESS;
        } else {
            A_ASSERT(0);
        }

        status = ar6000_WriteRegDiag(hifDevice, &address, &data);

        if (A_FAILED(status)) {
            break;
        }

        if (!waitForCompletion) {
            break;
        }

        (void)_delay_until_target_alive(hifDevice, 1800, TargetType);

        if (TargetType == TARGET_TYPE_AR6001) {
            address = 0x0C0000CC;
        } else if (TargetType == TARGET_TYPE_AR6002) {
            address = 0x000040C0;
        } else if (TargetType == TARGET_TYPE_AR6003) {
            address = 0x000040C0;
        } else {
            A_ASSERT(0);
        }

        data = 0;
        status = ar6000_ReadRegDiag(hifDevice, &address, &data);

        if (A_FAILED(status)) {
            break;
        }

        AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
        data &= RESET_CAUSE_LAST_MASK;
        if (data != 2) {
            AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
        }

    } while (FALSE);

    if (A_FAILED(status)) {
        AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
    }

    return A_OK;
}