| /****************************************************************************** |
| |
| AudioScience HPI driver |
| Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of version 2 of the GNU General Public License as |
| published by the Free Software Foundation; |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| |
| HPI Operating System function implementation for Linux |
| |
| (C) Copyright AudioScience Inc. 1997-2003 |
| ******************************************************************************/ |
| #define SOURCEFILE_NAME "hpios.c" |
| #include "hpi_internal.h" |
| #include "hpidebug.h" |
| #include <linux/delay.h> |
| #include <linux/sched.h> |
| |
| void hpios_delay_micro_seconds(u32 num_micro_sec) |
| { |
| if ((usecs_to_jiffies(num_micro_sec) > 1) && !in_interrupt()) { |
| /* MUST NOT SCHEDULE IN INTERRUPT CONTEXT! */ |
| schedule_timeout_uninterruptible(usecs_to_jiffies |
| (num_micro_sec)); |
| } else if (num_micro_sec <= 2000) |
| udelay(num_micro_sec); |
| else |
| mdelay(num_micro_sec / 1000); |
| |
| } |
| |
| void hpios_locked_mem_init(void) |
| { |
| } |
| |
| /** Allocated an area of locked memory for bus master DMA operations. |
| |
| On error, return -ENOMEM, and *pMemArea.size = 0 |
| */ |
| u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, |
| struct pci_dev *pdev) |
| { |
| /*?? any benefit in using managed dmam_alloc_coherent? */ |
| p_mem_area->vaddr = |
| dma_alloc_coherent(&pdev->dev, size, &p_mem_area->dma_handle, |
| GFP_DMA32 | GFP_KERNEL); |
| |
| if (p_mem_area->vaddr) { |
| HPI_DEBUG_LOG(DEBUG, "allocated %d bytes, dma 0x%x vma %p\n", |
| size, (unsigned int)p_mem_area->dma_handle, |
| p_mem_area->vaddr); |
| p_mem_area->pdev = &pdev->dev; |
| p_mem_area->size = size; |
| return 0; |
| } else { |
| HPI_DEBUG_LOG(WARNING, |
| "failed to allocate %d bytes locked memory\n", size); |
| p_mem_area->size = 0; |
| return -ENOMEM; |
| } |
| } |
| |
| u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area) |
| { |
| if (p_mem_area->size) { |
| dma_free_coherent(p_mem_area->pdev, p_mem_area->size, |
| p_mem_area->vaddr, p_mem_area->dma_handle); |
| HPI_DEBUG_LOG(DEBUG, "freed %lu bytes, dma 0x%x vma %p\n", |
| (unsigned long)p_mem_area->size, |
| (unsigned int)p_mem_area->dma_handle, |
| p_mem_area->vaddr); |
| p_mem_area->size = 0; |
| return 0; |
| } else { |
| return 1; |
| } |
| } |
| |
| void hpios_locked_mem_free_all(void) |
| { |
| } |
| |
| void __iomem *hpios_map_io(struct pci_dev *pci_dev, int idx, |
| unsigned int length) |
| { |
| HPI_DEBUG_LOG(DEBUG, "mapping %d %s %08llx-%08llx %04llx len 0x%x\n", |
| idx, pci_dev->resource[idx].name, |
| (unsigned long long)pci_resource_start(pci_dev, idx), |
| (unsigned long long)pci_resource_end(pci_dev, idx), |
| (unsigned long long)pci_resource_flags(pci_dev, idx), length); |
| |
| if (!(pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM)) { |
| HPI_DEBUG_LOG(ERROR, "not an io memory resource\n"); |
| return NULL; |
| } |
| |
| if (length > pci_resource_len(pci_dev, idx)) { |
| HPI_DEBUG_LOG(ERROR, "resource too small for requested %d \n", |
| length); |
| return NULL; |
| } |
| |
| return ioremap(pci_resource_start(pci_dev, idx), length); |
| } |