linux/sound/pci/asihpi/hpimsgx.c
<<
>>
Prefs
   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