Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /******************************************************************************
0003 
0004     AudioScience HPI driver
0005     Copyright (C) 1997-2014  AudioScience Inc. <support@audioscience.com>
0006 
0007 
0008 Extended Message Function With Response Caching
0009 
0010 (C) Copyright AudioScience Inc. 2002
0011 *****************************************************************************/
0012 #define SOURCEFILE_NAME "hpimsgx.c"
0013 #include "hpi_internal.h"
0014 #include "hpi_version.h"
0015 #include "hpimsginit.h"
0016 #include "hpicmn.h"
0017 #include "hpimsgx.h"
0018 #include "hpidebug.h"
0019 
0020 static const struct pci_device_id asihpi_pci_tbl[] = {
0021 #include "hpipcida.h"
0022 };
0023 
0024 static struct hpios_spinlock msgx_lock;
0025 
0026 static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
0027 static int logging_enabled = 1;
0028 
0029 static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
0030     *pci_info)
0031 {
0032 
0033     int i;
0034 
0035     for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
0036         if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
0037             && asihpi_pci_tbl[i].vendor !=
0038             pci_info->pci_dev->vendor)
0039             continue;
0040         if (asihpi_pci_tbl[i].device != PCI_ANY_ID
0041             && asihpi_pci_tbl[i].device !=
0042             pci_info->pci_dev->device)
0043             continue;
0044         if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
0045             && asihpi_pci_tbl[i].subvendor !=
0046             pci_info->pci_dev->subsystem_vendor)
0047             continue;
0048         if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
0049             && asihpi_pci_tbl[i].subdevice !=
0050             pci_info->pci_dev->subsystem_device)
0051             continue;
0052 
0053         /* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i,
0054            asihpi_pci_tbl[i].driver_data); */
0055         return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
0056     }
0057 
0058     return NULL;
0059 }
0060 
0061 static inline void hw_entry_point(struct hpi_message *phm,
0062     struct hpi_response *phr)
0063 {
0064     if ((phm->adapter_index < HPI_MAX_ADAPTERS)
0065         && hpi_entry_points[phm->adapter_index])
0066         hpi_entry_points[phm->adapter_index] (phm, phr);
0067     else
0068         hpi_init_response(phr, phm->object, phm->function,
0069             HPI_ERROR_PROCESSING_MESSAGE);
0070 }
0071 
0072 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
0073 static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
0074 
0075 static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
0076 static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
0077 
0078 static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
0079     void *h_owner);
0080 static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
0081     void *h_owner);
0082 static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
0083     void *h_owner);
0084 static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
0085     void *h_owner);
0086 
0087 static void HPIMSGX__reset(u16 adapter_index);
0088 
0089 static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
0090 static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
0091 
0092 #ifndef DISABLE_PRAGMA_PACK1
0093 #pragma pack(push, 1)
0094 #endif
0095 
0096 struct hpi_subsys_response {
0097     struct hpi_response_header h;
0098     struct hpi_subsys_res s;
0099 };
0100 
0101 struct hpi_adapter_response {
0102     struct hpi_response_header h;
0103     struct hpi_adapter_res a;
0104 };
0105 
0106 struct hpi_mixer_response {
0107     struct hpi_response_header h;
0108     struct hpi_mixer_res m;
0109 };
0110 
0111 struct hpi_stream_response {
0112     struct hpi_response_header h;
0113     struct hpi_stream_res d;
0114 };
0115 
0116 struct adapter_info {
0117     u16 type;
0118     u16 num_instreams;
0119     u16 num_outstreams;
0120 };
0121 
0122 struct asi_open_state {
0123     int open_flag;
0124     void *h_owner;
0125 };
0126 
0127 #ifndef DISABLE_PRAGMA_PACK1
0128 #pragma pack(pop)
0129 #endif
0130 
0131 /* Globals */
0132 static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
0133 
0134 static struct hpi_stream_response
0135     rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
0136 
0137 static struct hpi_stream_response
0138     rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
0139 
0140 static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
0141 
0142 static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
0143 
0144 /* use these to keep track of opens from user mode apps/DLLs */
0145 static struct asi_open_state
0146     outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
0147 
0148 static struct asi_open_state
0149     instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
0150 
0151 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
0152     void *h_owner)
0153 {
0154     if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID)
0155         HPI_DEBUG_LOG(WARNING,
0156             "suspicious adapter index %d in subsys message 0x%x.\n",
0157             phm->adapter_index, phm->function);
0158 
0159     switch (phm->function) {
0160     case HPI_SUBSYS_GET_VERSION:
0161         hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
0162             HPI_SUBSYS_GET_VERSION, 0);
0163         phr->u.s.version = HPI_VER >> 8;    /* return major.minor */
0164         phr->u.s.data = HPI_VER;    /* return major.minor.release */
0165         break;
0166     case HPI_SUBSYS_OPEN:
0167         /*do not propagate the message down the chain */
0168         hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0);
0169         break;
0170     case HPI_SUBSYS_CLOSE:
0171         /*do not propagate the message down the chain */
0172         hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE,
0173             0);
0174         HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
0175         break;
0176     case HPI_SUBSYS_DRIVER_LOAD:
0177         /* Initialize this module's internal state */
0178         hpios_msgxlock_init(&msgx_lock);
0179         memset(&hpi_entry_points, 0, sizeof(hpi_entry_points));
0180         /* Init subsys_findadapters response to no-adapters */
0181         HPIMSGX__reset(HPIMSGX_ALLADAPTERS);
0182         hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
0183             HPI_SUBSYS_DRIVER_LOAD, 0);
0184         /* individual HPIs dont implement driver load */
0185         HPI_COMMON(phm, phr);
0186         break;
0187     case HPI_SUBSYS_DRIVER_UNLOAD:
0188         HPI_COMMON(phm, phr);
0189         HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
0190         hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
0191             HPI_SUBSYS_DRIVER_UNLOAD, 0);
0192         return;
0193 
0194     case HPI_SUBSYS_GET_NUM_ADAPTERS:
0195     case HPI_SUBSYS_GET_ADAPTER:
0196         HPI_COMMON(phm, phr);
0197         break;
0198 
0199     case HPI_SUBSYS_CREATE_ADAPTER:
0200         HPIMSGX__init(phm, phr);
0201         break;
0202 
0203     default:
0204         /* Must explicitly handle every subsys message in this switch */
0205         hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
0206             HPI_ERROR_INVALID_FUNC);
0207         break;
0208     }
0209 }
0210 
0211 static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
0212     void *h_owner)
0213 {
0214     switch (phm->function) {
0215     case HPI_ADAPTER_OPEN:
0216         adapter_open(phm, phr);
0217         break;
0218     case HPI_ADAPTER_CLOSE:
0219         adapter_close(phm, phr);
0220         break;
0221     case HPI_ADAPTER_DELETE:
0222         HPIMSGX__cleanup(phm->adapter_index, h_owner);
0223         {
0224             struct hpi_message hm;
0225             struct hpi_response hr;
0226             hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0227                 HPI_ADAPTER_CLOSE);
0228             hm.adapter_index = phm->adapter_index;
0229             hw_entry_point(&hm, &hr);
0230         }
0231         hw_entry_point(phm, phr);
0232         break;
0233 
0234     default:
0235         hw_entry_point(phm, phr);
0236         break;
0237     }
0238 }
0239 
0240 static void mixer_message(struct hpi_message *phm, struct hpi_response *phr)
0241 {
0242     switch (phm->function) {
0243     case HPI_MIXER_OPEN:
0244         mixer_open(phm, phr);
0245         break;
0246     case HPI_MIXER_CLOSE:
0247         mixer_close(phm, phr);
0248         break;
0249     default:
0250         hw_entry_point(phm, phr);
0251         break;
0252     }
0253 }
0254 
0255 static void outstream_message(struct hpi_message *phm,
0256     struct hpi_response *phr, void *h_owner)
0257 {
0258     if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) {
0259         hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function,
0260             HPI_ERROR_INVALID_OBJ_INDEX);
0261         return;
0262     }
0263 
0264     switch (phm->function) {
0265     case HPI_OSTREAM_OPEN:
0266         outstream_open(phm, phr, h_owner);
0267         break;
0268     case HPI_OSTREAM_CLOSE:
0269         outstream_close(phm, phr, h_owner);
0270         break;
0271     default:
0272         hw_entry_point(phm, phr);
0273         break;
0274     }
0275 }
0276 
0277 static void instream_message(struct hpi_message *phm,
0278     struct hpi_response *phr, void *h_owner)
0279 {
0280     if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) {
0281         hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function,
0282             HPI_ERROR_INVALID_OBJ_INDEX);
0283         return;
0284     }
0285 
0286     switch (phm->function) {
0287     case HPI_ISTREAM_OPEN:
0288         instream_open(phm, phr, h_owner);
0289         break;
0290     case HPI_ISTREAM_CLOSE:
0291         instream_close(phm, phr, h_owner);
0292         break;
0293     default:
0294         hw_entry_point(phm, phr);
0295         break;
0296     }
0297 }
0298 
0299 /* NOTE: HPI_Message() must be defined in the driver as a wrapper for
0300  * HPI_MessageEx so that functions in hpifunc.c compile.
0301  */
0302 void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
0303     void *h_owner)
0304 {
0305 
0306     if (logging_enabled)
0307         HPI_DEBUG_MESSAGE(DEBUG, phm);
0308 
0309     if (phm->type != HPI_TYPE_REQUEST) {
0310         hpi_init_response(phr, phm->object, phm->function,
0311             HPI_ERROR_INVALID_TYPE);
0312         return;
0313     }
0314 
0315     if (phm->adapter_index >= HPI_MAX_ADAPTERS
0316         && phm->adapter_index != HPIMSGX_ALLADAPTERS) {
0317         hpi_init_response(phr, phm->object, phm->function,
0318             HPI_ERROR_BAD_ADAPTER_NUMBER);
0319         return;
0320     }
0321 
0322     switch (phm->object) {
0323     case HPI_OBJ_SUBSYSTEM:
0324         subsys_message(phm, phr, h_owner);
0325         break;
0326 
0327     case HPI_OBJ_ADAPTER:
0328         adapter_message(phm, phr, h_owner);
0329         break;
0330 
0331     case HPI_OBJ_MIXER:
0332         mixer_message(phm, phr);
0333         break;
0334 
0335     case HPI_OBJ_OSTREAM:
0336         outstream_message(phm, phr, h_owner);
0337         break;
0338 
0339     case HPI_OBJ_ISTREAM:
0340         instream_message(phm, phr, h_owner);
0341         break;
0342 
0343     default:
0344         hw_entry_point(phm, phr);
0345         break;
0346     }
0347 
0348     if (logging_enabled)
0349         HPI_DEBUG_RESPONSE(phr);
0350 
0351     if (phr->error >= HPI_ERROR_DSP_COMMUNICATION) {
0352         hpi_debug_level_set(HPI_DEBUG_LEVEL_ERROR);
0353         logging_enabled = 0;
0354     }
0355 }
0356 
0357 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
0358 {
0359     HPI_DEBUG_LOG(VERBOSE, "adapter_open\n");
0360     memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index],
0361         sizeof(rESP_HPI_ADAPTER_OPEN[0]));
0362 }
0363 
0364 static void adapter_close(struct hpi_message *phm, struct hpi_response *phr)
0365 {
0366     HPI_DEBUG_LOG(VERBOSE, "adapter_close\n");
0367     hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0);
0368 }
0369 
0370 static void mixer_open(struct hpi_message *phm, struct hpi_response *phr)
0371 {
0372     memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index],
0373         sizeof(rESP_HPI_MIXER_OPEN[0]));
0374 }
0375 
0376 static void mixer_close(struct hpi_message *phm, struct hpi_response *phr)
0377 {
0378     hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0);
0379 }
0380 
0381 static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
0382     void *h_owner)
0383 {
0384 
0385     struct hpi_message hm;
0386     struct hpi_response hr;
0387 
0388     hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0);
0389 
0390     hpios_msgxlock_lock(&msgx_lock);
0391 
0392     if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag)
0393         phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
0394     else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
0395         [phm->obj_index].h.error)
0396         memcpy(phr,
0397             &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm->
0398                 obj_index],
0399             sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
0400     else {
0401         instream_user_open[phm->adapter_index][phm->
0402             obj_index].open_flag = 1;
0403         hpios_msgxlock_unlock(&msgx_lock);
0404 
0405         /* issue a reset */
0406         hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
0407             HPI_ISTREAM_RESET);
0408         hm.adapter_index = phm->adapter_index;
0409         hm.obj_index = phm->obj_index;
0410         hw_entry_point(&hm, &hr);
0411 
0412         hpios_msgxlock_lock(&msgx_lock);
0413         if (hr.error) {
0414             instream_user_open[phm->adapter_index][phm->
0415                 obj_index].open_flag = 0;
0416             phr->error = hr.error;
0417         } else {
0418             instream_user_open[phm->adapter_index][phm->
0419                 obj_index].open_flag = 1;
0420             instream_user_open[phm->adapter_index][phm->
0421                 obj_index].h_owner = h_owner;
0422             memcpy(phr,
0423                 &rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
0424                 [phm->obj_index],
0425                 sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
0426         }
0427     }
0428     hpios_msgxlock_unlock(&msgx_lock);
0429 }
0430 
0431 static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
0432     void *h_owner)
0433 {
0434 
0435     struct hpi_message hm;
0436     struct hpi_response hr;
0437 
0438     hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0);
0439 
0440     hpios_msgxlock_lock(&msgx_lock);
0441     if (h_owner ==
0442         instream_user_open[phm->adapter_index][phm->
0443             obj_index].h_owner) {
0444         /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
0445            "instream %d owned by %p\n",
0446            phm->wAdapterIndex, phm->wObjIndex, hOwner); */
0447         instream_user_open[phm->adapter_index][phm->
0448             obj_index].h_owner = NULL;
0449         hpios_msgxlock_unlock(&msgx_lock);
0450         /* issue a reset */
0451         hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
0452             HPI_ISTREAM_RESET);
0453         hm.adapter_index = phm->adapter_index;
0454         hm.obj_index = phm->obj_index;
0455         hw_entry_point(&hm, &hr);
0456         hpios_msgxlock_lock(&msgx_lock);
0457         if (hr.error) {
0458             instream_user_open[phm->adapter_index][phm->
0459                 obj_index].h_owner = h_owner;
0460             phr->error = hr.error;
0461         } else {
0462             instream_user_open[phm->adapter_index][phm->
0463                 obj_index].open_flag = 0;
0464             instream_user_open[phm->adapter_index][phm->
0465                 obj_index].h_owner = NULL;
0466         }
0467     } else {
0468         HPI_DEBUG_LOG(WARNING,
0469             "%p trying to close %d instream %d owned by %p\n",
0470             h_owner, phm->adapter_index, phm->obj_index,
0471             instream_user_open[phm->adapter_index][phm->
0472                 obj_index].h_owner);
0473         phr->error = HPI_ERROR_OBJ_NOT_OPEN;
0474     }
0475     hpios_msgxlock_unlock(&msgx_lock);
0476 }
0477 
0478 static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
0479     void *h_owner)
0480 {
0481 
0482     struct hpi_message hm;
0483     struct hpi_response hr;
0484 
0485     hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0);
0486 
0487     hpios_msgxlock_lock(&msgx_lock);
0488 
0489     if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag)
0490         phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
0491     else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
0492         [phm->obj_index].h.error)
0493         memcpy(phr,
0494             &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm->
0495                 obj_index],
0496             sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
0497     else {
0498         outstream_user_open[phm->adapter_index][phm->
0499             obj_index].open_flag = 1;
0500         hpios_msgxlock_unlock(&msgx_lock);
0501 
0502         /* issue a reset */
0503         hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
0504             HPI_OSTREAM_RESET);
0505         hm.adapter_index = phm->adapter_index;
0506         hm.obj_index = phm->obj_index;
0507         hw_entry_point(&hm, &hr);
0508 
0509         hpios_msgxlock_lock(&msgx_lock);
0510         if (hr.error) {
0511             outstream_user_open[phm->adapter_index][phm->
0512                 obj_index].open_flag = 0;
0513             phr->error = hr.error;
0514         } else {
0515             outstream_user_open[phm->adapter_index][phm->
0516                 obj_index].open_flag = 1;
0517             outstream_user_open[phm->adapter_index][phm->
0518                 obj_index].h_owner = h_owner;
0519             memcpy(phr,
0520                 &rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
0521                 [phm->obj_index],
0522                 sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
0523         }
0524     }
0525     hpios_msgxlock_unlock(&msgx_lock);
0526 }
0527 
0528 static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
0529     void *h_owner)
0530 {
0531 
0532     struct hpi_message hm;
0533     struct hpi_response hr;
0534 
0535     hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0);
0536 
0537     hpios_msgxlock_lock(&msgx_lock);
0538 
0539     if (h_owner ==
0540         outstream_user_open[phm->adapter_index][phm->
0541             obj_index].h_owner) {
0542         /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
0543            "outstream %d owned by %p\n",
0544            phm->wAdapterIndex, phm->wObjIndex, hOwner); */
0545         outstream_user_open[phm->adapter_index][phm->
0546             obj_index].h_owner = NULL;
0547         hpios_msgxlock_unlock(&msgx_lock);
0548         /* issue a reset */
0549         hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
0550             HPI_OSTREAM_RESET);
0551         hm.adapter_index = phm->adapter_index;
0552         hm.obj_index = phm->obj_index;
0553         hw_entry_point(&hm, &hr);
0554         hpios_msgxlock_lock(&msgx_lock);
0555         if (hr.error) {
0556             outstream_user_open[phm->adapter_index][phm->
0557                 obj_index].h_owner = h_owner;
0558             phr->error = hr.error;
0559         } else {
0560             outstream_user_open[phm->adapter_index][phm->
0561                 obj_index].open_flag = 0;
0562             outstream_user_open[phm->adapter_index][phm->
0563                 obj_index].h_owner = NULL;
0564         }
0565     } else {
0566         HPI_DEBUG_LOG(WARNING,
0567             "%p trying to close %d outstream %d owned by %p\n",
0568             h_owner, phm->adapter_index, phm->obj_index,
0569             outstream_user_open[phm->adapter_index][phm->
0570                 obj_index].h_owner);
0571         phr->error = HPI_ERROR_OBJ_NOT_OPEN;
0572     }
0573     hpios_msgxlock_unlock(&msgx_lock);
0574 }
0575 
0576 static u16 adapter_prepare(u16 adapter)
0577 {
0578     struct hpi_message hm;
0579     struct hpi_response hr;
0580 
0581     /* Open the adapter and streams */
0582     u16 i;
0583 
0584     /* call to HPI_ADAPTER_OPEN */
0585     hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0586         HPI_ADAPTER_OPEN);
0587     hm.adapter_index = adapter;
0588     hw_entry_point(&hm, &hr);
0589     memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
0590         sizeof(rESP_HPI_ADAPTER_OPEN[0]));
0591     if (hr.error)
0592         return hr.error;
0593 
0594     /* call to HPI_ADAPTER_GET_INFO */
0595     hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0596         HPI_ADAPTER_GET_INFO);
0597     hm.adapter_index = adapter;
0598     hw_entry_point(&hm, &hr);
0599     if (hr.error)
0600         return hr.error;
0601 
0602     aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams;
0603     aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams;
0604     aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type;
0605 
0606     /* call to HPI_OSTREAM_OPEN */
0607     for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
0608         hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
0609             HPI_OSTREAM_OPEN);
0610         hm.adapter_index = adapter;
0611         hm.obj_index = i;
0612         hw_entry_point(&hm, &hr);
0613         memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr,
0614             sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
0615         outstream_user_open[adapter][i].open_flag = 0;
0616         outstream_user_open[adapter][i].h_owner = NULL;
0617     }
0618 
0619     /* call to HPI_ISTREAM_OPEN */
0620     for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) {
0621         hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
0622             HPI_ISTREAM_OPEN);
0623         hm.adapter_index = adapter;
0624         hm.obj_index = i;
0625         hw_entry_point(&hm, &hr);
0626         memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr,
0627             sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
0628         instream_user_open[adapter][i].open_flag = 0;
0629         instream_user_open[adapter][i].h_owner = NULL;
0630     }
0631 
0632     /* call to HPI_MIXER_OPEN */
0633     hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
0634     hm.adapter_index = adapter;
0635     hw_entry_point(&hm, &hr);
0636     memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
0637         sizeof(rESP_HPI_MIXER_OPEN[0]));
0638 
0639     return 0;
0640 }
0641 
0642 static void HPIMSGX__reset(u16 adapter_index)
0643 {
0644     int i;
0645     u16 adapter;
0646     struct hpi_response hr;
0647 
0648     if (adapter_index == HPIMSGX_ALLADAPTERS) {
0649         for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
0650 
0651             hpi_init_response(&hr, HPI_OBJ_ADAPTER,
0652                 HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER);
0653             memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
0654                 sizeof(rESP_HPI_ADAPTER_OPEN[adapter]));
0655 
0656             hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN,
0657                 HPI_ERROR_INVALID_OBJ);
0658             memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
0659                 sizeof(rESP_HPI_MIXER_OPEN[adapter]));
0660 
0661             for (i = 0; i < HPI_MAX_STREAMS; i++) {
0662                 hpi_init_response(&hr, HPI_OBJ_OSTREAM,
0663                     HPI_OSTREAM_OPEN,
0664                     HPI_ERROR_INVALID_OBJ);
0665                 memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i],
0666                     &hr,
0667                     sizeof(rESP_HPI_OSTREAM_OPEN[adapter]
0668                         [i]));
0669                 hpi_init_response(&hr, HPI_OBJ_ISTREAM,
0670                     HPI_ISTREAM_OPEN,
0671                     HPI_ERROR_INVALID_OBJ);
0672                 memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i],
0673                     &hr,
0674                     sizeof(rESP_HPI_ISTREAM_OPEN[adapter]
0675                         [i]));
0676             }
0677         }
0678     } else if (adapter_index < HPI_MAX_ADAPTERS) {
0679         rESP_HPI_ADAPTER_OPEN[adapter_index].h.error =
0680             HPI_ERROR_BAD_ADAPTER;
0681         rESP_HPI_MIXER_OPEN[adapter_index].h.error =
0682             HPI_ERROR_INVALID_OBJ;
0683         for (i = 0; i < HPI_MAX_STREAMS; i++) {
0684             rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error =
0685                 HPI_ERROR_INVALID_OBJ;
0686             rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
0687                 HPI_ERROR_INVALID_OBJ;
0688         }
0689     }
0690 }
0691 
0692 static u16 HPIMSGX__init(struct hpi_message *phm,
0693     /* HPI_SUBSYS_CREATE_ADAPTER structure with */
0694     /* resource list or NULL=find all */
0695     struct hpi_response *phr
0696     /* response from HPI_ADAPTER_GET_INFO */
0697     )
0698 {
0699     hpi_handler_func *entry_point_func;
0700     struct hpi_response hr;
0701 
0702     /* Init response here so we can pass in previous adapter list */
0703     hpi_init_response(&hr, phm->object, phm->function,
0704         HPI_ERROR_INVALID_OBJ);
0705 
0706     entry_point_func =
0707         hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
0708 
0709     if (entry_point_func) {
0710         HPI_DEBUG_MESSAGE(DEBUG, phm);
0711         entry_point_func(phm, &hr);
0712     } else {
0713         phr->error = HPI_ERROR_PROCESSING_MESSAGE;
0714         return phr->error;
0715     }
0716     if (hr.error == 0) {
0717         /* the adapter was created successfully
0718            save the mapping for future use */
0719         hpi_entry_points[hr.u.s.adapter_index] = entry_point_func;
0720         /* prepare adapter (pre-open streams etc.) */
0721         HPI_DEBUG_LOG(DEBUG,
0722             "HPI_SUBSYS_CREATE_ADAPTER successful,"
0723             " preparing adapter\n");
0724         adapter_prepare(hr.u.s.adapter_index);
0725     }
0726     memcpy(phr, &hr, hr.size);
0727     return phr->error;
0728 }
0729 
0730 static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
0731 {
0732     int i, adapter, adapter_limit;
0733 
0734     if (!h_owner)
0735         return;
0736 
0737     if (adapter_index == HPIMSGX_ALLADAPTERS) {
0738         adapter = 0;
0739         adapter_limit = HPI_MAX_ADAPTERS;
0740     } else {
0741         adapter = adapter_index;
0742         adapter_limit = adapter + 1;
0743     }
0744 
0745     for (; adapter < adapter_limit; adapter++) {
0746         /*      printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */
0747         for (i = 0; i < HPI_MAX_STREAMS; i++) {
0748             if (h_owner ==
0749                 outstream_user_open[adapter][i].h_owner) {
0750                 struct hpi_message hm;
0751                 struct hpi_response hr;
0752 
0753                 HPI_DEBUG_LOG(DEBUG,
0754                     "Close adapter %d ostream %d\n",
0755                     adapter, i);
0756 
0757                 hpi_init_message_response(&hm, &hr,
0758                     HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET);
0759                 hm.adapter_index = (u16)adapter;
0760                 hm.obj_index = (u16)i;
0761                 hw_entry_point(&hm, &hr);
0762 
0763                 hm.function = HPI_OSTREAM_HOSTBUFFER_FREE;
0764                 hw_entry_point(&hm, &hr);
0765 
0766                 hm.function = HPI_OSTREAM_GROUP_RESET;
0767                 hw_entry_point(&hm, &hr);
0768 
0769                 outstream_user_open[adapter][i].open_flag = 0;
0770                 outstream_user_open[adapter][i].h_owner =
0771                     NULL;
0772             }
0773             if (h_owner == instream_user_open[adapter][i].h_owner) {
0774                 struct hpi_message hm;
0775                 struct hpi_response hr;
0776 
0777                 HPI_DEBUG_LOG(DEBUG,
0778                     "Close adapter %d istream %d\n",
0779                     adapter, i);
0780 
0781                 hpi_init_message_response(&hm, &hr,
0782                     HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET);
0783                 hm.adapter_index = (u16)adapter;
0784                 hm.obj_index = (u16)i;
0785                 hw_entry_point(&hm, &hr);
0786 
0787                 hm.function = HPI_ISTREAM_HOSTBUFFER_FREE;
0788                 hw_entry_point(&hm, &hr);
0789 
0790                 hm.function = HPI_ISTREAM_GROUP_RESET;
0791                 hw_entry_point(&hm, &hr);
0792 
0793                 instream_user_open[adapter][i].open_flag = 0;
0794                 instream_user_open[adapter][i].h_owner = NULL;
0795             }
0796         }
0797     }
0798 }