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