1 /******************************************************************************* 2 3 AudioScience HPI driver 4 Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of version 2 of the GNU General Public License as 8 published by the Free Software Foundation; 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 Common Linux HPI ioctl and module probe/remove functions 20 *******************************************************************************/ 21 #define SOURCEFILE_NAME "hpioctl.c" 22 23 #include "hpi_internal.h" 24 #include "hpi_version.h" 25 #include "hpimsginit.h" 26 #include "hpidebug.h" 27 #include "hpimsgx.h" 28 #include "hpioctl.h" 29 #include "hpicmn.h" 30 31 #include <linux/fs.h> 32 #include <linux/slab.h> 33 #include <linux/moduleparam.h> 34 #include <asm/uaccess.h> 35 #include <linux/pci.h> 36 #include <linux/stringify.h> 37 #include <linux/module.h> 38 39 #ifdef MODULE_FIRMWARE 40 MODULE_FIRMWARE("asihpi/dsp5000.bin"); 41 MODULE_FIRMWARE("asihpi/dsp6200.bin"); 42 MODULE_FIRMWARE("asihpi/dsp6205.bin"); 43 MODULE_FIRMWARE("asihpi/dsp6400.bin"); 44 MODULE_FIRMWARE("asihpi/dsp6600.bin"); 45 MODULE_FIRMWARE("asihpi/dsp8700.bin"); 46 MODULE_FIRMWARE("asihpi/dsp8900.bin"); 47 #endif 48 49 static int prealloc_stream_buf; 50 module_param(prealloc_stream_buf, int, S_IRUGO); 51 MODULE_PARM_DESC(prealloc_stream_buf, 52 "Preallocate size for per-adapter stream buffer"); 53 54 /* Allow the debug level to be changed after module load. 55 E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel 56 */ 57 module_param(hpi_debug_level, int, S_IRUGO | S_IWUSR); 58 MODULE_PARM_DESC(hpi_debug_level, "debug verbosity 0..5"); 59 60 /* List of adapters found */ 61 static struct hpi_adapter adapters[HPI_MAX_ADAPTERS]; 62 63 /* Wrapper function to HPI_Message to enable dumping of the 64 message and response types. 65 */ 66 static void hpi_send_recv_f(struct hpi_message *phm, struct hpi_response *phr, 67 struct file *file) 68 { 69 if ((phm->adapter_index >= HPI_MAX_ADAPTERS) 70 && (phm->object != HPI_OBJ_SUBSYSTEM)) 71 phr->error = HPI_ERROR_INVALID_OBJ_INDEX; 72 else 73 hpi_send_recv_ex(phm, phr, file); 74 } 75 76 /* This is called from hpifunc.c functions, called by ALSA 77 * (or other kernel process) In this case there is no file descriptor 78 * available for the message cache code 79 */ 80 void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr) 81 { 82 hpi_send_recv_f(phm, phr, HOWNER_KERNEL); 83 } 84 85 EXPORT_SYMBOL(hpi_send_recv); 86 /* for radio-asihpi */ 87 88 int asihpi_hpi_release(struct file *file) 89 { 90 struct hpi_message hm; 91 struct hpi_response hr; 92 93 /* HPI_DEBUG_LOG(INFO,"hpi_release file %p, pid %d\n", file, current->pid); */ 94 /* close the subsystem just in case the application forgot to. */ 95 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, 96 HPI_SUBSYS_CLOSE); 97 hpi_send_recv_ex(&hm, &hr, file); 98 return 0; 99 } 100 101 long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 102 { 103 struct hpi_ioctl_linux __user *phpi_ioctl_data; 104 void __user *puhm; 105 void __user *puhr; 106 union hpi_message_buffer_v1 *hm; 107 union hpi_response_buffer_v1 *hr; 108 u16 res_max_size; 109 u32 uncopied_bytes; 110 int err = 0; 111 112 if (cmd != HPI_IOCTL_LINUX) 113 return -EINVAL; 114 115 hm = kmalloc(sizeof(*hm), GFP_KERNEL); 116 hr = kmalloc(sizeof(*hr), GFP_KERNEL); 117 if (!hm || !hr) { 118 err = -ENOMEM; 119 goto out; 120 } 121 122 phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg; 123 124 /* Read the message and response pointers from user space. */ 125 if (get_user(puhm, &phpi_ioctl_data->phm) 126 || get_user(puhr, &phpi_ioctl_data->phr)) { 127 err = -EFAULT; 128 goto out; 129 } 130 131 /* Now read the message size and data from user space. */ 132 if (get_user(hm->h.size, (u16 __user *)puhm)) { 133 err = -EFAULT; 134 goto out; 135 } 136 if (hm->h.size > sizeof(*hm)) 137 hm->h.size = sizeof(*hm); 138 139 /* printk(KERN_INFO "message size %d\n", hm->h.wSize); */ 140 141 uncopied_bytes = copy_from_user(hm, puhm, hm->h.size); 142 if (uncopied_bytes) { 143 HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes); 144 err = -EFAULT; 145 goto out; 146 } 147 148 if (get_user(res_max_size, (u16 __user *)puhr)) { 149 err = -EFAULT; 150 goto out; 151 } 152 /* printk(KERN_INFO "user response size %d\n", res_max_size); */ 153 if (res_max_size < sizeof(struct hpi_response_header)) { 154 HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size); 155 err = -EFAULT; 156 goto out; 157 } 158 159 switch (hm->h.function) { 160 case HPI_SUBSYS_CREATE_ADAPTER: 161 case HPI_ADAPTER_DELETE: 162 /* Application must not use these functions! */ 163 hr->h.size = sizeof(hr->h); 164 hr->h.error = HPI_ERROR_INVALID_OPERATION; 165 hr->h.function = hm->h.function; 166 uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); 167 if (uncopied_bytes) 168 err = -EFAULT; 169 else 170 err = 0; 171 goto out; 172 } 173 174 hr->h.size = res_max_size; 175 if (hm->h.object == HPI_OBJ_SUBSYSTEM) { 176 hpi_send_recv_f(&hm->m0, &hr->r0, file); 177 } else { 178 u16 __user *ptr = NULL; 179 u32 size = 0; 180 /* -1=no data 0=read from user mem, 1=write to user mem */ 181 int wrflag = -1; 182 struct hpi_adapter *pa = NULL; 183 184 if (hm->h.adapter_index < ARRAY_SIZE(adapters)) 185 pa = &adapters[hm->h.adapter_index]; 186 187 if (!pa || !pa->adapter || !pa->adapter->type) { 188 hpi_init_response(&hr->r0, hm->h.object, 189 hm->h.function, HPI_ERROR_BAD_ADAPTER_NUMBER); 190 191 uncopied_bytes = 192 copy_to_user(puhr, hr, sizeof(hr->h)); 193 if (uncopied_bytes) 194 err = -EFAULT; 195 else 196 err = 0; 197 goto out; 198 } 199 200 if (mutex_lock_interruptible(&pa->mutex)) { 201 err = -EINTR; 202 goto out; 203 } 204 205 /* Dig out any pointers embedded in the message. */ 206 switch (hm->h.function) { 207 case HPI_OSTREAM_WRITE: 208 case HPI_ISTREAM_READ:{ 209 /* Yes, sparse, this is correct. */ 210 ptr = (u16 __user *)hm->m0.u.d.u.data.pb_data; 211 size = hm->m0.u.d.u.data.data_size; 212 213 /* Allocate buffer according to application request. 214 ?Is it better to alloc/free for the duration 215 of the transaction? 216 */ 217 if (pa->buffer_size < size) { 218 HPI_DEBUG_LOG(DEBUG, 219 "Realloc adapter %d stream " 220 "buffer from %zd to %d\n", 221 hm->h.adapter_index, 222 pa->buffer_size, size); 223 if (pa->p_buffer) { 224 pa->buffer_size = 0; 225 vfree(pa->p_buffer); 226 } 227 pa->p_buffer = vmalloc(size); 228 if (pa->p_buffer) 229 pa->buffer_size = size; 230 else { 231 HPI_DEBUG_LOG(ERROR, 232 "HPI could not allocate " 233 "stream buffer size %d\n", 234 size); 235 236 mutex_unlock(&pa->mutex); 237 err = -EINVAL; 238 goto out; 239 } 240 } 241 242 hm->m0.u.d.u.data.pb_data = pa->p_buffer; 243 if (hm->h.function == HPI_ISTREAM_READ) 244 /* from card, WRITE to user mem */ 245 wrflag = 1; 246 else 247 wrflag = 0; 248 break; 249 } 250 251 default: 252 size = 0; 253 break; 254 } 255 256 if (size && (wrflag == 0)) { 257 uncopied_bytes = 258 copy_from_user(pa->p_buffer, ptr, size); 259 if (uncopied_bytes) 260 HPI_DEBUG_LOG(WARNING, 261 "Missed %d of %d " 262 "bytes from user\n", uncopied_bytes, 263 size); 264 } 265 266 hpi_send_recv_f(&hm->m0, &hr->r0, file); 267 268 if (size && (wrflag == 1)) { 269 uncopied_bytes = 270 copy_to_user(ptr, pa->p_buffer, size); 271 if (uncopied_bytes) 272 HPI_DEBUG_LOG(WARNING, 273 "Missed %d of %d " "bytes to user\n", 274 uncopied_bytes, size); 275 } 276 277 mutex_unlock(&pa->mutex); 278 } 279 280 /* on return response size must be set */ 281 /*printk(KERN_INFO "response size %d\n", hr->h.wSize); */ 282 283 if (!hr->h.size) { 284 HPI_DEBUG_LOG(ERROR, "response zero size\n"); 285 err = -EFAULT; 286 goto out; 287 } 288 289 if (hr->h.size > res_max_size) { 290 HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size, 291 res_max_size); 292 hr->h.error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; 293 hr->h.specific_error = hr->h.size; 294 hr->h.size = sizeof(hr->h); 295 } 296 297 uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); 298 if (uncopied_bytes) { 299 HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes); 300 err = -EFAULT; 301 goto out; 302 } 303 304 out: 305 kfree(hm); 306 kfree(hr); 307 return err; 308 } 309 310 int asihpi_adapter_probe(struct pci_dev *pci_dev, 311 const struct pci_device_id *pci_id) 312 { 313 int idx, nm; 314 int adapter_index; 315 unsigned int memlen; 316 struct hpi_message hm; 317 struct hpi_response hr; 318 struct hpi_adapter adapter; 319 struct hpi_pci pci; 320 321 memset(&adapter, 0, sizeof(adapter)); 322 323 dev_printk(KERN_DEBUG, &pci_dev->dev, 324 "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor, 325 pci_dev->device, pci_dev->subsystem_vendor, 326 pci_dev->subsystem_device, pci_dev->devfn); 327 328 if (pci_enable_device(pci_dev) < 0) { 329 dev_err(&pci_dev->dev, 330 "pci_enable_device failed, disabling device\n"); 331 return -EIO; 332 } 333 334 pci_set_master(pci_dev); /* also sets latency timer if < 16 */ 335 336 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, 337 HPI_SUBSYS_CREATE_ADAPTER); 338 hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, 339 HPI_ERROR_PROCESSING_MESSAGE); 340 341 hm.adapter_index = HPI_ADAPTER_INDEX_INVALID; 342 343 nm = HPI_MAX_ADAPTER_MEM_SPACES; 344 345 for (idx = 0; idx < nm; idx++) { 346 HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx, 347 &pci_dev->resource[idx]); 348 349 if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { 350 memlen = pci_resource_len(pci_dev, idx); 351 pci.ap_mem_base[idx] = 352 ioremap(pci_resource_start(pci_dev, idx), 353 memlen); 354 if (!pci.ap_mem_base[idx]) { 355 HPI_DEBUG_LOG(ERROR, 356 "ioremap failed, aborting\n"); 357 /* unmap previously mapped pci mem space */ 358 goto err; 359 } 360 } 361 } 362 363 pci.pci_dev = pci_dev; 364 hm.u.s.resource.bus_type = HPI_BUS_PCI; 365 hm.u.s.resource.r.pci = &pci; 366 367 /* call CreateAdapterObject on the relevant hpi module */ 368 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); 369 if (hr.error) 370 goto err; 371 372 adapter_index = hr.u.s.adapter_index; 373 adapter.adapter = hpi_find_adapter(adapter_index); 374 375 if (prealloc_stream_buf) { 376 adapter.p_buffer = vmalloc(prealloc_stream_buf); 377 if (!adapter.p_buffer) { 378 HPI_DEBUG_LOG(ERROR, 379 "HPI could not allocate " 380 "kernel buffer size %d\n", 381 prealloc_stream_buf); 382 goto err; 383 } 384 } 385 386 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 387 HPI_ADAPTER_OPEN); 388 hm.adapter_index = adapter.adapter->index; 389 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); 390 391 if (hr.error) 392 goto err; 393 394 /* WARNING can't init mutex in 'adapter' 395 * and then copy it to adapters[] ?!?! 396 */ 397 adapters[adapter_index] = adapter; 398 mutex_init(&adapters[adapter_index].mutex); 399 pci_set_drvdata(pci_dev, &adapters[adapter_index]); 400 401 dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n", 402 adapter.adapter->type, adapter_index); 403 404 return 0; 405 406 err: 407 for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) { 408 if (pci.ap_mem_base[idx]) { 409 iounmap(pci.ap_mem_base[idx]); 410 pci.ap_mem_base[idx] = NULL; 411 } 412 } 413 414 if (adapter.p_buffer) { 415 adapter.buffer_size = 0; 416 vfree(adapter.p_buffer); 417 } 418 419 HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n"); 420 return -ENODEV; 421 } 422 423 void asihpi_adapter_remove(struct pci_dev *pci_dev) 424 { 425 int idx; 426 struct hpi_message hm; 427 struct hpi_response hr; 428 struct hpi_adapter *pa; 429 struct hpi_pci pci; 430 431 pa = pci_get_drvdata(pci_dev); 432 pci = pa->adapter->pci; 433 434 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 435 HPI_ADAPTER_DELETE); 436 hm.adapter_index = pa->adapter->index; 437 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); 438 439 /* unmap PCI memory space, mapped during device init. */ 440 for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) { 441 if (pci.ap_mem_base[idx]) 442 iounmap(pci.ap_mem_base[idx]); 443 } 444 445 if (pa->p_buffer) 446 vfree(pa->p_buffer); 447 448 if (1) 449 dev_info(&pci_dev->dev, 450 "remove %04x:%04x,%04x:%04x,%04x, HPI index %d\n", 451 pci_dev->vendor, pci_dev->device, 452 pci_dev->subsystem_vendor, pci_dev->subsystem_device, 453 pci_dev->devfn, pa->adapter->index); 454 455 memset(pa, 0, sizeof(*pa)); 456 } 457 458 void __init asihpi_init(void) 459 { 460 struct hpi_message hm; 461 struct hpi_response hr; 462 463 memset(adapters, 0, sizeof(adapters)); 464 465 printk(KERN_INFO "ASIHPI driver " HPI_VER_STRING "\n"); 466 467 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, 468 HPI_SUBSYS_DRIVER_LOAD); 469 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); 470 } 471 472 void asihpi_exit(void) 473 { 474 struct hpi_message hm; 475 struct hpi_response hr; 476 477 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, 478 HPI_SUBSYS_DRIVER_UNLOAD); 479 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); 480 } 481