1185377Ssam/* 2185377Ssam * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2004 Atheros Communications, Inc. 4185377Ssam * 5185377Ssam * Permission to use, copy, modify, and/or distribute this software for any 6185377Ssam * purpose with or without fee is hereby granted, provided that the above 7185377Ssam * copyright notice and this permission notice appear in all copies. 8185377Ssam * 9185377Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10185377Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11185377Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12185377Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13185377Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14185377Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15185377Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16185377Ssam * 17192397Ssam * $FreeBSD$ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam 24185377Ssam#include "ar5210/ar5210.h" 25185377Ssam#include "ar5210/ar5210reg.h" 26185377Ssam 27185377Ssam/* 28185377Ssam * Return non-zero if an interrupt is pending. 29185377Ssam */ 30185377SsamHAL_BOOL 31185377Ssamar5210IsInterruptPending(struct ath_hal *ah) 32185377Ssam{ 33185377Ssam return (OS_REG_READ(ah, AR_INTPEND) ? AH_TRUE : AH_FALSE); 34185377Ssam} 35185377Ssam 36185377Ssam/* 37185377Ssam * Read the Interrupt Status Register value and return 38185377Ssam * an abstracted bitmask of the data found in the ISR. 39185377Ssam * Note that reading the ISR clear pending interrupts. 40185377Ssam */ 41185377SsamHAL_BOOL 42185377Ssamar5210GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) 43185377Ssam{ 44185377Ssam#define AR_FATAL_INT \ 45185377Ssam (AR_ISR_MCABT_INT | AR_ISR_SSERR_INT | AR_ISR_DPERR_INT | AR_ISR_RXORN_INT) 46185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 47185377Ssam uint32_t isr; 48185377Ssam 49185377Ssam isr = OS_REG_READ(ah, AR_ISR); 50185377Ssam if (isr == 0xffffffff) { 51185377Ssam *masked = 0; 52185377Ssam return AH_FALSE; 53185377Ssam } 54185377Ssam 55185377Ssam /* 56185377Ssam * Mask interrupts that have no device-independent 57185377Ssam * representation; these are added back below. We 58185377Ssam * also masked with the abstracted IMR to insure no 59185377Ssam * status bits leak through that weren't requested 60185377Ssam * (e.g. RXNOFRM) and that might confuse the caller. 61185377Ssam */ 62192397Ssam *masked = (isr & (HAL_INT_COMMON - HAL_INT_BNR)) & ahp->ah_maskReg; 63185377Ssam 64185377Ssam if (isr & AR_FATAL_INT) 65185377Ssam *masked |= HAL_INT_FATAL; 66185377Ssam if (isr & (AR_ISR_RXOK_INT | AR_ISR_RXERR_INT)) 67185377Ssam *masked |= HAL_INT_RX; 68185377Ssam if (isr & (AR_ISR_TXOK_INT | AR_ISR_TXDESC_INT | AR_ISR_TXERR_INT | AR_ISR_TXEOL_INT)) 69185377Ssam *masked |= HAL_INT_TX; 70185377Ssam 71185377Ssam /* 72185377Ssam * On fatal errors collect ISR state for debugging. 73185377Ssam */ 74185377Ssam if (*masked & HAL_INT_FATAL) { 75185377Ssam AH_PRIVATE(ah)->ah_fatalState[0] = isr; 76185377Ssam } 77185377Ssam 78185377Ssam return AH_TRUE; 79185377Ssam#undef AR_FATAL_INT 80185377Ssam} 81185377Ssam 82185377SsamHAL_INT 83185377Ssamar5210GetInterrupts(struct ath_hal *ah) 84185377Ssam{ 85185377Ssam return AH5210(ah)->ah_maskReg; 86185377Ssam} 87185377Ssam 88185377SsamHAL_INT 89185377Ssamar5210SetInterrupts(struct ath_hal *ah, HAL_INT ints) 90185377Ssam{ 91185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 92185377Ssam uint32_t omask = ahp->ah_maskReg; 93185377Ssam uint32_t mask; 94185377Ssam 95185377Ssam HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", 96185377Ssam __func__, omask, ints); 97185377Ssam 98185377Ssam /* 99185377Ssam * Disable interrupts here before reading & modifying 100185377Ssam * the mask so that the ISR does not modify the mask 101185377Ssam * out from under us. 102185377Ssam */ 103185377Ssam if (omask & HAL_INT_GLOBAL) { 104185377Ssam HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); 105185377Ssam OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); 106185377Ssam } 107185377Ssam 108192397Ssam mask = ints & (HAL_INT_COMMON - HAL_INT_BNR); 109185377Ssam if (ints & HAL_INT_RX) 110185377Ssam mask |= AR_IMR_RXOK_INT | AR_IMR_RXERR_INT; 111185377Ssam if (ints & HAL_INT_TX) { 112185377Ssam if (ahp->ah_txOkInterruptMask) 113185377Ssam mask |= AR_IMR_TXOK_INT; 114185377Ssam if (ahp->ah_txErrInterruptMask) 115185377Ssam mask |= AR_IMR_TXERR_INT; 116185377Ssam if (ahp->ah_txDescInterruptMask) 117185377Ssam mask |= AR_IMR_TXDESC_INT; 118185377Ssam if (ahp->ah_txEolInterruptMask) 119185377Ssam mask |= AR_IMR_TXEOL_INT; 120185377Ssam } 121185377Ssam 122185377Ssam /* Write the new IMR and store off our SW copy. */ 123185377Ssam HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); 124185377Ssam OS_REG_WRITE(ah, AR_IMR, mask); 125185377Ssam ahp->ah_maskReg = ints; 126185377Ssam 127185377Ssam /* Re-enable interrupts as appropriate. */ 128185377Ssam if (ints & HAL_INT_GLOBAL) { 129185377Ssam HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); 130185377Ssam OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); 131185377Ssam } 132185377Ssam 133185377Ssam return omask; 134185377Ssam} 135