diff options
Diffstat (limited to 'sound/pci/asihpi/hpioctl.c')
-rw-r--r-- | sound/pci/asihpi/hpioctl.c | 147 |
1 files changed, 74 insertions, 73 deletions
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index 62895a719fcb..d8e7047512f8 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c | |||
@@ -25,11 +25,13 @@ Common Linux HPI ioctl and module probe/remove functions | |||
25 | #include "hpidebug.h" | 25 | #include "hpidebug.h" |
26 | #include "hpimsgx.h" | 26 | #include "hpimsgx.h" |
27 | #include "hpioctl.h" | 27 | #include "hpioctl.h" |
28 | #include "hpicmn.h" | ||
28 | 29 | ||
29 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
31 | #include <linux/moduleparam.h> | 32 | #include <linux/moduleparam.h> |
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
34 | #include <linux/pci.h> | ||
33 | #include <linux/stringify.h> | 35 | #include <linux/stringify.h> |
34 | 36 | ||
35 | #ifdef MODULE_FIRMWARE | 37 | #ifdef MODULE_FIRMWARE |
@@ -45,7 +47,7 @@ MODULE_FIRMWARE("asihpi/dsp8900.bin"); | |||
45 | static int prealloc_stream_buf; | 47 | static int prealloc_stream_buf; |
46 | module_param(prealloc_stream_buf, int, S_IRUGO); | 48 | module_param(prealloc_stream_buf, int, S_IRUGO); |
47 | MODULE_PARM_DESC(prealloc_stream_buf, | 49 | MODULE_PARM_DESC(prealloc_stream_buf, |
48 | "preallocate size for per-adapter stream buffer"); | 50 | "Preallocate size for per-adapter stream buffer"); |
49 | 51 | ||
50 | /* Allow the debug level to be changed after module load. | 52 | /* Allow the debug level to be changed after module load. |
51 | E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel | 53 | E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel |
@@ -121,8 +123,8 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
121 | phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg; | 123 | phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg; |
122 | 124 | ||
123 | /* Read the message and response pointers from user space. */ | 125 | /* Read the message and response pointers from user space. */ |
124 | if (get_user(puhm, &phpi_ioctl_data->phm) || | 126 | if (get_user(puhm, &phpi_ioctl_data->phm) |
125 | get_user(puhr, &phpi_ioctl_data->phr)) { | 127 | || get_user(puhr, &phpi_ioctl_data->phr)) { |
126 | err = -EFAULT; | 128 | err = -EFAULT; |
127 | goto out; | 129 | goto out; |
128 | } | 130 | } |
@@ -135,7 +137,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
135 | if (hm->h.size > sizeof(*hm)) | 137 | if (hm->h.size > sizeof(*hm)) |
136 | hm->h.size = sizeof(*hm); | 138 | hm->h.size = sizeof(*hm); |
137 | 139 | ||
138 | /*printk(KERN_INFO "message size %d\n", hm->h.wSize); */ | 140 | /* printk(KERN_INFO "message size %d\n", hm->h.wSize); */ |
139 | 141 | ||
140 | uncopied_bytes = copy_from_user(hm, puhm, hm->h.size); | 142 | uncopied_bytes = copy_from_user(hm, puhm, hm->h.size); |
141 | if (uncopied_bytes) { | 143 | if (uncopied_bytes) { |
@@ -155,26 +157,29 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
155 | goto out; | 157 | goto out; |
156 | } | 158 | } |
157 | 159 | ||
158 | pa = &adapters[hm->h.adapter_index]; | 160 | if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) { |
159 | hr->h.size = 0; | 161 | err = -EINVAL; |
160 | if (hm->h.object == HPI_OBJ_SUBSYSTEM) { | 162 | goto out; |
161 | switch (hm->h.function) { | 163 | } |
162 | case HPI_SUBSYS_CREATE_ADAPTER: | ||
163 | case HPI_SUBSYS_DELETE_ADAPTER: | ||
164 | /* Application must not use these functions! */ | ||
165 | hr->h.size = sizeof(hr->h); | ||
166 | hr->h.error = HPI_ERROR_INVALID_OPERATION; | ||
167 | hr->h.function = hm->h.function; | ||
168 | uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); | ||
169 | if (uncopied_bytes) | ||
170 | err = -EFAULT; | ||
171 | else | ||
172 | err = 0; | ||
173 | goto out; | ||
174 | 164 | ||
175 | default: | 165 | switch (hm->h.function) { |
176 | hpi_send_recv_f(&hm->m0, &hr->r0, file); | 166 | case HPI_SUBSYS_CREATE_ADAPTER: |
177 | } | 167 | case HPI_ADAPTER_DELETE: |
168 | /* Application must not use these functions! */ | ||
169 | hr->h.size = sizeof(hr->h); | ||
170 | hr->h.error = HPI_ERROR_INVALID_OPERATION; | ||
171 | hr->h.function = hm->h.function; | ||
172 | uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); | ||
173 | if (uncopied_bytes) | ||
174 | err = -EFAULT; | ||
175 | else | ||
176 | err = 0; | ||
177 | goto out; | ||
178 | } | ||
179 | |||
180 | hr->h.size = res_max_size; | ||
181 | if (hm->h.object == HPI_OBJ_SUBSYSTEM) { | ||
182 | hpi_send_recv_f(&hm->m0, &hr->r0, file); | ||
178 | } else { | 183 | } else { |
179 | u16 __user *ptr = NULL; | 184 | u16 __user *ptr = NULL; |
180 | u32 size = 0; | 185 | u32 size = 0; |
@@ -182,8 +187,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
182 | /* -1=no data 0=read from user mem, 1=write to user mem */ | 187 | /* -1=no data 0=read from user mem, 1=write to user mem */ |
183 | int wrflag = -1; | 188 | int wrflag = -1; |
184 | u32 adapter = hm->h.adapter_index; | 189 | u32 adapter = hm->h.adapter_index; |
190 | pa = &adapters[adapter]; | ||
185 | 191 | ||
186 | if ((hm->h.adapter_index > HPI_MAX_ADAPTERS) || (!pa->type)) { | 192 | if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) { |
187 | hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER, | 193 | hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER, |
188 | HPI_ADAPTER_OPEN, | 194 | HPI_ADAPTER_OPEN, |
189 | HPI_ERROR_BAD_ADAPTER_NUMBER); | 195 | HPI_ERROR_BAD_ADAPTER_NUMBER); |
@@ -216,7 +222,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
216 | */ | 222 | */ |
217 | if (pa->buffer_size < size) { | 223 | if (pa->buffer_size < size) { |
218 | HPI_DEBUG_LOG(DEBUG, | 224 | HPI_DEBUG_LOG(DEBUG, |
219 | "realloc adapter %d stream " | 225 | "Realloc adapter %d stream " |
220 | "buffer from %zd to %d\n", | 226 | "buffer from %zd to %d\n", |
221 | hm->h.adapter_index, | 227 | hm->h.adapter_index, |
222 | pa->buffer_size, size); | 228 | pa->buffer_size, size); |
@@ -259,7 +265,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
259 | copy_from_user(pa->p_buffer, ptr, size); | 265 | copy_from_user(pa->p_buffer, ptr, size); |
260 | if (uncopied_bytes) | 266 | if (uncopied_bytes) |
261 | HPI_DEBUG_LOG(WARNING, | 267 | HPI_DEBUG_LOG(WARNING, |
262 | "missed %d of %d " | 268 | "Missed %d of %d " |
263 | "bytes from user\n", uncopied_bytes, | 269 | "bytes from user\n", uncopied_bytes, |
264 | size); | 270 | size); |
265 | } | 271 | } |
@@ -271,7 +277,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
271 | copy_to_user(ptr, pa->p_buffer, size); | 277 | copy_to_user(ptr, pa->p_buffer, size); |
272 | if (uncopied_bytes) | 278 | if (uncopied_bytes) |
273 | HPI_DEBUG_LOG(WARNING, | 279 | HPI_DEBUG_LOG(WARNING, |
274 | "missed %d of %d " "bytes to user\n", | 280 | "Missed %d of %d " "bytes to user\n", |
275 | uncopied_bytes, size); | 281 | uncopied_bytes, size); |
276 | } | 282 | } |
277 | 283 | ||
@@ -290,9 +296,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
290 | if (hr->h.size > res_max_size) { | 296 | if (hr->h.size > res_max_size) { |
291 | HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size, | 297 | HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size, |
292 | res_max_size); | 298 | res_max_size); |
293 | /*HPI_DEBUG_MESSAGE(ERROR, hm); */ | 299 | hr->h.error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; |
294 | err = -EFAULT; | 300 | hr->h.specific_error = hr->h.size; |
295 | goto out; | 301 | hr->h.size = sizeof(hr->h); |
296 | } | 302 | } |
297 | 303 | ||
298 | uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); | 304 | uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); |
@@ -311,7 +317,7 @@ out: | |||
311 | int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | 317 | int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, |
312 | const struct pci_device_id *pci_id) | 318 | const struct pci_device_id *pci_id) |
313 | { | 319 | { |
314 | int err, idx, nm; | 320 | int idx, nm; |
315 | unsigned int memlen; | 321 | unsigned int memlen; |
316 | struct hpi_message hm; | 322 | struct hpi_message hm; |
317 | struct hpi_response hr; | 323 | struct hpi_response hr; |
@@ -320,28 +326,33 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
320 | 326 | ||
321 | memset(&adapter, 0, sizeof(adapter)); | 327 | memset(&adapter, 0, sizeof(adapter)); |
322 | 328 | ||
323 | printk(KERN_DEBUG "probe PCI device (%04x:%04x,%04x:%04x,%04x)\n", | 329 | dev_printk(KERN_DEBUG, &pci_dev->dev, |
324 | pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor, | 330 | "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor, |
331 | pci_dev->device, pci_dev->subsystem_vendor, | ||
325 | pci_dev->subsystem_device, pci_dev->devfn); | 332 | pci_dev->subsystem_device, pci_dev->devfn); |
326 | 333 | ||
334 | if (pci_enable_device(pci_dev) < 0) { | ||
335 | dev_printk(KERN_ERR, &pci_dev->dev, | ||
336 | "pci_enable_device failed, disabling device\n"); | ||
337 | return -EIO; | ||
338 | } | ||
339 | |||
340 | pci_set_master(pci_dev); /* also sets latency timer if < 16 */ | ||
341 | |||
327 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | 342 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, |
328 | HPI_SUBSYS_CREATE_ADAPTER); | 343 | HPI_SUBSYS_CREATE_ADAPTER); |
329 | hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, | 344 | hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, |
330 | HPI_ERROR_PROCESSING_MESSAGE); | 345 | HPI_ERROR_PROCESSING_MESSAGE); |
331 | 346 | ||
332 | hm.adapter_index = -1; /* an invalid index */ | 347 | hm.adapter_index = HPI_ADAPTER_INDEX_INVALID; |
333 | 348 | ||
334 | /* fill in HPI_PCI information from kernel provided information */ | ||
335 | adapter.pci = pci_dev; | 349 | adapter.pci = pci_dev; |
336 | 350 | ||
337 | nm = HPI_MAX_ADAPTER_MEM_SPACES; | 351 | nm = HPI_MAX_ADAPTER_MEM_SPACES; |
338 | 352 | ||
339 | for (idx = 0; idx < nm; idx++) { | 353 | for (idx = 0; idx < nm; idx++) { |
340 | HPI_DEBUG_LOG(INFO, "resource %d %s %08llx-%08llx %04llx\n", | 354 | HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx, |
341 | idx, pci_dev->resource[idx].name, | 355 | &pci_dev->resource[idx]); |
342 | (unsigned long long)pci_resource_start(pci_dev, idx), | ||
343 | (unsigned long long)pci_resource_end(pci_dev, idx), | ||
344 | (unsigned long long)pci_resource_flags(pci_dev, idx)); | ||
345 | 356 | ||
346 | if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { | 357 | if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { |
347 | memlen = pci_resource_len(pci_dev, idx); | 358 | memlen = pci_resource_len(pci_dev, idx); |
@@ -359,19 +370,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
359 | pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx]; | 370 | pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx]; |
360 | } | 371 | } |
361 | 372 | ||
362 | /* could replace Pci with direct pointer to pci_dev for linux | 373 | pci.pci_dev = pci_dev; |
363 | Instead wrap accessor functions for IDs etc. | ||
364 | Would it work for windows? | ||
365 | */ | ||
366 | pci.bus_number = pci_dev->bus->number; | ||
367 | pci.vendor_id = (u16)pci_dev->vendor; | ||
368 | pci.device_id = (u16)pci_dev->device; | ||
369 | pci.subsys_vendor_id = (u16)(pci_dev->subsystem_vendor & 0xffff); | ||
370 | pci.subsys_device_id = (u16)(pci_dev->subsystem_device & 0xffff); | ||
371 | pci.device_number = pci_dev->devfn; | ||
372 | pci.interrupt = pci_dev->irq; | ||
373 | pci.p_os_data = pci_dev; | ||
374 | |||
375 | hm.u.s.resource.bus_type = HPI_BUS_PCI; | 374 | hm.u.s.resource.bus_type = HPI_BUS_PCI; |
376 | hm.u.s.resource.r.pci = &pci; | 375 | hm.u.s.resource.r.pci = &pci; |
377 | 376 | ||
@@ -392,23 +391,27 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
392 | } | 391 | } |
393 | 392 | ||
394 | adapter.index = hr.u.s.adapter_index; | 393 | adapter.index = hr.u.s.adapter_index; |
395 | adapter.type = hr.u.s.aw_adapter_list[adapter.index]; | 394 | adapter.type = hr.u.s.adapter_type; |
395 | |||
396 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
397 | HPI_ADAPTER_OPEN); | ||
396 | hm.adapter_index = adapter.index; | 398 | hm.adapter_index = adapter.index; |
399 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); | ||
397 | 400 | ||
398 | err = hpi_adapter_open(NULL, adapter.index); | 401 | if (hr.error) |
399 | if (err) | ||
400 | goto err; | 402 | goto err; |
401 | 403 | ||
402 | adapter.snd_card_asihpi = NULL; | 404 | adapter.snd_card_asihpi = NULL; |
403 | /* WARNING can't init mutex in 'adapter' | 405 | /* WARNING can't init mutex in 'adapter' |
404 | * and then copy it to adapters[] ?!?! | 406 | * and then copy it to adapters[] ?!?! |
405 | */ | 407 | */ |
406 | adapters[hr.u.s.adapter_index] = adapter; | 408 | adapters[adapter.index] = adapter; |
407 | mutex_init(&adapters[adapter.index].mutex); | 409 | mutex_init(&adapters[adapter.index].mutex); |
408 | pci_set_drvdata(pci_dev, &adapters[adapter.index]); | 410 | pci_set_drvdata(pci_dev, &adapters[adapter.index]); |
409 | 411 | ||
410 | printk(KERN_INFO "probe found adapter ASI%04X HPI index #%d.\n", | 412 | dev_printk(KERN_INFO, &pci_dev->dev, |
411 | adapter.type, adapter.index); | 413 | "probe succeeded for ASI%04X HPI index %d\n", adapter.type, |
414 | adapter.index); | ||
412 | 415 | ||
413 | return 0; | 416 | return 0; |
414 | 417 | ||
@@ -435,10 +438,10 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) | |||
435 | struct hpi_message hm; | 438 | struct hpi_message hm; |
436 | struct hpi_response hr; | 439 | struct hpi_response hr; |
437 | struct hpi_adapter *pa; | 440 | struct hpi_adapter *pa; |
438 | pa = (struct hpi_adapter *)pci_get_drvdata(pci_dev); | 441 | pa = pci_get_drvdata(pci_dev); |
439 | 442 | ||
440 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | 443 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, |
441 | HPI_SUBSYS_DELETE_ADAPTER); | 444 | HPI_ADAPTER_DELETE); |
442 | hm.adapter_index = pa->index; | 445 | hm.adapter_index = pa->index; |
443 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); | 446 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); |
444 | 447 | ||
@@ -450,20 +453,18 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) | |||
450 | } | 453 | } |
451 | } | 454 | } |
452 | 455 | ||
453 | if (pa->p_buffer) { | 456 | if (pa->p_buffer) |
454 | pa->buffer_size = 0; | ||
455 | vfree(pa->p_buffer); | 457 | vfree(pa->p_buffer); |
456 | } | ||
457 | 458 | ||
458 | pci_set_drvdata(pci_dev, NULL); | 459 | pci_set_drvdata(pci_dev, NULL); |
459 | /* | 460 | if (1) |
460 | printk(KERN_INFO "PCI device (%04x:%04x,%04x:%04x,%04x)," | 461 | dev_printk(KERN_INFO, &pci_dev->dev, |
461 | " HPI index # %d, removed.\n", | 462 | "remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n", |
462 | pci_dev->vendor, pci_dev->device, | 463 | pci_dev->vendor, pci_dev->device, |
463 | pci_dev->subsystem_vendor, | 464 | pci_dev->subsystem_vendor, pci_dev->subsystem_device, |
464 | pci_dev->subsystem_device, pci_dev->devfn, | 465 | pci_dev->devfn, pa->index); |
465 | pa->index); | 466 | |
466 | */ | 467 | memset(pa, 0, sizeof(*pa)); |
467 | } | 468 | } |
468 | 469 | ||
469 | void __init asihpi_init(void) | 470 | void __init asihpi_init(void) |