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 19Extended 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 29static struct pci_device_id asihpi_pci_tbl[] = { 30#include "hpipcida.h" 31}; 32 33static struct hpios_spinlock msgx_lock; 34 35static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS]; 36 37static 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 67static 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 87static void adapter_open(struct hpi_message *phm, struct hpi_response *phr); 88static void adapter_close(struct hpi_message *phm, struct hpi_response *phr); 89 90static void mixer_open(struct hpi_message *phm, struct hpi_response *phr); 91static void mixer_close(struct hpi_message *phm, struct hpi_response *phr); 92 93static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, 94 void *h_owner); 95static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, 96 void *h_owner); 97static void instream_open(struct hpi_message *phm, struct hpi_response *phr, 98 void *h_owner); 99static void instream_close(struct hpi_message *phm, struct hpi_response *phr, 100 void *h_owner); 101 102static void HPIMSGX__reset(u16 adapter_index); 103static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr); 104static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner); 105 106#ifndef DISABLE_PRAGMA_PACK1 107#pragma pack(push, 1) 108#endif 109 110struct hpi_subsys_response { 111 struct hpi_response_header h; 112 struct hpi_subsys_res s; 113}; 114 115struct hpi_adapter_response { 116 struct hpi_response_header h; 117 struct hpi_adapter_res a; 118}; 119 120struct hpi_mixer_response { 121 struct hpi_response_header h; 122 struct hpi_mixer_res m; 123}; 124 125struct hpi_stream_response { 126 struct hpi_response_header h; 127 struct hpi_stream_res d; 128}; 129 130struct adapter_info { 131 u16 type; 132 u16 num_instreams; 133 u16 num_outstreams; 134}; 135 136struct 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 */ 146static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS]; 147 148static struct hpi_stream_response 149 rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 150 151static struct hpi_stream_response 152 rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 153 154static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS]; 155 156static struct hpi_subsys_response gRESP_HPI_SUBSYS_FIND_ADAPTERS; 157 158static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS]; 159 160/* use these to keep track of opens from user mode apps/DLLs */ 161static struct asi_open_state 162 outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 163 164static struct asi_open_state 165 instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 166 167static 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 290static 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 306static 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 321static 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 343static 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 */ 368void 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 (phr->error >= HPI_ERROR_BACKEND_BASE) { 413 void *ep = NULL; 414 char *ep_name; 415 416 HPI_DEBUG_MESSAGE(ERROR, phm); 417 418 if (phm->adapter_index < HPI_MAX_ADAPTERS) 419 ep = hpi_entry_points[phm->adapter_index]; 420 421 /* Don't need this? Have adapter index in debug info 422 Know at driver load time index->backend mapping */ 423 if (ep == HPI_6000) 424 ep_name = "HPI_6000"; 425 else if (ep == HPI_6205) 426 ep_name = "HPI_6205"; 427 else 428 ep_name = "unknown"; 429 430 HPI_DEBUG_LOG(ERROR, "HPI %s response - error# %d\n", ep_name, 431 phr->error); 432 433 if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) 434 hpi_debug_data((u16 *)phm, 435 sizeof(*phm) / sizeof(u16)); 436 } 437} 438 439static void adapter_open(struct hpi_message *phm, struct hpi_response *phr) 440{ 441 HPI_DEBUG_LOG(VERBOSE, "adapter_open\n"); 442 memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index], 443 sizeof(rESP_HPI_ADAPTER_OPEN[0])); 444} 445 446static void adapter_close(struct hpi_message *phm, struct hpi_response *phr) 447{ 448 HPI_DEBUG_LOG(VERBOSE, "adapter_close\n"); 449 hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0); 450} 451 452static void mixer_open(struct hpi_message *phm, struct hpi_response *phr) 453{ 454 memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index], 455 sizeof(rESP_HPI_MIXER_OPEN[0])); 456} 457 458static void mixer_close(struct hpi_message *phm, struct hpi_response *phr) 459{ 460 hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0); 461} 462 463static void instream_open(struct hpi_message *phm, struct hpi_response *phr, 464 void *h_owner) 465{ 466 467 struct hpi_message hm; 468 struct hpi_response hr; 469 470 hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0); 471 472 hpios_msgxlock_lock(&msgx_lock); 473 474 if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag) 475 phr->error = HPI_ERROR_OBJ_ALREADY_OPEN; 476 else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index] 477 [phm->obj_index].h.error) 478 memcpy(phr, 479 &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm-> 480 obj_index], 481 sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 482 else { 483 instream_user_open[phm->adapter_index][phm-> 484 obj_index].open_flag = 1; 485 hpios_msgxlock_un_lock(&msgx_lock); 486 487 /* issue a reset */ 488 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 489 HPI_ISTREAM_RESET); 490 hm.adapter_index = phm->adapter_index; 491 hm.obj_index = phm->obj_index; 492 hw_entry_point(&hm, &hr); 493 494 hpios_msgxlock_lock(&msgx_lock); 495 if (hr.error) { 496 instream_user_open[phm->adapter_index][phm-> 497 obj_index].open_flag = 0; 498 phr->error = hr.error; 499 } else { 500 instream_user_open[phm->adapter_index][phm-> 501 obj_index].open_flag = 1; 502 instream_user_open[phm->adapter_index][phm-> 503 obj_index].h_owner = h_owner; 504 memcpy(phr, 505 &rESP_HPI_ISTREAM_OPEN[phm->adapter_index] 506 [phm->obj_index], 507 sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 508 } 509 } 510 hpios_msgxlock_un_lock(&msgx_lock); 511} 512 513static void instream_close(struct hpi_message *phm, struct hpi_response *phr, 514 void *h_owner) 515{ 516 517 struct hpi_message hm; 518 struct hpi_response hr; 519 520 hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0); 521 522 hpios_msgxlock_lock(&msgx_lock); 523 if (h_owner == 524 instream_user_open[phm->adapter_index][phm-> 525 obj_index].h_owner) { 526 /* HPI_DEBUG_LOG(INFO,"closing adapter %d " 527 "instream %d owned by %p\n", 528 phm->wAdapterIndex, phm->wObjIndex, hOwner); */ 529 instream_user_open[phm->adapter_index][phm-> 530 obj_index].h_owner = NULL; 531 hpios_msgxlock_un_lock(&msgx_lock); 532 /* issue a reset */ 533 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 534 HPI_ISTREAM_RESET); 535 hm.adapter_index = phm->adapter_index; 536 hm.obj_index = phm->obj_index; 537 hw_entry_point(&hm, &hr); 538 hpios_msgxlock_lock(&msgx_lock); 539 if (hr.error) { 540 instream_user_open[phm->adapter_index][phm-> 541 obj_index].h_owner = h_owner; 542 phr->error = hr.error; 543 } else { 544 instream_user_open[phm->adapter_index][phm-> 545 obj_index].open_flag = 0; 546 instream_user_open[phm->adapter_index][phm-> 547 obj_index].h_owner = NULL; 548 } 549 } else { 550 HPI_DEBUG_LOG(WARNING, 551 "%p trying to close %d instream %d owned by %p\n", 552 h_owner, phm->adapter_index, phm->obj_index, 553 instream_user_open[phm->adapter_index][phm-> 554 obj_index].h_owner); 555 phr->error = HPI_ERROR_OBJ_NOT_OPEN; 556 } 557 hpios_msgxlock_un_lock(&msgx_lock); 558} 559 560static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, 561 void *h_owner) 562{ 563 564 struct hpi_message hm; 565 struct hpi_response hr; 566 567 hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0); 568 569 hpios_msgxlock_lock(&msgx_lock); 570 571 if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag) 572 phr->error = HPI_ERROR_OBJ_ALREADY_OPEN; 573 else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index] 574 [phm->obj_index].h.error) 575 memcpy(phr, 576 &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm-> 577 obj_index], 578 sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 579 else { 580 outstream_user_open[phm->adapter_index][phm-> 581 obj_index].open_flag = 1; 582 hpios_msgxlock_un_lock(&msgx_lock); 583 584 /* issue a reset */ 585 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 586 HPI_OSTREAM_RESET); 587 hm.adapter_index = phm->adapter_index; 588 hm.obj_index = phm->obj_index; 589 hw_entry_point(&hm, &hr); 590 591 hpios_msgxlock_lock(&msgx_lock); 592 if (hr.error) { 593 outstream_user_open[phm->adapter_index][phm-> 594 obj_index].open_flag = 0; 595 phr->error = hr.error; 596 } else { 597 outstream_user_open[phm->adapter_index][phm-> 598 obj_index].open_flag = 1; 599 outstream_user_open[phm->adapter_index][phm-> 600 obj_index].h_owner = h_owner; 601 memcpy(phr, 602 &rESP_HPI_OSTREAM_OPEN[phm->adapter_index] 603 [phm->obj_index], 604 sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 605 } 606 } 607 hpios_msgxlock_un_lock(&msgx_lock); 608} 609 610static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, 611 void *h_owner) 612{ 613 614 struct hpi_message hm; 615 struct hpi_response hr; 616 617 hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0); 618 619 hpios_msgxlock_lock(&msgx_lock); 620 621 if (h_owner == 622 outstream_user_open[phm->adapter_index][phm-> 623 obj_index].h_owner) { 624 /* HPI_DEBUG_LOG(INFO,"closing adapter %d " 625 "outstream %d owned by %p\n", 626 phm->wAdapterIndex, phm->wObjIndex, hOwner); */ 627 outstream_user_open[phm->adapter_index][phm-> 628 obj_index].h_owner = NULL; 629 hpios_msgxlock_un_lock(&msgx_lock); 630 /* issue a reset */ 631 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 632 HPI_OSTREAM_RESET); 633 hm.adapter_index = phm->adapter_index; 634 hm.obj_index = phm->obj_index; 635 hw_entry_point(&hm, &hr); 636 hpios_msgxlock_lock(&msgx_lock); 637 if (hr.error) { 638 outstream_user_open[phm->adapter_index][phm-> 639 obj_index].h_owner = h_owner; 640 phr->error = hr.error; 641 } else { 642 outstream_user_open[phm->adapter_index][phm-> 643 obj_index].open_flag = 0; 644 outstream_user_open[phm->adapter_index][phm-> 645 obj_index].h_owner = NULL; 646 } 647 } else { 648 HPI_DEBUG_LOG(WARNING, 649 "%p trying to close %d outstream %d owned by %p\n", 650 h_owner, phm->adapter_index, phm->obj_index, 651 outstream_user_open[phm->adapter_index][phm-> 652 obj_index].h_owner); 653 phr->error = HPI_ERROR_OBJ_NOT_OPEN; 654 } 655 hpios_msgxlock_un_lock(&msgx_lock); 656} 657 658static u16 adapter_prepare(u16 adapter) 659{ 660 struct hpi_message hm; 661 struct hpi_response hr; 662 663 /* Open the adapter and streams */ 664 u16 i; 665 666 /* call to HPI_ADAPTER_OPEN */ 667 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 668 HPI_ADAPTER_OPEN); 669 hm.adapter_index = adapter; 670 hw_entry_point(&hm, &hr); 671 memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr, 672 sizeof(rESP_HPI_ADAPTER_OPEN[0])); 673 if (hr.error) 674 return hr.error; 675 676 /* call to HPI_ADAPTER_GET_INFO */ 677 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 678 HPI_ADAPTER_GET_INFO); 679 hm.adapter_index = adapter; 680 hw_entry_point(&hm, &hr); 681 if (hr.error) 682 return hr.error; 683 684 aDAPTER_INFO[adapter].num_outstreams = hr.u.a.num_outstreams; 685 aDAPTER_INFO[adapter].num_instreams = hr.u.a.num_instreams; 686 aDAPTER_INFO[adapter].type = hr.u.a.adapter_type; 687 688 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list[adapter] = 689 hr.u.a.adapter_type; 690 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters++; 691 if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters > HPI_MAX_ADAPTERS) 692 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters = 693 HPI_MAX_ADAPTERS; 694 695 /* call to HPI_OSTREAM_OPEN */ 696 for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) { 697 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 698 HPI_OSTREAM_OPEN); 699 hm.adapter_index = adapter; 700 hm.obj_index = i; 701 hw_entry_point(&hm, &hr); 702 memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr, 703 sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 704 outstream_user_open[adapter][i].open_flag = 0; 705 outstream_user_open[adapter][i].h_owner = NULL; 706 } 707 708 /* call to HPI_ISTREAM_OPEN */ 709 for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) { 710 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 711 HPI_ISTREAM_OPEN); 712 hm.adapter_index = adapter; 713 hm.obj_index = i; 714 hw_entry_point(&hm, &hr); 715 memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr, 716 sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 717 instream_user_open[adapter][i].open_flag = 0; 718 instream_user_open[adapter][i].h_owner = NULL; 719 } 720 721 /* call to HPI_MIXER_OPEN */ 722 hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN); 723 hm.adapter_index = adapter; 724 hw_entry_point(&hm, &hr); 725 memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, 726 sizeof(rESP_HPI_MIXER_OPEN[0])); 727 728 return gRESP_HPI_SUBSYS_FIND_ADAPTERS.h.error; 729} 730 731static void HPIMSGX__reset(u16 adapter_index) 732{ 733 int i; 734 u16 adapter; 735 struct hpi_response hr; 736 737 if (adapter_index == HPIMSGX_ALLADAPTERS) { 738 /* reset all responses to contain errors */ 739 hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, 740 HPI_SUBSYS_FIND_ADAPTERS, 0); 741 memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr, 742 sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS)); 743 744 for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) { 745 746 hpi_init_response(&hr, HPI_OBJ_ADAPTER, 747 HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER); 748 memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr, 749 sizeof(rESP_HPI_ADAPTER_OPEN[adapter])); 750 751 hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN, 752 HPI_ERROR_INVALID_OBJ); 753 memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, 754 sizeof(rESP_HPI_MIXER_OPEN[adapter])); 755 756 for (i = 0; i < HPI_MAX_STREAMS; i++) { 757 hpi_init_response(&hr, HPI_OBJ_OSTREAM, 758 HPI_OSTREAM_OPEN, 759 HPI_ERROR_INVALID_OBJ); 760 memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], 761 &hr, 762 sizeof(rESP_HPI_OSTREAM_OPEN[adapter] 763 [i])); 764 hpi_init_response(&hr, HPI_OBJ_ISTREAM, 765 HPI_ISTREAM_OPEN, 766 HPI_ERROR_INVALID_OBJ); 767 memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], 768 &hr, 769 sizeof(rESP_HPI_ISTREAM_OPEN[adapter] 770 [i])); 771 } 772 } 773 } else if (adapter_index < HPI_MAX_ADAPTERS) { 774 rESP_HPI_ADAPTER_OPEN[adapter_index].h.error = 775 HPI_ERROR_BAD_ADAPTER; 776 rESP_HPI_MIXER_OPEN[adapter_index].h.error = 777 HPI_ERROR_INVALID_OBJ; 778 for (i = 0; i < HPI_MAX_STREAMS; i++) { 779 rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error = 780 HPI_ERROR_INVALID_OBJ; 781 rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error = 782 HPI_ERROR_INVALID_OBJ; 783 } 784 if (gRESP_HPI_SUBSYS_FIND_ADAPTERS. 785 s.aw_adapter_list[adapter_index]) { 786 gRESP_HPI_SUBSYS_FIND_ADAPTERS. 787 s.aw_adapter_list[adapter_index] = 0; 788 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters--; 789 } 790 } 791} 792 793static u16 HPIMSGX__init(struct hpi_message *phm, 794 /* HPI_SUBSYS_CREATE_ADAPTER structure with */ 795 /* resource list or NULL=find all */ 796 struct hpi_response *phr 797 /* response from HPI_ADAPTER_GET_INFO */ 798 ) 799{ 800 hpi_handler_func *entry_point_func; 801 struct hpi_response hr; 802 803 if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters >= HPI_MAX_ADAPTERS) 804 return HPI_ERROR_BAD_ADAPTER_NUMBER; 805 806 /* Init response here so we can pass in previous adapter list */ 807 hpi_init_response(&hr, phm->object, phm->function, 808 HPI_ERROR_INVALID_OBJ); 809 memcpy(hr.u.s.aw_adapter_list, 810 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list, 811 sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list)); 812 813 entry_point_func = 814 hpi_lookup_entry_point_function(phm->u.s.resource.r.pci); 815 816 if (entry_point_func) { 817 HPI_DEBUG_MESSAGE(DEBUG, phm); 818 entry_point_func(phm, &hr); 819 } else { 820 phr->error = HPI_ERROR_PROCESSING_MESSAGE; 821 return phr->error; 822 } 823 if (hr.error == 0) { 824 /* the adapter was created succesfully 825 save the mapping for future use */ 826 hpi_entry_points[hr.u.s.adapter_index] = entry_point_func; 827 /* prepare adapter (pre-open streams etc.) */ 828 HPI_DEBUG_LOG(DEBUG, 829 "HPI_SUBSYS_CREATE_ADAPTER successful," 830 " preparing adapter\n"); 831 adapter_prepare(hr.u.s.adapter_index); 832 } 833 memcpy(phr, &hr, hr.size); 834 return phr->error; 835} 836 837static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner) 838{ 839 int i, adapter, adapter_limit; 840 841 if (!h_owner) 842 return; 843 844 if (adapter_index == HPIMSGX_ALLADAPTERS) { 845 adapter = 0; 846 adapter_limit = HPI_MAX_ADAPTERS; 847 } else { 848 adapter = adapter_index; 849 adapter_limit = adapter + 1; 850 } 851 852 for (; adapter < adapter_limit; adapter++) { 853 /* printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */ 854 for (i = 0; i < HPI_MAX_STREAMS; i++) { 855 if (h_owner == 856 outstream_user_open[adapter][i].h_owner) { 857 struct hpi_message hm; 858 struct hpi_response hr; 859 860 HPI_DEBUG_LOG(DEBUG, 861 "close adapter %d ostream %d\n", 862 adapter, i); 863 864 hpi_init_message_response(&hm, &hr, 865 HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET); 866 hm.adapter_index = (u16)adapter; 867 hm.obj_index = (u16)i; 868 hw_entry_point(&hm, &hr); 869 870 hm.function = HPI_OSTREAM_HOSTBUFFER_FREE; 871 hw_entry_point(&hm, &hr); 872 873 hm.function = HPI_OSTREAM_GROUP_RESET; 874 hw_entry_point(&hm, &hr); 875 876 outstream_user_open[adapter][i].open_flag = 0; 877 outstream_user_open[adapter][i].h_owner = 878 NULL; 879 } 880 if (h_owner == instream_user_open[adapter][i].h_owner) { 881 struct hpi_message hm; 882 struct hpi_response hr; 883 884 HPI_DEBUG_LOG(DEBUG, 885 "close adapter %d istream %d\n", 886 adapter, i); 887 888 hpi_init_message_response(&hm, &hr, 889 HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET); 890 hm.adapter_index = (u16)adapter; 891 hm.obj_index = (u16)i; 892 hw_entry_point(&hm, &hr); 893 894 hm.function = HPI_ISTREAM_HOSTBUFFER_FREE; 895 hw_entry_point(&hm, &hr); 896 897 hm.function = HPI_ISTREAM_GROUP_RESET; 898 hw_entry_point(&hm, &hr); 899 900 instream_user_open[adapter][i].open_flag = 0; 901 instream_user_open[adapter][i].h_owner = NULL; 902 } 903 } 904 } 905} 906