1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /******************************************************************************
3 
4     AudioScience HPI driver
5     Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
6 
7 
8 HPI Operating System Specific macros for Linux Kernel driver
9 
10 (C) Copyright AudioScience Inc. 1997-2003
11 ******************************************************************************/
12 #ifndef _HPIOS_H_
13 #define _HPIOS_H_
14 
15 #undef HPI_OS_LINUX_KERNEL
16 #define HPI_OS_LINUX_KERNEL
17 
18 #define HPI_OS_DEFINED
19 #define HPI_BUILD_KERNEL_MODE
20 
21 #include <linux/io.h>
22 #include <linux/ioctl.h>
23 #include <linux/kernel.h>
24 #include <linux/string.h>
25 #include <linux/device.h>
26 #include <linux/firmware.h>
27 #include <linux/interrupt.h>
28 #include <linux/pci.h>
29 #include <linux/mutex.h>
30 
31 #define HPI_NO_OS_FILE_OPS
32 
33 /** Details of a memory area allocated with  pci_alloc_consistent
34 Need all info for parameters to pci_free_consistent
35 */
36 struct consistent_dma_area {
37 	struct device *pdev;
38 	/* looks like dma-mapping dma_devres ?! */
39 	size_t size;
40 	void *vaddr;
41 	dma_addr_t dma_handle;
42 };
43 
hpios_locked_mem_get_phys_addr(struct consistent_dma_area * locked_mem_handle,u32 * p_physical_addr)44 static inline u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area
45 	*locked_mem_handle, u32 *p_physical_addr)
46 {
47 	*p_physical_addr = locked_mem_handle->dma_handle;
48 	return 0;
49 }
50 
hpios_locked_mem_get_virt_addr(struct consistent_dma_area * locked_mem_handle,void ** pp_virtual_addr)51 static inline u16 hpios_locked_mem_get_virt_addr(struct consistent_dma_area
52 	*locked_mem_handle, void **pp_virtual_addr)
53 {
54 	*pp_virtual_addr = locked_mem_handle->vaddr;
55 	return 0;
56 }
57 
hpios_locked_mem_valid(struct consistent_dma_area * locked_mem_handle)58 static inline u16 hpios_locked_mem_valid(struct consistent_dma_area
59 	*locked_mem_handle)
60 {
61 	return locked_mem_handle->size != 0;
62 }
63 
64 struct hpi_ioctl_linux {
65 	void __user *phm;
66 	void __user *phr;
67 };
68 
69 /* Conflict?: H is already used by a number of drivers hid, bluetooth hci,
70    and some sound drivers sb16, hdsp, emu10k. AFAIK 0xFC is unused command
71 */
72 #define HPI_IOCTL_LINUX _IOWR('H', 0xFC, struct hpi_ioctl_linux)
73 
74 #define HPI_DEBUG_FLAG_ERROR   KERN_ERR
75 #define HPI_DEBUG_FLAG_WARNING KERN_WARNING
76 #define HPI_DEBUG_FLAG_NOTICE  KERN_NOTICE
77 #define HPI_DEBUG_FLAG_INFO    KERN_INFO
78 #define HPI_DEBUG_FLAG_DEBUG   KERN_DEBUG
79 #define HPI_DEBUG_FLAG_VERBOSE KERN_DEBUG	/* kernel has no verbose */
80 
81 #include <linux/spinlock.h>
82 
83 #define HPI_LOCKING
84 
85 struct hpios_spinlock {
86 	spinlock_t lock;	/* SEE hpios_spinlock */
87 	int lock_context;
88 };
89 
90 /* The reason for all this evilness is that ALSA calls some of a drivers
91  * operators in atomic context, and some not.  But all our functions channel
92  * through the HPI_Message conduit, so we can't handle the different context
93  * per function
94  */
95 #define IN_LOCK_BH 1
96 #define IN_LOCK_IRQ 0
cond_lock(struct hpios_spinlock * l)97 static inline void cond_lock(struct hpios_spinlock *l)
98 {
99 	if (irqs_disabled()) {
100 		/* NO bh or isr can execute on this processor,
101 		   so ordinary lock will do
102 		 */
103 		spin_lock(&((l)->lock));
104 		l->lock_context = IN_LOCK_IRQ;
105 	} else {
106 		spin_lock_bh(&((l)->lock));
107 		l->lock_context = IN_LOCK_BH;
108 	}
109 }
110 
cond_unlock(struct hpios_spinlock * l)111 static inline void cond_unlock(struct hpios_spinlock *l)
112 {
113 	if (l->lock_context == IN_LOCK_BH)
114 		spin_unlock_bh(&((l)->lock));
115 	else
116 		spin_unlock(&((l)->lock));
117 }
118 
119 #define hpios_msgxlock_init(obj)      spin_lock_init(&(obj)->lock)
120 #define hpios_msgxlock_lock(obj)   cond_lock(obj)
121 #define hpios_msgxlock_unlock(obj) cond_unlock(obj)
122 
123 #define hpios_dsplock_init(obj)       spin_lock_init(&(obj)->dsp_lock.lock)
124 #define hpios_dsplock_lock(obj)    cond_lock(&(obj)->dsp_lock)
125 #define hpios_dsplock_unlock(obj)  cond_unlock(&(obj)->dsp_lock)
126 
127 #ifdef CONFIG_SND_DEBUG
128 #define HPI_BUILD_DEBUG
129 #endif
130 
131 #define HPI_ALIST_LOCKING
132 #define hpios_alistlock_init(obj)    spin_lock_init(&((obj)->list_lock.lock))
133 #define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock))
134 #define hpios_alistlock_unlock(obj) spin_unlock(&((obj)->list_lock.lock))
135 
136 struct snd_card;
137 
138 /** pci drvdata points to an instance of this struct */
139 struct hpi_adapter {
140 	struct hpi_adapter_obj *adapter;
141 	struct snd_card *snd_card;
142 
143 	int irq;
144 	int interrupt_mode;
145 	void (*interrupt_callback) (struct hpi_adapter *);
146 
147 	/* mutex prevents contention for one card
148 	   between multiple user programs (via ioctl) */
149 	struct mutex mutex;
150 	char *p_buffer;
151 	size_t buffer_size;
152 };
153 
154 #endif
155