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