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