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