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