1*719f82d3SEliot Blennerhassett /****************************************************************************** 2*719f82d3SEliot Blennerhassett 3*719f82d3SEliot Blennerhassett AudioScience HPI driver 4*719f82d3SEliot Blennerhassett Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> 5*719f82d3SEliot Blennerhassett 6*719f82d3SEliot Blennerhassett This program is free software; you can redistribute it and/or modify 7*719f82d3SEliot Blennerhassett it under the terms of version 2 of the GNU General Public License as 8*719f82d3SEliot Blennerhassett published by the Free Software Foundation; 9*719f82d3SEliot Blennerhassett 10*719f82d3SEliot Blennerhassett This program is distributed in the hope that it will be useful, 11*719f82d3SEliot Blennerhassett but WITHOUT ANY WARRANTY; without even the implied warranty of 12*719f82d3SEliot Blennerhassett MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*719f82d3SEliot Blennerhassett GNU General Public License for more details. 14*719f82d3SEliot Blennerhassett 15*719f82d3SEliot Blennerhassett You should have received a copy of the GNU General Public License 16*719f82d3SEliot Blennerhassett along with this program; if not, write to the Free Software 17*719f82d3SEliot Blennerhassett Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18*719f82d3SEliot Blennerhassett 19*719f82d3SEliot Blennerhassett HPI Operating System function implementation for Linux 20*719f82d3SEliot Blennerhassett 21*719f82d3SEliot Blennerhassett (C) Copyright AudioScience Inc. 1997-2003 22*719f82d3SEliot Blennerhassett ******************************************************************************/ 23*719f82d3SEliot Blennerhassett #define SOURCEFILE_NAME "hpios.c" 24*719f82d3SEliot Blennerhassett #include "hpi_internal.h" 25*719f82d3SEliot Blennerhassett #include "hpidebug.h" 26*719f82d3SEliot Blennerhassett #include <linux/delay.h> 27*719f82d3SEliot Blennerhassett #include <linux/sched.h> 28*719f82d3SEliot Blennerhassett 29*719f82d3SEliot Blennerhassett void hpios_delay_micro_seconds(u32 num_micro_sec) 30*719f82d3SEliot Blennerhassett { 31*719f82d3SEliot Blennerhassett if ((usecs_to_jiffies(num_micro_sec) > 1) && !in_interrupt()) { 32*719f82d3SEliot Blennerhassett /* MUST NOT SCHEDULE IN INTERRUPT CONTEXT! */ 33*719f82d3SEliot Blennerhassett schedule_timeout_uninterruptible(usecs_to_jiffies 34*719f82d3SEliot Blennerhassett (num_micro_sec)); 35*719f82d3SEliot Blennerhassett } else if (num_micro_sec <= 2000) 36*719f82d3SEliot Blennerhassett udelay(num_micro_sec); 37*719f82d3SEliot Blennerhassett else 38*719f82d3SEliot Blennerhassett mdelay(num_micro_sec / 1000); 39*719f82d3SEliot Blennerhassett 40*719f82d3SEliot Blennerhassett } 41*719f82d3SEliot Blennerhassett 42*719f82d3SEliot Blennerhassett void hpios_locked_mem_init(void) 43*719f82d3SEliot Blennerhassett { 44*719f82d3SEliot Blennerhassett } 45*719f82d3SEliot Blennerhassett 46*719f82d3SEliot Blennerhassett /** Allocated an area of locked memory for bus master DMA operations. 47*719f82d3SEliot Blennerhassett 48*719f82d3SEliot Blennerhassett On error, return -ENOMEM, and *pMemArea.size = 0 49*719f82d3SEliot Blennerhassett */ 50*719f82d3SEliot Blennerhassett u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, 51*719f82d3SEliot Blennerhassett struct pci_dev *pdev) 52*719f82d3SEliot Blennerhassett { 53*719f82d3SEliot Blennerhassett /*?? any benefit in using managed dmam_alloc_coherent? */ 54*719f82d3SEliot Blennerhassett p_mem_area->vaddr = 55*719f82d3SEliot Blennerhassett dma_alloc_coherent(&pdev->dev, size, &p_mem_area->dma_handle, 56*719f82d3SEliot Blennerhassett GFP_DMA32 | GFP_KERNEL); 57*719f82d3SEliot Blennerhassett 58*719f82d3SEliot Blennerhassett if (p_mem_area->vaddr) { 59*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "allocated %d bytes, dma 0x%x vma %p\n", 60*719f82d3SEliot Blennerhassett size, (unsigned int)p_mem_area->dma_handle, 61*719f82d3SEliot Blennerhassett p_mem_area->vaddr); 62*719f82d3SEliot Blennerhassett p_mem_area->pdev = &pdev->dev; 63*719f82d3SEliot Blennerhassett p_mem_area->size = size; 64*719f82d3SEliot Blennerhassett return 0; 65*719f82d3SEliot Blennerhassett } else { 66*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(WARNING, 67*719f82d3SEliot Blennerhassett "failed to allocate %d bytes locked memory\n", size); 68*719f82d3SEliot Blennerhassett p_mem_area->size = 0; 69*719f82d3SEliot Blennerhassett return -ENOMEM; 70*719f82d3SEliot Blennerhassett } 71*719f82d3SEliot Blennerhassett } 72*719f82d3SEliot Blennerhassett 73*719f82d3SEliot Blennerhassett u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area) 74*719f82d3SEliot Blennerhassett { 75*719f82d3SEliot Blennerhassett if (p_mem_area->size) { 76*719f82d3SEliot Blennerhassett dma_free_coherent(p_mem_area->pdev, p_mem_area->size, 77*719f82d3SEliot Blennerhassett p_mem_area->vaddr, p_mem_area->dma_handle); 78*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "freed %lu bytes, dma 0x%x vma %p\n", 79*719f82d3SEliot Blennerhassett (unsigned long)p_mem_area->size, 80*719f82d3SEliot Blennerhassett (unsigned int)p_mem_area->dma_handle, 81*719f82d3SEliot Blennerhassett p_mem_area->vaddr); 82*719f82d3SEliot Blennerhassett p_mem_area->size = 0; 83*719f82d3SEliot Blennerhassett return 0; 84*719f82d3SEliot Blennerhassett } else { 85*719f82d3SEliot Blennerhassett return 1; 86*719f82d3SEliot Blennerhassett } 87*719f82d3SEliot Blennerhassett } 88*719f82d3SEliot Blennerhassett 89*719f82d3SEliot Blennerhassett void hpios_locked_mem_free_all(void) 90*719f82d3SEliot Blennerhassett { 91*719f82d3SEliot Blennerhassett } 92*719f82d3SEliot Blennerhassett 93*719f82d3SEliot Blennerhassett void __iomem *hpios_map_io(struct pci_dev *pci_dev, int idx, 94*719f82d3SEliot Blennerhassett unsigned int length) 95*719f82d3SEliot Blennerhassett { 96*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "mapping %d %s %08llx-%08llx %04llx len 0x%x\n", 97*719f82d3SEliot Blennerhassett idx, pci_dev->resource[idx].name, 98*719f82d3SEliot Blennerhassett (unsigned long long)pci_resource_start(pci_dev, idx), 99*719f82d3SEliot Blennerhassett (unsigned long long)pci_resource_end(pci_dev, idx), 100*719f82d3SEliot Blennerhassett (unsigned long long)pci_resource_flags(pci_dev, idx), length); 101*719f82d3SEliot Blennerhassett 102*719f82d3SEliot Blennerhassett if (!(pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM)) { 103*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "not an io memory resource\n"); 104*719f82d3SEliot Blennerhassett return NULL; 105*719f82d3SEliot Blennerhassett } 106*719f82d3SEliot Blennerhassett 107*719f82d3SEliot Blennerhassett if (length > pci_resource_len(pci_dev, idx)) { 108*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "resource too small for requested %d \n", 109*719f82d3SEliot Blennerhassett length); 110*719f82d3SEliot Blennerhassett return NULL; 111*719f82d3SEliot Blennerhassett } 112*719f82d3SEliot Blennerhassett 113*719f82d3SEliot Blennerhassett return ioremap(pci_resource_start(pci_dev, idx), length); 114*719f82d3SEliot Blennerhassett } 115