1 /****************************************************************************** 2 3 AudioScience HPI driver 4 Copyright (C) 1997-2010 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 Extended Message Function With Response Cacheing 20 21 (C) Copyright AudioScience Inc. 2002 22 *****************************************************************************/ 23 #define SOURCEFILE_NAME "hpimsgx.c" 24 #include "hpi_internal.h" 25 #include "hpimsginit.h" 26 #include "hpicmn.h" 27 #include "hpimsgx.h" 28 #include "hpidebug.h" 29 30 static struct pci_device_id asihpi_pci_tbl[] = { 31 #include "hpipcida.h" 32 }; 33 34 static struct hpios_spinlock msgx_lock; 35 36 static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS]; 37 38 static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci 39 *pci_info) 40 { 41 42 int i; 43 44 for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) { 45 if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID 46 && asihpi_pci_tbl[i].vendor != 47 pci_info->pci_dev->vendor) 48 continue; 49 if (asihpi_pci_tbl[i].device != PCI_ANY_ID 50 && asihpi_pci_tbl[i].device != 51 pci_info->pci_dev->device) 52 continue; 53 if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID 54 && asihpi_pci_tbl[i].subvendor != 55 pci_info->pci_dev->subsystem_vendor) 56 continue; 57 if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID 58 && asihpi_pci_tbl[i].subdevice != 59 pci_info->pci_dev->subsystem_device) 60 continue; 61 62 /* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i, 63 asihpi_pci_tbl[i].driver_data); */ 64 return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data; 65 } 66 67 return NULL; 68 } 69 70 static inline void hw_entry_point(struct hpi_message *phm, 71 struct hpi_response *phr) 72 { 73 if ((phm->adapter_index < HPI_MAX_ADAPTERS) 74 && hpi_entry_points[phm->adapter_index]) 75 hpi_entry_points[phm->adapter_index] (phm, phr); 76 else 77 hpi_init_response(phr, phm->object, phm->function, 78 HPI_ERROR_PROCESSING_MESSAGE); 79 } 80 81 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr); 82 static void adapter_close(struct hpi_message *phm, struct hpi_response *phr); 83 84 static void mixer_open(struct hpi_message *phm, struct hpi_response *phr); 85 static void mixer_close(struct hpi_message *phm, struct hpi_response *phr); 86 87 static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, 88 void *h_owner); 89 static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, 90 void *h_owner); 91 static void instream_open(struct hpi_message *phm, struct hpi_response *phr, 92 void *h_owner); 93 static void instream_close(struct hpi_message *phm, struct hpi_response *phr, 94 void *h_owner); 95 96 static void HPIMSGX__reset(u16 adapter_index); 97 98 static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr); 99 static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner); 100 101 #ifndef DISABLE_PRAGMA_PACK1 102 #pragma pack(push, 1) 103 #endif 104 105 struct hpi_subsys_response { 106 struct hpi_response_header h; 107 struct hpi_subsys_res s; 108 }; 109 110 struct hpi_adapter_response { 111 struct hpi_response_header h; 112 struct hpi_adapter_res a; 113 }; 114 115 struct hpi_mixer_response { 116 struct hpi_response_header h; 117 struct hpi_mixer_res m; 118 }; 119 120 struct hpi_stream_response { 121 struct hpi_response_header h; 122 struct hpi_stream_res d; 123 }; 124 125 struct adapter_info { 126 u16 type; 127 u16 num_instreams; 128 u16 num_outstreams; 129 }; 130 131 struct asi_open_state { 132 int open_flag; 133 void *h_owner; 134 }; 135 136 #ifndef DISABLE_PRAGMA_PACK1 137 #pragma pack(pop) 138 #endif 139 140 /* Globals */ 141 static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS]; 142 143 static struct hpi_stream_response 144 rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 145 146 static struct hpi_stream_response 147 rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 148 149 static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS]; 150 151 static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS]; 152 153 /* use these to keep track of opens from user mode apps/DLLs */ 154 static struct asi_open_state 155 outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 156 157 static struct asi_open_state 158 instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 159 160 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, 161 void *h_owner) 162 { 163 if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID) 164 HPI_DEBUG_LOG(WARNING, 165 "suspicious adapter index %d in subsys message 0x%x.\n", 166 phm->adapter_index, phm->function); 167 168 switch (phm->function) { 169 case HPI_SUBSYS_GET_VERSION: 170 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, 171 HPI_SUBSYS_GET_VERSION, 0); 172 phr->u.s.version = HPI_VER >> 8; /* return major.minor */ 173 phr->u.s.data = HPI_VER; /* return major.minor.release */ 174 break; 175 case HPI_SUBSYS_OPEN: 176 /*do not propagate the message down the chain */ 177 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0); 178 break; 179 case HPI_SUBSYS_CLOSE: 180 /*do not propagate the message down the chain */ 181 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE, 182 0); 183 HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner); 184 break; 185 case HPI_SUBSYS_DRIVER_LOAD: 186 /* Initialize this module's internal state */ 187 hpios_msgxlock_init(&msgx_lock); 188 memset(&hpi_entry_points, 0, sizeof(hpi_entry_points)); 189 hpios_locked_mem_init(); 190 /* Init subsys_findadapters response to no-adapters */ 191 HPIMSGX__reset(HPIMSGX_ALLADAPTERS); 192 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, 193 HPI_SUBSYS_DRIVER_LOAD, 0); 194 /* individual HPIs dont implement driver load */ 195 HPI_COMMON(phm, phr); 196 break; 197 case HPI_SUBSYS_DRIVER_UNLOAD: 198 HPI_COMMON(phm, phr); 199 HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner); 200 hpios_locked_mem_free_all(); 201 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, 202 HPI_SUBSYS_DRIVER_UNLOAD, 0); 203 return; 204 205 case HPI_SUBSYS_GET_NUM_ADAPTERS: 206 case HPI_SUBSYS_GET_ADAPTER: 207 HPI_COMMON(phm, phr); 208 break; 209 210 case HPI_SUBSYS_CREATE_ADAPTER: 211 HPIMSGX__init(phm, phr); 212 break; 213 214 case HPI_SUBSYS_DELETE_ADAPTER: 215 HPIMSGX__cleanup(phm->obj_index, h_owner); 216 { 217 struct hpi_message hm; 218 struct hpi_response hr; 219 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 220 HPI_ADAPTER_CLOSE); 221 hm.adapter_index = phm->obj_index; 222 hw_entry_point(&hm, &hr); 223 } 224 if ((phm->obj_index < HPI_MAX_ADAPTERS) 225 && hpi_entry_points[phm->obj_index]) { 226 hpi_entry_points[phm->obj_index] (phm, phr); 227 hpi_entry_points[phm->obj_index] = NULL; 228 } else 229 phr->error = HPI_ERROR_INVALID_OBJ_INDEX; 230 231 break; 232 default: 233 /* Must explicitly handle every subsys message in this switch */ 234 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 235 HPI_ERROR_INVALID_FUNC); 236 break; 237 } 238 } 239 240 static void adapter_message(struct hpi_message *phm, struct hpi_response *phr, 241 void *h_owner) 242 { 243 switch (phm->function) { 244 case HPI_ADAPTER_OPEN: 245 adapter_open(phm, phr); 246 break; 247 case HPI_ADAPTER_CLOSE: 248 adapter_close(phm, phr); 249 break; 250 default: 251 hw_entry_point(phm, phr); 252 break; 253 } 254 } 255 256 static void mixer_message(struct hpi_message *phm, struct hpi_response *phr) 257 { 258 switch (phm->function) { 259 case HPI_MIXER_OPEN: 260 mixer_open(phm, phr); 261 break; 262 case HPI_MIXER_CLOSE: 263 mixer_close(phm, phr); 264 break; 265 default: 266 hw_entry_point(phm, phr); 267 break; 268 } 269 } 270 271 static void outstream_message(struct hpi_message *phm, 272 struct hpi_response *phr, void *h_owner) 273 { 274 if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) { 275 hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function, 276 HPI_ERROR_INVALID_OBJ_INDEX); 277 return; 278 } 279 280 switch (phm->function) { 281 case HPI_OSTREAM_OPEN: 282 outstream_open(phm, phr, h_owner); 283 break; 284 case HPI_OSTREAM_CLOSE: 285 outstream_close(phm, phr, h_owner); 286 break; 287 default: 288 hw_entry_point(phm, phr); 289 break; 290 } 291 } 292 293 static void instream_message(struct hpi_message *phm, 294 struct hpi_response *phr, void *h_owner) 295 { 296 if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) { 297 hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function, 298 HPI_ERROR_INVALID_OBJ_INDEX); 299 return; 300 } 301 302 switch (phm->function) { 303 case HPI_ISTREAM_OPEN: 304 instream_open(phm, phr, h_owner); 305 break; 306 case HPI_ISTREAM_CLOSE: 307 instream_close(phm, phr, h_owner); 308 break; 309 default: 310 hw_entry_point(phm, phr); 311 break; 312 } 313 } 314 315 /* NOTE: HPI_Message() must be defined in the driver as a wrapper for 316 * HPI_MessageEx so that functions in hpifunc.c compile. 317 */ 318 void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr, 319 void *h_owner) 320 { 321 HPI_DEBUG_MESSAGE(DEBUG, phm); 322 323 if (phm->type != HPI_TYPE_MESSAGE) { 324 hpi_init_response(phr, phm->object, phm->function, 325 HPI_ERROR_INVALID_TYPE); 326 return; 327 } 328 329 if (phm->adapter_index >= HPI_MAX_ADAPTERS 330 && phm->adapter_index != HPIMSGX_ALLADAPTERS) { 331 hpi_init_response(phr, phm->object, phm->function, 332 HPI_ERROR_BAD_ADAPTER_NUMBER); 333 return; 334 } 335 336 switch (phm->object) { 337 case HPI_OBJ_SUBSYSTEM: 338 subsys_message(phm, phr, h_owner); 339 break; 340 341 case HPI_OBJ_ADAPTER: 342 adapter_message(phm, phr, h_owner); 343 break; 344 345 case HPI_OBJ_MIXER: 346 mixer_message(phm, phr); 347 break; 348 349 case HPI_OBJ_OSTREAM: 350 outstream_message(phm, phr, h_owner); 351 break; 352 353 case HPI_OBJ_ISTREAM: 354 instream_message(phm, phr, h_owner); 355 break; 356 357 default: 358 hw_entry_point(phm, phr); 359 break; 360 } 361 HPI_DEBUG_RESPONSE(phr); 362 363 } 364 365 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr) 366 { 367 HPI_DEBUG_LOG(VERBOSE, "adapter_open\n"); 368 memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index], 369 sizeof(rESP_HPI_ADAPTER_OPEN[0])); 370 } 371 372 static void adapter_close(struct hpi_message *phm, struct hpi_response *phr) 373 { 374 HPI_DEBUG_LOG(VERBOSE, "adapter_close\n"); 375 hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0); 376 } 377 378 static void mixer_open(struct hpi_message *phm, struct hpi_response *phr) 379 { 380 memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index], 381 sizeof(rESP_HPI_MIXER_OPEN[0])); 382 } 383 384 static void mixer_close(struct hpi_message *phm, struct hpi_response *phr) 385 { 386 hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0); 387 } 388 389 static void instream_open(struct hpi_message *phm, struct hpi_response *phr, 390 void *h_owner) 391 { 392 393 struct hpi_message hm; 394 struct hpi_response hr; 395 396 hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0); 397 398 hpios_msgxlock_lock(&msgx_lock); 399 400 if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag) 401 phr->error = HPI_ERROR_OBJ_ALREADY_OPEN; 402 else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index] 403 [phm->obj_index].h.error) 404 memcpy(phr, 405 &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm-> 406 obj_index], 407 sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 408 else { 409 instream_user_open[phm->adapter_index][phm-> 410 obj_index].open_flag = 1; 411 hpios_msgxlock_unlock(&msgx_lock); 412 413 /* issue a reset */ 414 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 415 HPI_ISTREAM_RESET); 416 hm.adapter_index = phm->adapter_index; 417 hm.obj_index = phm->obj_index; 418 hw_entry_point(&hm, &hr); 419 420 hpios_msgxlock_lock(&msgx_lock); 421 if (hr.error) { 422 instream_user_open[phm->adapter_index][phm-> 423 obj_index].open_flag = 0; 424 phr->error = hr.error; 425 } else { 426 instream_user_open[phm->adapter_index][phm-> 427 obj_index].open_flag = 1; 428 instream_user_open[phm->adapter_index][phm-> 429 obj_index].h_owner = h_owner; 430 memcpy(phr, 431 &rESP_HPI_ISTREAM_OPEN[phm->adapter_index] 432 [phm->obj_index], 433 sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 434 } 435 } 436 hpios_msgxlock_unlock(&msgx_lock); 437 } 438 439 static void instream_close(struct hpi_message *phm, struct hpi_response *phr, 440 void *h_owner) 441 { 442 443 struct hpi_message hm; 444 struct hpi_response hr; 445 446 hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0); 447 448 hpios_msgxlock_lock(&msgx_lock); 449 if (h_owner == 450 instream_user_open[phm->adapter_index][phm-> 451 obj_index].h_owner) { 452 /* HPI_DEBUG_LOG(INFO,"closing adapter %d " 453 "instream %d owned by %p\n", 454 phm->wAdapterIndex, phm->wObjIndex, hOwner); */ 455 instream_user_open[phm->adapter_index][phm-> 456 obj_index].h_owner = NULL; 457 hpios_msgxlock_unlock(&msgx_lock); 458 /* issue a reset */ 459 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 460 HPI_ISTREAM_RESET); 461 hm.adapter_index = phm->adapter_index; 462 hm.obj_index = phm->obj_index; 463 hw_entry_point(&hm, &hr); 464 hpios_msgxlock_lock(&msgx_lock); 465 if (hr.error) { 466 instream_user_open[phm->adapter_index][phm-> 467 obj_index].h_owner = h_owner; 468 phr->error = hr.error; 469 } else { 470 instream_user_open[phm->adapter_index][phm-> 471 obj_index].open_flag = 0; 472 instream_user_open[phm->adapter_index][phm-> 473 obj_index].h_owner = NULL; 474 } 475 } else { 476 HPI_DEBUG_LOG(WARNING, 477 "%p trying to close %d instream %d owned by %p\n", 478 h_owner, phm->adapter_index, phm->obj_index, 479 instream_user_open[phm->adapter_index][phm-> 480 obj_index].h_owner); 481 phr->error = HPI_ERROR_OBJ_NOT_OPEN; 482 } 483 hpios_msgxlock_unlock(&msgx_lock); 484 } 485 486 static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, 487 void *h_owner) 488 { 489 490 struct hpi_message hm; 491 struct hpi_response hr; 492 493 hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0); 494 495 hpios_msgxlock_lock(&msgx_lock); 496 497 if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag) 498 phr->error = HPI_ERROR_OBJ_ALREADY_OPEN; 499 else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index] 500 [phm->obj_index].h.error) 501 memcpy(phr, 502 &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm-> 503 obj_index], 504 sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 505 else { 506 outstream_user_open[phm->adapter_index][phm-> 507 obj_index].open_flag = 1; 508 hpios_msgxlock_unlock(&msgx_lock); 509 510 /* issue a reset */ 511 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 512 HPI_OSTREAM_RESET); 513 hm.adapter_index = phm->adapter_index; 514 hm.obj_index = phm->obj_index; 515 hw_entry_point(&hm, &hr); 516 517 hpios_msgxlock_lock(&msgx_lock); 518 if (hr.error) { 519 outstream_user_open[phm->adapter_index][phm-> 520 obj_index].open_flag = 0; 521 phr->error = hr.error; 522 } else { 523 outstream_user_open[phm->adapter_index][phm-> 524 obj_index].open_flag = 1; 525 outstream_user_open[phm->adapter_index][phm-> 526 obj_index].h_owner = h_owner; 527 memcpy(phr, 528 &rESP_HPI_OSTREAM_OPEN[phm->adapter_index] 529 [phm->obj_index], 530 sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 531 } 532 } 533 hpios_msgxlock_unlock(&msgx_lock); 534 } 535 536 static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, 537 void *h_owner) 538 { 539 540 struct hpi_message hm; 541 struct hpi_response hr; 542 543 hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0); 544 545 hpios_msgxlock_lock(&msgx_lock); 546 547 if (h_owner == 548 outstream_user_open[phm->adapter_index][phm-> 549 obj_index].h_owner) { 550 /* HPI_DEBUG_LOG(INFO,"closing adapter %d " 551 "outstream %d owned by %p\n", 552 phm->wAdapterIndex, phm->wObjIndex, hOwner); */ 553 outstream_user_open[phm->adapter_index][phm-> 554 obj_index].h_owner = NULL; 555 hpios_msgxlock_unlock(&msgx_lock); 556 /* issue a reset */ 557 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 558 HPI_OSTREAM_RESET); 559 hm.adapter_index = phm->adapter_index; 560 hm.obj_index = phm->obj_index; 561 hw_entry_point(&hm, &hr); 562 hpios_msgxlock_lock(&msgx_lock); 563 if (hr.error) { 564 outstream_user_open[phm->adapter_index][phm-> 565 obj_index].h_owner = h_owner; 566 phr->error = hr.error; 567 } else { 568 outstream_user_open[phm->adapter_index][phm-> 569 obj_index].open_flag = 0; 570 outstream_user_open[phm->adapter_index][phm-> 571 obj_index].h_owner = NULL; 572 } 573 } else { 574 HPI_DEBUG_LOG(WARNING, 575 "%p trying to close %d outstream %d owned by %p\n", 576 h_owner, phm->adapter_index, phm->obj_index, 577 outstream_user_open[phm->adapter_index][phm-> 578 obj_index].h_owner); 579 phr->error = HPI_ERROR_OBJ_NOT_OPEN; 580 } 581 hpios_msgxlock_unlock(&msgx_lock); 582 } 583 584 static u16 adapter_prepare(u16 adapter) 585 { 586 struct hpi_message hm; 587 struct hpi_response hr; 588 589 /* Open the adapter and streams */ 590 u16 i; 591 592 /* call to HPI_ADAPTER_OPEN */ 593 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 594 HPI_ADAPTER_OPEN); 595 hm.adapter_index = adapter; 596 hw_entry_point(&hm, &hr); 597 memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr, 598 sizeof(rESP_HPI_ADAPTER_OPEN[0])); 599 if (hr.error) 600 return hr.error; 601 602 /* call to HPI_ADAPTER_GET_INFO */ 603 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 604 HPI_ADAPTER_GET_INFO); 605 hm.adapter_index = adapter; 606 hw_entry_point(&hm, &hr); 607 if (hr.error) 608 return hr.error; 609 610 aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams; 611 aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams; 612 aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type; 613 614 /* call to HPI_OSTREAM_OPEN */ 615 for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) { 616 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 617 HPI_OSTREAM_OPEN); 618 hm.adapter_index = adapter; 619 hm.obj_index = i; 620 hw_entry_point(&hm, &hr); 621 memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr, 622 sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 623 outstream_user_open[adapter][i].open_flag = 0; 624 outstream_user_open[adapter][i].h_owner = NULL; 625 } 626 627 /* call to HPI_ISTREAM_OPEN */ 628 for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) { 629 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 630 HPI_ISTREAM_OPEN); 631 hm.adapter_index = adapter; 632 hm.obj_index = i; 633 hw_entry_point(&hm, &hr); 634 memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr, 635 sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 636 instream_user_open[adapter][i].open_flag = 0; 637 instream_user_open[adapter][i].h_owner = NULL; 638 } 639 640 /* call to HPI_MIXER_OPEN */ 641 hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN); 642 hm.adapter_index = adapter; 643 hw_entry_point(&hm, &hr); 644 memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, 645 sizeof(rESP_HPI_MIXER_OPEN[0])); 646 647 return 0; 648 } 649 650 static void HPIMSGX__reset(u16 adapter_index) 651 { 652 int i; 653 u16 adapter; 654 struct hpi_response hr; 655 656 if (adapter_index == HPIMSGX_ALLADAPTERS) { 657 for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) { 658 659 hpi_init_response(&hr, HPI_OBJ_ADAPTER, 660 HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER); 661 memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr, 662 sizeof(rESP_HPI_ADAPTER_OPEN[adapter])); 663 664 hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN, 665 HPI_ERROR_INVALID_OBJ); 666 memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, 667 sizeof(rESP_HPI_MIXER_OPEN[adapter])); 668 669 for (i = 0; i < HPI_MAX_STREAMS; i++) { 670 hpi_init_response(&hr, HPI_OBJ_OSTREAM, 671 HPI_OSTREAM_OPEN, 672 HPI_ERROR_INVALID_OBJ); 673 memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], 674 &hr, 675 sizeof(rESP_HPI_OSTREAM_OPEN[adapter] 676 [i])); 677 hpi_init_response(&hr, HPI_OBJ_ISTREAM, 678 HPI_ISTREAM_OPEN, 679 HPI_ERROR_INVALID_OBJ); 680 memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], 681 &hr, 682 sizeof(rESP_HPI_ISTREAM_OPEN[adapter] 683 [i])); 684 } 685 } 686 } else if (adapter_index < HPI_MAX_ADAPTERS) { 687 rESP_HPI_ADAPTER_OPEN[adapter_index].h.error = 688 HPI_ERROR_BAD_ADAPTER; 689 rESP_HPI_MIXER_OPEN[adapter_index].h.error = 690 HPI_ERROR_INVALID_OBJ; 691 for (i = 0; i < HPI_MAX_STREAMS; i++) { 692 rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error = 693 HPI_ERROR_INVALID_OBJ; 694 rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error = 695 HPI_ERROR_INVALID_OBJ; 696 } 697 } 698 } 699 700 static u16 HPIMSGX__init(struct hpi_message *phm, 701 /* HPI_SUBSYS_CREATE_ADAPTER structure with */ 702 /* resource list or NULL=find all */ 703 struct hpi_response *phr 704 /* response from HPI_ADAPTER_GET_INFO */ 705 ) 706 { 707 hpi_handler_func *entry_point_func; 708 struct hpi_response hr; 709 710 /* Init response here so we can pass in previous adapter list */ 711 hpi_init_response(&hr, phm->object, phm->function, 712 HPI_ERROR_INVALID_OBJ); 713 714 entry_point_func = 715 hpi_lookup_entry_point_function(phm->u.s.resource.r.pci); 716 717 if (entry_point_func) { 718 HPI_DEBUG_MESSAGE(DEBUG, phm); 719 entry_point_func(phm, &hr); 720 } else { 721 phr->error = HPI_ERROR_PROCESSING_MESSAGE; 722 return phr->error; 723 } 724 if (hr.error == 0) { 725 /* the adapter was created succesfully 726 save the mapping for future use */ 727 hpi_entry_points[hr.u.s.adapter_index] = entry_point_func; 728 /* prepare adapter (pre-open streams etc.) */ 729 HPI_DEBUG_LOG(DEBUG, 730 "HPI_SUBSYS_CREATE_ADAPTER successful," 731 " preparing adapter\n"); 732 adapter_prepare(hr.u.s.adapter_index); 733 } 734 memcpy(phr, &hr, hr.size); 735 return phr->error; 736 } 737 738 static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner) 739 { 740 int i, adapter, adapter_limit; 741 742 if (!h_owner) 743 return; 744 745 if (adapter_index == HPIMSGX_ALLADAPTERS) { 746 adapter = 0; 747 adapter_limit = HPI_MAX_ADAPTERS; 748 } else { 749 adapter = adapter_index; 750 adapter_limit = adapter + 1; 751 } 752 753 for (; adapter < adapter_limit; adapter++) { 754 /* printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */ 755 for (i = 0; i < HPI_MAX_STREAMS; i++) { 756 if (h_owner == 757 outstream_user_open[adapter][i].h_owner) { 758 struct hpi_message hm; 759 struct hpi_response hr; 760 761 HPI_DEBUG_LOG(DEBUG, 762 "Close adapter %d ostream %d\n", 763 adapter, i); 764 765 hpi_init_message_response(&hm, &hr, 766 HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET); 767 hm.adapter_index = (u16)adapter; 768 hm.obj_index = (u16)i; 769 hw_entry_point(&hm, &hr); 770 771 hm.function = HPI_OSTREAM_HOSTBUFFER_FREE; 772 hw_entry_point(&hm, &hr); 773 774 hm.function = HPI_OSTREAM_GROUP_RESET; 775 hw_entry_point(&hm, &hr); 776 777 outstream_user_open[adapter][i].open_flag = 0; 778 outstream_user_open[adapter][i].h_owner = 779 NULL; 780 } 781 if (h_owner == instream_user_open[adapter][i].h_owner) { 782 struct hpi_message hm; 783 struct hpi_response hr; 784 785 HPI_DEBUG_LOG(DEBUG, 786 "Close adapter %d istream %d\n", 787 adapter, i); 788 789 hpi_init_message_response(&hm, &hr, 790 HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET); 791 hm.adapter_index = (u16)adapter; 792 hm.obj_index = (u16)i; 793 hw_entry_point(&hm, &hr); 794 795 hm.function = HPI_ISTREAM_HOSTBUFFER_FREE; 796 hw_entry_point(&hm, &hr); 797 798 hm.function = HPI_ISTREAM_GROUP_RESET; 799 hw_entry_point(&hm, &hr); 800 801 instream_user_open[adapter][i].open_flag = 0; 802 instream_user_open[adapter][i].h_owner = NULL; 803 } 804 } 805 } 806 } 807