1263970Sdes/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ 2224638Sbrooks 357429Smarkm/*- 492559Sdes * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> 557429Smarkm * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org> 657429Smarkm * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org> 757429Smarkm * 857429Smarkm * Permission to use, copy, modify, and distribute this software for any 957429Smarkm * purpose with or without fee is hereby granted, provided that the above 1057429Smarkm * copyright notice and this permission notice appear in all copies. 1157429Smarkm * 1257429Smarkm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1357429Smarkm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1457429Smarkm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1557429Smarkm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1657429Smarkm * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1757429Smarkm * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1857429Smarkm * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1957429Smarkm */ 2057429Smarkm 2157429Smarkm#include <sys/cdefs.h> 2257429Smarkm#include "opt_wlan.h" 2357429Smarkm 2457429Smarkm#include <sys/param.h> 2557429Smarkm#include <sys/lock.h> 2657429Smarkm#include <sys/mutex.h> 2757429Smarkm#include <sys/mbuf.h> 28263970Sdes#include <sys/kernel.h> 2957429Smarkm#include <sys/socket.h> 30162856Sdes#include <sys/systm.h> 31162856Sdes#include <sys/malloc.h> 32162856Sdes#include <sys/queue.h> 33162856Sdes#include <sys/taskqueue.h> 34162856Sdes#include <sys/bus.h> 35162856Sdes#include <sys/endian.h> 36162856Sdes#include <sys/linker.h> 3792559Sdes 3860573Skris#include <machine/bus.h> 3960573Skris#include <machine/resource.h> 4076262Sgreen#include <sys/rman.h> 4192559Sdes 4257429Smarkm#include <net/if.h> 4357429Smarkm#include <net/ethernet.h> 4460573Skris#include <net/if_media.h> 4560573Skris 4657429Smarkm#include <net80211/ieee80211_var.h> 4760573Skris#include <net80211/ieee80211_radiotap.h> 4860573Skris 4960573Skris#include <dev/rtwn/if_rtwnvar.h> 50251135Sdes#include <dev/rtwn/if_rtwn_debug.h> 51251135Sdes 52106130Sdes#include <dev/rtwn/pci/rtwn_pci_var.h> 5360573Skris 5460573Skris#include <dev/rtwn/rtl8192c/pci/r92ce.h> 5560573Skris#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h> 5657429Smarkm 5757429Smarkmint 58106130Sdesr92ce_get_intr_status(struct rtwn_pci_softc *pc, int *rings) 5957429Smarkm{ 6057429Smarkm struct rtwn_softc *sc = &pc->pc_sc; 6160573Skris uint32_t status; 6260573Skris int ret; 6360573Skris 6460573Skris *rings = 0; 6592559Sdes status = rtwn_read_4(sc, R92C_HISR); 6669587Sgreen RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: HISR %08X, HISRE %04X\n", 6769587Sgreen __func__, status, rtwn_read_2(sc, R92C_HISRE)); 6860573Skris if (status == 0 || status == 0xffffffff) 6960573Skris return (0); 7092559Sdes 7192559Sdes /* Disable interrupts. */ 7292559Sdes rtwn_write_4(sc, R92C_HIMR, 0); 7392559Sdes 7498684Sdes /* Ack interrupts. */ 75147005Sdes rtwn_write_4(sc, R92C_HISR, status); 7692559Sdes 7798684Sdes if (status & R92C_IMR_BDOK) 78147005Sdes *rings |= (1 << RTWN_PCI_BEACON_QUEUE); 7992559Sdes if (status & R92C_IMR_HIGHDOK) 80147005Sdes *rings |= (1 << RTWN_PCI_HIGH_QUEUE); 81147005Sdes if (status & R92C_IMR_MGNTDOK) 8292559Sdes *rings |= (1 << RTWN_PCI_MGNT_QUEUE); 8392559Sdes if (status & R92C_IMR_BKDOK) 8476262Sgreen *rings |= (1 << RTWN_PCI_BK_QUEUE); 85147005Sdes if (status & R92C_IMR_BEDOK) 86147005Sdes *rings |= (1 << RTWN_PCI_BE_QUEUE); 8792559Sdes if (status & R92C_IMR_VIDOK) 8892559Sdes *rings |= (1 << RTWN_PCI_VI_QUEUE); 8998684Sdes if (status & R92C_IMR_VODOK) 90147005Sdes *rings |= (1 << RTWN_PCI_VO_QUEUE); 91147005Sdes 92147005Sdes ret = 0; 9398684Sdes if (status & R92C_IMR_RXFOVW) 9498684Sdes ret |= RTWN_PCI_INTR_RX_OVERFLOW; 95147005Sdes if (status & R92C_IMR_RDU) 96147005Sdes ret |= RTWN_PCI_INTR_RX_DESC_UNAVAIL; 9798684Sdes if (status & R92C_IMR_ROK) 98192595Sdes ret |= RTWN_PCI_INTR_RX_DONE; 99247485Sdes if (status & R92C_IMR_TXFOVW) 100264693Sdes ret |= RTWN_PCI_INTR_TX_OVERFLOW; 101264693Sdes if (status & R92C_IMR_PSTIMEOUT) 102264693Sdes ret |= RTWN_PCI_INTR_PS_TIMEOUT; 103192595Sdes 10492559Sdes return (ret); 10592559Sdes} 10676262Sgreen 107113911Sdes#define R92C_INT_ENABLE (R92C_IMR_ROK | R92C_IMR_VODOK | R92C_IMR_VIDOK | \ 108113911Sdes R92C_IMR_BEDOK | R92C_IMR_BKDOK | R92C_IMR_MGNTDOK | \ 10992559Sdes R92C_IMR_HIGHDOK | R92C_IMR_BDOK | R92C_IMR_RDU | \ 11076262Sgreen R92C_IMR_RXFOVW) 111113911Sdesvoid 112113911Sdesr92ce_enable_intr(struct rtwn_pci_softc *pc) 11392559Sdes{ 11492559Sdes struct rtwn_softc *sc = &pc->pc_sc; 11592559Sdes 11692559Sdes /* Enable interrupts. */ 11792559Sdes rtwn_write_4(sc, R92C_HIMR, R92C_INT_ENABLE); 11892559Sdes} 11992559Sdes 12076262Sgreenvoid 12176262Sgreenr92ce_start_xfers(struct rtwn_softc *sc) 12276262Sgreen{ 12392559Sdes /* Clear pending interrupts. */ 124113911Sdes rtwn_write_4(sc, R92C_HISR, 0xffffffff); 12592559Sdes 12692559Sdes /* Enable interrupts. */ 12776262Sgreen rtwn_write_4(sc, R92C_HIMR, R92C_INT_ENABLE); 12876262Sgreen} 12976262Sgreen#undef R92C_INT_ENABLE 13092559Sdes