1*719f82d3SEliot Blennerhassett /****************************************************************************** 2*719f82d3SEliot Blennerhassett 3*719f82d3SEliot Blennerhassett AudioScience HPI driver 4*719f82d3SEliot Blennerhassett Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> 5*719f82d3SEliot Blennerhassett 6*719f82d3SEliot Blennerhassett This program is free software; you can redistribute it and/or modify 7*719f82d3SEliot Blennerhassett it under the terms of version 2 of the GNU General Public License as 8*719f82d3SEliot Blennerhassett published by the Free Software Foundation; 9*719f82d3SEliot Blennerhassett 10*719f82d3SEliot Blennerhassett This program is distributed in the hope that it will be useful, 11*719f82d3SEliot Blennerhassett but WITHOUT ANY WARRANTY; without even the implied warranty of 12*719f82d3SEliot Blennerhassett MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*719f82d3SEliot Blennerhassett GNU General Public License for more details. 14*719f82d3SEliot Blennerhassett 15*719f82d3SEliot Blennerhassett You should have received a copy of the GNU General Public License 16*719f82d3SEliot Blennerhassett along with this program; if not, write to the Free Software 17*719f82d3SEliot Blennerhassett Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18*719f82d3SEliot Blennerhassett 19*719f82d3SEliot Blennerhassett Extended Message Function With Response Cacheing 20*719f82d3SEliot Blennerhassett 21*719f82d3SEliot Blennerhassett (C) Copyright AudioScience Inc. 2002 22*719f82d3SEliot Blennerhassett *****************************************************************************/ 23*719f82d3SEliot Blennerhassett #define SOURCEFILE_NAME "hpimsgx.c" 24*719f82d3SEliot Blennerhassett #include "hpi_internal.h" 25*719f82d3SEliot Blennerhassett #include "hpimsginit.h" 26*719f82d3SEliot Blennerhassett #include "hpimsgx.h" 27*719f82d3SEliot Blennerhassett #include "hpidebug.h" 28*719f82d3SEliot Blennerhassett 29*719f82d3SEliot Blennerhassett static struct pci_device_id asihpi_pci_tbl[] = { 30*719f82d3SEliot Blennerhassett #include "hpipcida.h" 31*719f82d3SEliot Blennerhassett }; 32*719f82d3SEliot Blennerhassett 33*719f82d3SEliot Blennerhassett static struct hpios_spinlock msgx_lock; 34*719f82d3SEliot Blennerhassett 35*719f82d3SEliot Blennerhassett static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS]; 36*719f82d3SEliot Blennerhassett 37*719f82d3SEliot Blennerhassett static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci 38*719f82d3SEliot Blennerhassett *pci_info) 39*719f82d3SEliot Blennerhassett { 40*719f82d3SEliot Blennerhassett 41*719f82d3SEliot Blennerhassett int i; 42*719f82d3SEliot Blennerhassett 43*719f82d3SEliot Blennerhassett for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) { 44*719f82d3SEliot Blennerhassett if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID 45*719f82d3SEliot Blennerhassett && asihpi_pci_tbl[i].vendor != pci_info->vendor_id) 46*719f82d3SEliot Blennerhassett continue; 47*719f82d3SEliot Blennerhassett if (asihpi_pci_tbl[i].device != PCI_ANY_ID 48*719f82d3SEliot Blennerhassett && asihpi_pci_tbl[i].device != pci_info->device_id) 49*719f82d3SEliot Blennerhassett continue; 50*719f82d3SEliot Blennerhassett if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID 51*719f82d3SEliot Blennerhassett && asihpi_pci_tbl[i].subvendor != 52*719f82d3SEliot Blennerhassett pci_info->subsys_vendor_id) 53*719f82d3SEliot Blennerhassett continue; 54*719f82d3SEliot Blennerhassett if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID 55*719f82d3SEliot Blennerhassett && asihpi_pci_tbl[i].subdevice != 56*719f82d3SEliot Blennerhassett pci_info->subsys_device_id) 57*719f82d3SEliot Blennerhassett continue; 58*719f82d3SEliot Blennerhassett 59*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, " %x,%lu\n", i, 60*719f82d3SEliot Blennerhassett asihpi_pci_tbl[i].driver_data); 61*719f82d3SEliot Blennerhassett return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data; 62*719f82d3SEliot Blennerhassett } 63*719f82d3SEliot Blennerhassett 64*719f82d3SEliot Blennerhassett return NULL; 65*719f82d3SEliot Blennerhassett } 66*719f82d3SEliot Blennerhassett 67*719f82d3SEliot Blennerhassett static inline void hw_entry_point(struct hpi_message *phm, 68*719f82d3SEliot Blennerhassett struct hpi_response *phr) 69*719f82d3SEliot Blennerhassett { 70*719f82d3SEliot Blennerhassett 71*719f82d3SEliot Blennerhassett hpi_handler_func *ep; 72*719f82d3SEliot Blennerhassett 73*719f82d3SEliot Blennerhassett if (phm->adapter_index < HPI_MAX_ADAPTERS) { 74*719f82d3SEliot Blennerhassett ep = (hpi_handler_func *) hpi_entry_points[phm-> 75*719f82d3SEliot Blennerhassett adapter_index]; 76*719f82d3SEliot Blennerhassett if (ep) { 77*719f82d3SEliot Blennerhassett HPI_DEBUG_MESSAGE(DEBUG, phm); 78*719f82d3SEliot Blennerhassett ep(phm, phr); 79*719f82d3SEliot Blennerhassett HPI_DEBUG_RESPONSE(phr); 80*719f82d3SEliot Blennerhassett return; 81*719f82d3SEliot Blennerhassett } 82*719f82d3SEliot Blennerhassett } 83*719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 84*719f82d3SEliot Blennerhassett HPI_ERROR_PROCESSING_MESSAGE); 85*719f82d3SEliot Blennerhassett } 86*719f82d3SEliot Blennerhassett 87*719f82d3SEliot Blennerhassett static void adapter_open(struct hpi_message *phm, struct hpi_response *phr); 88*719f82d3SEliot Blennerhassett static void adapter_close(struct hpi_message *phm, struct hpi_response *phr); 89*719f82d3SEliot Blennerhassett 90*719f82d3SEliot Blennerhassett static void mixer_open(struct hpi_message *phm, struct hpi_response *phr); 91*719f82d3SEliot Blennerhassett static void mixer_close(struct hpi_message *phm, struct hpi_response *phr); 92*719f82d3SEliot Blennerhassett 93*719f82d3SEliot Blennerhassett static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, 94*719f82d3SEliot Blennerhassett void *h_owner); 95*719f82d3SEliot Blennerhassett static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, 96*719f82d3SEliot Blennerhassett void *h_owner); 97*719f82d3SEliot Blennerhassett static void instream_open(struct hpi_message *phm, struct hpi_response *phr, 98*719f82d3SEliot Blennerhassett void *h_owner); 99*719f82d3SEliot Blennerhassett static void instream_close(struct hpi_message *phm, struct hpi_response *phr, 100*719f82d3SEliot Blennerhassett void *h_owner); 101*719f82d3SEliot Blennerhassett 102*719f82d3SEliot Blennerhassett static void HPIMSGX__reset(u16 adapter_index); 103*719f82d3SEliot Blennerhassett static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr); 104*719f82d3SEliot Blennerhassett static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner); 105*719f82d3SEliot Blennerhassett 106*719f82d3SEliot Blennerhassett #ifndef DISABLE_PRAGMA_PACK1 107*719f82d3SEliot Blennerhassett #pragma pack(push, 1) 108*719f82d3SEliot Blennerhassett #endif 109*719f82d3SEliot Blennerhassett 110*719f82d3SEliot Blennerhassett struct hpi_subsys_response { 111*719f82d3SEliot Blennerhassett struct hpi_response_header h; 112*719f82d3SEliot Blennerhassett struct hpi_subsys_res s; 113*719f82d3SEliot Blennerhassett }; 114*719f82d3SEliot Blennerhassett 115*719f82d3SEliot Blennerhassett struct hpi_adapter_response { 116*719f82d3SEliot Blennerhassett struct hpi_response_header h; 117*719f82d3SEliot Blennerhassett struct hpi_adapter_res a; 118*719f82d3SEliot Blennerhassett }; 119*719f82d3SEliot Blennerhassett 120*719f82d3SEliot Blennerhassett struct hpi_mixer_response { 121*719f82d3SEliot Blennerhassett struct hpi_response_header h; 122*719f82d3SEliot Blennerhassett struct hpi_mixer_res m; 123*719f82d3SEliot Blennerhassett }; 124*719f82d3SEliot Blennerhassett 125*719f82d3SEliot Blennerhassett struct hpi_stream_response { 126*719f82d3SEliot Blennerhassett struct hpi_response_header h; 127*719f82d3SEliot Blennerhassett struct hpi_stream_res d; 128*719f82d3SEliot Blennerhassett }; 129*719f82d3SEliot Blennerhassett 130*719f82d3SEliot Blennerhassett struct adapter_info { 131*719f82d3SEliot Blennerhassett u16 type; 132*719f82d3SEliot Blennerhassett u16 num_instreams; 133*719f82d3SEliot Blennerhassett u16 num_outstreams; 134*719f82d3SEliot Blennerhassett }; 135*719f82d3SEliot Blennerhassett 136*719f82d3SEliot Blennerhassett struct asi_open_state { 137*719f82d3SEliot Blennerhassett int open_flag; 138*719f82d3SEliot Blennerhassett void *h_owner; 139*719f82d3SEliot Blennerhassett }; 140*719f82d3SEliot Blennerhassett 141*719f82d3SEliot Blennerhassett #ifndef DISABLE_PRAGMA_PACK1 142*719f82d3SEliot Blennerhassett #pragma pack(pop) 143*719f82d3SEliot Blennerhassett #endif 144*719f82d3SEliot Blennerhassett 145*719f82d3SEliot Blennerhassett /* Globals */ 146*719f82d3SEliot Blennerhassett static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS]; 147*719f82d3SEliot Blennerhassett 148*719f82d3SEliot Blennerhassett static struct hpi_stream_response 149*719f82d3SEliot Blennerhassett rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 150*719f82d3SEliot Blennerhassett 151*719f82d3SEliot Blennerhassett static struct hpi_stream_response 152*719f82d3SEliot Blennerhassett rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 153*719f82d3SEliot Blennerhassett 154*719f82d3SEliot Blennerhassett static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS]; 155*719f82d3SEliot Blennerhassett 156*719f82d3SEliot Blennerhassett static struct hpi_subsys_response gRESP_HPI_SUBSYS_FIND_ADAPTERS; 157*719f82d3SEliot Blennerhassett 158*719f82d3SEliot Blennerhassett static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS]; 159*719f82d3SEliot Blennerhassett 160*719f82d3SEliot Blennerhassett /* use these to keep track of opens from user mode apps/DLLs */ 161*719f82d3SEliot Blennerhassett static struct asi_open_state 162*719f82d3SEliot Blennerhassett outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 163*719f82d3SEliot Blennerhassett 164*719f82d3SEliot Blennerhassett static struct asi_open_state 165*719f82d3SEliot Blennerhassett instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; 166*719f82d3SEliot Blennerhassett 167*719f82d3SEliot Blennerhassett static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, 168*719f82d3SEliot Blennerhassett void *h_owner) 169*719f82d3SEliot Blennerhassett { 170*719f82d3SEliot Blennerhassett switch (phm->function) { 171*719f82d3SEliot Blennerhassett case HPI_SUBSYS_GET_VERSION: 172*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, 173*719f82d3SEliot Blennerhassett HPI_SUBSYS_GET_VERSION, 0); 174*719f82d3SEliot Blennerhassett phr->u.s.version = HPI_VER >> 8; /* return major.minor */ 175*719f82d3SEliot Blennerhassett phr->u.s.data = HPI_VER; /* return major.minor.release */ 176*719f82d3SEliot Blennerhassett break; 177*719f82d3SEliot Blennerhassett case HPI_SUBSYS_OPEN: 178*719f82d3SEliot Blennerhassett /*do not propagate the message down the chain */ 179*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0); 180*719f82d3SEliot Blennerhassett break; 181*719f82d3SEliot Blennerhassett case HPI_SUBSYS_CLOSE: 182*719f82d3SEliot Blennerhassett /*do not propagate the message down the chain */ 183*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE, 184*719f82d3SEliot Blennerhassett 0); 185*719f82d3SEliot Blennerhassett HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner); 186*719f82d3SEliot Blennerhassett break; 187*719f82d3SEliot Blennerhassett case HPI_SUBSYS_DRIVER_LOAD: 188*719f82d3SEliot Blennerhassett /* Initialize this module's internal state */ 189*719f82d3SEliot Blennerhassett hpios_msgxlock_init(&msgx_lock); 190*719f82d3SEliot Blennerhassett memset(&hpi_entry_points, 0, sizeof(hpi_entry_points)); 191*719f82d3SEliot Blennerhassett hpios_locked_mem_init(); 192*719f82d3SEliot Blennerhassett /* Init subsys_findadapters response to no-adapters */ 193*719f82d3SEliot Blennerhassett HPIMSGX__reset(HPIMSGX_ALLADAPTERS); 194*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, 195*719f82d3SEliot Blennerhassett HPI_SUBSYS_DRIVER_LOAD, 0); 196*719f82d3SEliot Blennerhassett /* individual HPIs dont implement driver load */ 197*719f82d3SEliot Blennerhassett HPI_COMMON(phm, phr); 198*719f82d3SEliot Blennerhassett break; 199*719f82d3SEliot Blennerhassett case HPI_SUBSYS_DRIVER_UNLOAD: 200*719f82d3SEliot Blennerhassett HPI_COMMON(phm, phr); 201*719f82d3SEliot Blennerhassett HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner); 202*719f82d3SEliot Blennerhassett hpios_locked_mem_free_all(); 203*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, 204*719f82d3SEliot Blennerhassett HPI_SUBSYS_DRIVER_UNLOAD, 0); 205*719f82d3SEliot Blennerhassett return; 206*719f82d3SEliot Blennerhassett 207*719f82d3SEliot Blennerhassett case HPI_SUBSYS_GET_INFO: 208*719f82d3SEliot Blennerhassett HPI_COMMON(phm, phr); 209*719f82d3SEliot Blennerhassett break; 210*719f82d3SEliot Blennerhassett 211*719f82d3SEliot Blennerhassett case HPI_SUBSYS_FIND_ADAPTERS: 212*719f82d3SEliot Blennerhassett memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS, 213*719f82d3SEliot Blennerhassett sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS)); 214*719f82d3SEliot Blennerhassett break; 215*719f82d3SEliot Blennerhassett case HPI_SUBSYS_GET_NUM_ADAPTERS: 216*719f82d3SEliot Blennerhassett memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS, 217*719f82d3SEliot Blennerhassett sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS)); 218*719f82d3SEliot Blennerhassett phr->function = HPI_SUBSYS_GET_NUM_ADAPTERS; 219*719f82d3SEliot Blennerhassett break; 220*719f82d3SEliot Blennerhassett case HPI_SUBSYS_GET_ADAPTER: 221*719f82d3SEliot Blennerhassett { 222*719f82d3SEliot Blennerhassett int count = phm->adapter_index; 223*719f82d3SEliot Blennerhassett int index = 0; 224*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, 225*719f82d3SEliot Blennerhassett HPI_SUBSYS_GET_ADAPTER, 0); 226*719f82d3SEliot Blennerhassett 227*719f82d3SEliot Blennerhassett /* This is complicated by the fact that we want to 228*719f82d3SEliot Blennerhassett * "skip" 0's in the adapter list. 229*719f82d3SEliot Blennerhassett * First, make sure we are pointing to a 230*719f82d3SEliot Blennerhassett * non-zero adapter type. 231*719f82d3SEliot Blennerhassett */ 232*719f82d3SEliot Blennerhassett while (gRESP_HPI_SUBSYS_FIND_ADAPTERS. 233*719f82d3SEliot Blennerhassett s.aw_adapter_list[index] == 0) { 234*719f82d3SEliot Blennerhassett index++; 235*719f82d3SEliot Blennerhassett if (index >= HPI_MAX_ADAPTERS) 236*719f82d3SEliot Blennerhassett break; 237*719f82d3SEliot Blennerhassett } 238*719f82d3SEliot Blennerhassett while (count) { 239*719f82d3SEliot Blennerhassett /* move on to the next adapter */ 240*719f82d3SEliot Blennerhassett index++; 241*719f82d3SEliot Blennerhassett if (index >= HPI_MAX_ADAPTERS) 242*719f82d3SEliot Blennerhassett break; 243*719f82d3SEliot Blennerhassett while (gRESP_HPI_SUBSYS_FIND_ADAPTERS. 244*719f82d3SEliot Blennerhassett s.aw_adapter_list[index] == 0) { 245*719f82d3SEliot Blennerhassett index++; 246*719f82d3SEliot Blennerhassett if (index >= HPI_MAX_ADAPTERS) 247*719f82d3SEliot Blennerhassett break; 248*719f82d3SEliot Blennerhassett } 249*719f82d3SEliot Blennerhassett count--; 250*719f82d3SEliot Blennerhassett } 251*719f82d3SEliot Blennerhassett 252*719f82d3SEliot Blennerhassett if (index < HPI_MAX_ADAPTERS) { 253*719f82d3SEliot Blennerhassett phr->u.s.adapter_index = (u16)index; 254*719f82d3SEliot Blennerhassett phr->u.s.aw_adapter_list[0] = 255*719f82d3SEliot Blennerhassett gRESP_HPI_SUBSYS_FIND_ADAPTERS. 256*719f82d3SEliot Blennerhassett s.aw_adapter_list[index]; 257*719f82d3SEliot Blennerhassett } else { 258*719f82d3SEliot Blennerhassett phr->u.s.adapter_index = 0; 259*719f82d3SEliot Blennerhassett phr->u.s.aw_adapter_list[0] = 0; 260*719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER; 261*719f82d3SEliot Blennerhassett } 262*719f82d3SEliot Blennerhassett break; 263*719f82d3SEliot Blennerhassett } 264*719f82d3SEliot Blennerhassett case HPI_SUBSYS_CREATE_ADAPTER: 265*719f82d3SEliot Blennerhassett HPIMSGX__init(phm, phr); 266*719f82d3SEliot Blennerhassett break; 267*719f82d3SEliot Blennerhassett case HPI_SUBSYS_DELETE_ADAPTER: 268*719f82d3SEliot Blennerhassett HPIMSGX__cleanup(phm->adapter_index, h_owner); 269*719f82d3SEliot Blennerhassett { 270*719f82d3SEliot Blennerhassett struct hpi_message hm; 271*719f82d3SEliot Blennerhassett struct hpi_response hr; 272*719f82d3SEliot Blennerhassett /* call to HPI_ADAPTER_CLOSE */ 273*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 274*719f82d3SEliot Blennerhassett HPI_ADAPTER_CLOSE); 275*719f82d3SEliot Blennerhassett hm.adapter_index = phm->adapter_index; 276*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 277*719f82d3SEliot Blennerhassett } 278*719f82d3SEliot Blennerhassett hw_entry_point(phm, phr); 279*719f82d3SEliot Blennerhassett gRESP_HPI_SUBSYS_FIND_ADAPTERS.s. 280*719f82d3SEliot Blennerhassett aw_adapter_list[phm->adapter_index] 281*719f82d3SEliot Blennerhassett = 0; 282*719f82d3SEliot Blennerhassett hpi_entry_points[phm->adapter_index] = NULL; 283*719f82d3SEliot Blennerhassett break; 284*719f82d3SEliot Blennerhassett default: 285*719f82d3SEliot Blennerhassett hw_entry_point(phm, phr); 286*719f82d3SEliot Blennerhassett break; 287*719f82d3SEliot Blennerhassett } 288*719f82d3SEliot Blennerhassett } 289*719f82d3SEliot Blennerhassett 290*719f82d3SEliot Blennerhassett static void adapter_message(struct hpi_message *phm, struct hpi_response *phr, 291*719f82d3SEliot Blennerhassett void *h_owner) 292*719f82d3SEliot Blennerhassett { 293*719f82d3SEliot Blennerhassett switch (phm->function) { 294*719f82d3SEliot Blennerhassett case HPI_ADAPTER_OPEN: 295*719f82d3SEliot Blennerhassett adapter_open(phm, phr); 296*719f82d3SEliot Blennerhassett break; 297*719f82d3SEliot Blennerhassett case HPI_ADAPTER_CLOSE: 298*719f82d3SEliot Blennerhassett adapter_close(phm, phr); 299*719f82d3SEliot Blennerhassett break; 300*719f82d3SEliot Blennerhassett default: 301*719f82d3SEliot Blennerhassett hw_entry_point(phm, phr); 302*719f82d3SEliot Blennerhassett break; 303*719f82d3SEliot Blennerhassett } 304*719f82d3SEliot Blennerhassett } 305*719f82d3SEliot Blennerhassett 306*719f82d3SEliot Blennerhassett static void mixer_message(struct hpi_message *phm, struct hpi_response *phr) 307*719f82d3SEliot Blennerhassett { 308*719f82d3SEliot Blennerhassett switch (phm->function) { 309*719f82d3SEliot Blennerhassett case HPI_MIXER_OPEN: 310*719f82d3SEliot Blennerhassett mixer_open(phm, phr); 311*719f82d3SEliot Blennerhassett break; 312*719f82d3SEliot Blennerhassett case HPI_MIXER_CLOSE: 313*719f82d3SEliot Blennerhassett mixer_close(phm, phr); 314*719f82d3SEliot Blennerhassett break; 315*719f82d3SEliot Blennerhassett default: 316*719f82d3SEliot Blennerhassett hw_entry_point(phm, phr); 317*719f82d3SEliot Blennerhassett break; 318*719f82d3SEliot Blennerhassett } 319*719f82d3SEliot Blennerhassett } 320*719f82d3SEliot Blennerhassett 321*719f82d3SEliot Blennerhassett static void outstream_message(struct hpi_message *phm, 322*719f82d3SEliot Blennerhassett struct hpi_response *phr, void *h_owner) 323*719f82d3SEliot Blennerhassett { 324*719f82d3SEliot Blennerhassett if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) { 325*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function, 326*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ_INDEX); 327*719f82d3SEliot Blennerhassett return; 328*719f82d3SEliot Blennerhassett } 329*719f82d3SEliot Blennerhassett 330*719f82d3SEliot Blennerhassett switch (phm->function) { 331*719f82d3SEliot Blennerhassett case HPI_OSTREAM_OPEN: 332*719f82d3SEliot Blennerhassett outstream_open(phm, phr, h_owner); 333*719f82d3SEliot Blennerhassett break; 334*719f82d3SEliot Blennerhassett case HPI_OSTREAM_CLOSE: 335*719f82d3SEliot Blennerhassett outstream_close(phm, phr, h_owner); 336*719f82d3SEliot Blennerhassett break; 337*719f82d3SEliot Blennerhassett default: 338*719f82d3SEliot Blennerhassett hw_entry_point(phm, phr); 339*719f82d3SEliot Blennerhassett break; 340*719f82d3SEliot Blennerhassett } 341*719f82d3SEliot Blennerhassett } 342*719f82d3SEliot Blennerhassett 343*719f82d3SEliot Blennerhassett static void instream_message(struct hpi_message *phm, 344*719f82d3SEliot Blennerhassett struct hpi_response *phr, void *h_owner) 345*719f82d3SEliot Blennerhassett { 346*719f82d3SEliot Blennerhassett if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) { 347*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function, 348*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ_INDEX); 349*719f82d3SEliot Blennerhassett return; 350*719f82d3SEliot Blennerhassett } 351*719f82d3SEliot Blennerhassett 352*719f82d3SEliot Blennerhassett switch (phm->function) { 353*719f82d3SEliot Blennerhassett case HPI_ISTREAM_OPEN: 354*719f82d3SEliot Blennerhassett instream_open(phm, phr, h_owner); 355*719f82d3SEliot Blennerhassett break; 356*719f82d3SEliot Blennerhassett case HPI_ISTREAM_CLOSE: 357*719f82d3SEliot Blennerhassett instream_close(phm, phr, h_owner); 358*719f82d3SEliot Blennerhassett break; 359*719f82d3SEliot Blennerhassett default: 360*719f82d3SEliot Blennerhassett hw_entry_point(phm, phr); 361*719f82d3SEliot Blennerhassett break; 362*719f82d3SEliot Blennerhassett } 363*719f82d3SEliot Blennerhassett } 364*719f82d3SEliot Blennerhassett 365*719f82d3SEliot Blennerhassett /* NOTE: HPI_Message() must be defined in the driver as a wrapper for 366*719f82d3SEliot Blennerhassett * HPI_MessageEx so that functions in hpifunc.c compile. 367*719f82d3SEliot Blennerhassett */ 368*719f82d3SEliot Blennerhassett void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr, 369*719f82d3SEliot Blennerhassett void *h_owner) 370*719f82d3SEliot Blennerhassett { 371*719f82d3SEliot Blennerhassett HPI_DEBUG_MESSAGE(DEBUG, phm); 372*719f82d3SEliot Blennerhassett 373*719f82d3SEliot Blennerhassett if (phm->type != HPI_TYPE_MESSAGE) { 374*719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 375*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_TYPE); 376*719f82d3SEliot Blennerhassett return; 377*719f82d3SEliot Blennerhassett } 378*719f82d3SEliot Blennerhassett 379*719f82d3SEliot Blennerhassett if (phm->adapter_index >= HPI_MAX_ADAPTERS 380*719f82d3SEliot Blennerhassett && phm->adapter_index != HPIMSGX_ALLADAPTERS) { 381*719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 382*719f82d3SEliot Blennerhassett HPI_ERROR_BAD_ADAPTER_NUMBER); 383*719f82d3SEliot Blennerhassett return; 384*719f82d3SEliot Blennerhassett } 385*719f82d3SEliot Blennerhassett 386*719f82d3SEliot Blennerhassett switch (phm->object) { 387*719f82d3SEliot Blennerhassett case HPI_OBJ_SUBSYSTEM: 388*719f82d3SEliot Blennerhassett subsys_message(phm, phr, h_owner); 389*719f82d3SEliot Blennerhassett break; 390*719f82d3SEliot Blennerhassett 391*719f82d3SEliot Blennerhassett case HPI_OBJ_ADAPTER: 392*719f82d3SEliot Blennerhassett adapter_message(phm, phr, h_owner); 393*719f82d3SEliot Blennerhassett break; 394*719f82d3SEliot Blennerhassett 395*719f82d3SEliot Blennerhassett case HPI_OBJ_MIXER: 396*719f82d3SEliot Blennerhassett mixer_message(phm, phr); 397*719f82d3SEliot Blennerhassett break; 398*719f82d3SEliot Blennerhassett 399*719f82d3SEliot Blennerhassett case HPI_OBJ_OSTREAM: 400*719f82d3SEliot Blennerhassett outstream_message(phm, phr, h_owner); 401*719f82d3SEliot Blennerhassett break; 402*719f82d3SEliot Blennerhassett 403*719f82d3SEliot Blennerhassett case HPI_OBJ_ISTREAM: 404*719f82d3SEliot Blennerhassett instream_message(phm, phr, h_owner); 405*719f82d3SEliot Blennerhassett break; 406*719f82d3SEliot Blennerhassett 407*719f82d3SEliot Blennerhassett default: 408*719f82d3SEliot Blennerhassett hw_entry_point(phm, phr); 409*719f82d3SEliot Blennerhassett break; 410*719f82d3SEliot Blennerhassett } 411*719f82d3SEliot Blennerhassett HPI_DEBUG_RESPONSE(phr); 412*719f82d3SEliot Blennerhassett #if 1 413*719f82d3SEliot Blennerhassett if (phr->error >= HPI_ERROR_BACKEND_BASE) { 414*719f82d3SEliot Blennerhassett void *ep = NULL; 415*719f82d3SEliot Blennerhassett char *ep_name; 416*719f82d3SEliot Blennerhassett 417*719f82d3SEliot Blennerhassett HPI_DEBUG_MESSAGE(ERROR, phm); 418*719f82d3SEliot Blennerhassett 419*719f82d3SEliot Blennerhassett if (phm->adapter_index < HPI_MAX_ADAPTERS) 420*719f82d3SEliot Blennerhassett ep = hpi_entry_points[phm->adapter_index]; 421*719f82d3SEliot Blennerhassett 422*719f82d3SEliot Blennerhassett /* Don't need this? Have adapter index in debug info 423*719f82d3SEliot Blennerhassett Know at driver load time index->backend mapping */ 424*719f82d3SEliot Blennerhassett if (ep == HPI_6000) 425*719f82d3SEliot Blennerhassett ep_name = "HPI_6000"; 426*719f82d3SEliot Blennerhassett else if (ep == HPI_6205) 427*719f82d3SEliot Blennerhassett ep_name = "HPI_6205"; 428*719f82d3SEliot Blennerhassett else 429*719f82d3SEliot Blennerhassett ep_name = "unknown"; 430*719f82d3SEliot Blennerhassett 431*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "HPI %s response - error# %d\n", ep_name, 432*719f82d3SEliot Blennerhassett phr->error); 433*719f82d3SEliot Blennerhassett 434*719f82d3SEliot Blennerhassett if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) 435*719f82d3SEliot Blennerhassett hpi_debug_data((u16 *)phm, 436*719f82d3SEliot Blennerhassett sizeof(*phm) / sizeof(u16)); 437*719f82d3SEliot Blennerhassett } 438*719f82d3SEliot Blennerhassett #endif 439*719f82d3SEliot Blennerhassett } 440*719f82d3SEliot Blennerhassett 441*719f82d3SEliot Blennerhassett static void adapter_open(struct hpi_message *phm, struct hpi_response *phr) 442*719f82d3SEliot Blennerhassett { 443*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, "adapter_open\n"); 444*719f82d3SEliot Blennerhassett memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index], 445*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_ADAPTER_OPEN[0])); 446*719f82d3SEliot Blennerhassett } 447*719f82d3SEliot Blennerhassett 448*719f82d3SEliot Blennerhassett static void adapter_close(struct hpi_message *phm, struct hpi_response *phr) 449*719f82d3SEliot Blennerhassett { 450*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, "adapter_close\n"); 451*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0); 452*719f82d3SEliot Blennerhassett } 453*719f82d3SEliot Blennerhassett 454*719f82d3SEliot Blennerhassett static void mixer_open(struct hpi_message *phm, struct hpi_response *phr) 455*719f82d3SEliot Blennerhassett { 456*719f82d3SEliot Blennerhassett memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index], 457*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_MIXER_OPEN[0])); 458*719f82d3SEliot Blennerhassett } 459*719f82d3SEliot Blennerhassett 460*719f82d3SEliot Blennerhassett static void mixer_close(struct hpi_message *phm, struct hpi_response *phr) 461*719f82d3SEliot Blennerhassett { 462*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0); 463*719f82d3SEliot Blennerhassett } 464*719f82d3SEliot Blennerhassett 465*719f82d3SEliot Blennerhassett static void instream_open(struct hpi_message *phm, struct hpi_response *phr, 466*719f82d3SEliot Blennerhassett void *h_owner) 467*719f82d3SEliot Blennerhassett { 468*719f82d3SEliot Blennerhassett 469*719f82d3SEliot Blennerhassett struct hpi_message hm; 470*719f82d3SEliot Blennerhassett struct hpi_response hr; 471*719f82d3SEliot Blennerhassett 472*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0); 473*719f82d3SEliot Blennerhassett 474*719f82d3SEliot Blennerhassett hpios_msgxlock_lock(&msgx_lock); 475*719f82d3SEliot Blennerhassett 476*719f82d3SEliot Blennerhassett if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag) 477*719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_OBJ_ALREADY_OPEN; 478*719f82d3SEliot Blennerhassett else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index] 479*719f82d3SEliot Blennerhassett [phm->obj_index].h.error) 480*719f82d3SEliot Blennerhassett memcpy(phr, 481*719f82d3SEliot Blennerhassett &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm-> 482*719f82d3SEliot Blennerhassett obj_index], 483*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 484*719f82d3SEliot Blennerhassett else { 485*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 486*719f82d3SEliot Blennerhassett obj_index].open_flag = 1; 487*719f82d3SEliot Blennerhassett hpios_msgxlock_un_lock(&msgx_lock); 488*719f82d3SEliot Blennerhassett 489*719f82d3SEliot Blennerhassett /* issue a reset */ 490*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 491*719f82d3SEliot Blennerhassett HPI_ISTREAM_RESET); 492*719f82d3SEliot Blennerhassett hm.adapter_index = phm->adapter_index; 493*719f82d3SEliot Blennerhassett hm.obj_index = phm->obj_index; 494*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 495*719f82d3SEliot Blennerhassett 496*719f82d3SEliot Blennerhassett hpios_msgxlock_lock(&msgx_lock); 497*719f82d3SEliot Blennerhassett if (hr.error) { 498*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 499*719f82d3SEliot Blennerhassett obj_index].open_flag = 0; 500*719f82d3SEliot Blennerhassett phr->error = hr.error; 501*719f82d3SEliot Blennerhassett } else { 502*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 503*719f82d3SEliot Blennerhassett obj_index].open_flag = 1; 504*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 505*719f82d3SEliot Blennerhassett obj_index].h_owner = h_owner; 506*719f82d3SEliot Blennerhassett memcpy(phr, 507*719f82d3SEliot Blennerhassett &rESP_HPI_ISTREAM_OPEN[phm->adapter_index] 508*719f82d3SEliot Blennerhassett [phm->obj_index], 509*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 510*719f82d3SEliot Blennerhassett } 511*719f82d3SEliot Blennerhassett } 512*719f82d3SEliot Blennerhassett hpios_msgxlock_un_lock(&msgx_lock); 513*719f82d3SEliot Blennerhassett } 514*719f82d3SEliot Blennerhassett 515*719f82d3SEliot Blennerhassett static void instream_close(struct hpi_message *phm, struct hpi_response *phr, 516*719f82d3SEliot Blennerhassett void *h_owner) 517*719f82d3SEliot Blennerhassett { 518*719f82d3SEliot Blennerhassett 519*719f82d3SEliot Blennerhassett struct hpi_message hm; 520*719f82d3SEliot Blennerhassett struct hpi_response hr; 521*719f82d3SEliot Blennerhassett 522*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0); 523*719f82d3SEliot Blennerhassett 524*719f82d3SEliot Blennerhassett hpios_msgxlock_lock(&msgx_lock); 525*719f82d3SEliot Blennerhassett if (h_owner == 526*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 527*719f82d3SEliot Blennerhassett obj_index].h_owner) { 528*719f82d3SEliot Blennerhassett /* HPI_DEBUG_LOG(INFO,"closing adapter %d " 529*719f82d3SEliot Blennerhassett "instream %d owned by %p\n", 530*719f82d3SEliot Blennerhassett phm->wAdapterIndex, phm->wObjIndex, hOwner); */ 531*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 532*719f82d3SEliot Blennerhassett obj_index].h_owner = NULL; 533*719f82d3SEliot Blennerhassett hpios_msgxlock_un_lock(&msgx_lock); 534*719f82d3SEliot Blennerhassett /* issue a reset */ 535*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 536*719f82d3SEliot Blennerhassett HPI_ISTREAM_RESET); 537*719f82d3SEliot Blennerhassett hm.adapter_index = phm->adapter_index; 538*719f82d3SEliot Blennerhassett hm.obj_index = phm->obj_index; 539*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 540*719f82d3SEliot Blennerhassett hpios_msgxlock_lock(&msgx_lock); 541*719f82d3SEliot Blennerhassett if (hr.error) { 542*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 543*719f82d3SEliot Blennerhassett obj_index].h_owner = h_owner; 544*719f82d3SEliot Blennerhassett phr->error = hr.error; 545*719f82d3SEliot Blennerhassett } else { 546*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 547*719f82d3SEliot Blennerhassett obj_index].open_flag = 0; 548*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 549*719f82d3SEliot Blennerhassett obj_index].h_owner = NULL; 550*719f82d3SEliot Blennerhassett } 551*719f82d3SEliot Blennerhassett } else { 552*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(WARNING, 553*719f82d3SEliot Blennerhassett "%p trying to close %d instream %d owned by %p\n", 554*719f82d3SEliot Blennerhassett h_owner, phm->adapter_index, phm->obj_index, 555*719f82d3SEliot Blennerhassett instream_user_open[phm->adapter_index][phm-> 556*719f82d3SEliot Blennerhassett obj_index].h_owner); 557*719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_OBJ_NOT_OPEN; 558*719f82d3SEliot Blennerhassett } 559*719f82d3SEliot Blennerhassett hpios_msgxlock_un_lock(&msgx_lock); 560*719f82d3SEliot Blennerhassett } 561*719f82d3SEliot Blennerhassett 562*719f82d3SEliot Blennerhassett static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, 563*719f82d3SEliot Blennerhassett void *h_owner) 564*719f82d3SEliot Blennerhassett { 565*719f82d3SEliot Blennerhassett 566*719f82d3SEliot Blennerhassett struct hpi_message hm; 567*719f82d3SEliot Blennerhassett struct hpi_response hr; 568*719f82d3SEliot Blennerhassett 569*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0); 570*719f82d3SEliot Blennerhassett 571*719f82d3SEliot Blennerhassett hpios_msgxlock_lock(&msgx_lock); 572*719f82d3SEliot Blennerhassett 573*719f82d3SEliot Blennerhassett if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag) 574*719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_OBJ_ALREADY_OPEN; 575*719f82d3SEliot Blennerhassett else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index] 576*719f82d3SEliot Blennerhassett [phm->obj_index].h.error) 577*719f82d3SEliot Blennerhassett memcpy(phr, 578*719f82d3SEliot Blennerhassett &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm-> 579*719f82d3SEliot Blennerhassett obj_index], 580*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 581*719f82d3SEliot Blennerhassett else { 582*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 583*719f82d3SEliot Blennerhassett obj_index].open_flag = 1; 584*719f82d3SEliot Blennerhassett hpios_msgxlock_un_lock(&msgx_lock); 585*719f82d3SEliot Blennerhassett 586*719f82d3SEliot Blennerhassett /* issue a reset */ 587*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 588*719f82d3SEliot Blennerhassett HPI_OSTREAM_RESET); 589*719f82d3SEliot Blennerhassett hm.adapter_index = phm->adapter_index; 590*719f82d3SEliot Blennerhassett hm.obj_index = phm->obj_index; 591*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 592*719f82d3SEliot Blennerhassett 593*719f82d3SEliot Blennerhassett hpios_msgxlock_lock(&msgx_lock); 594*719f82d3SEliot Blennerhassett if (hr.error) { 595*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 596*719f82d3SEliot Blennerhassett obj_index].open_flag = 0; 597*719f82d3SEliot Blennerhassett phr->error = hr.error; 598*719f82d3SEliot Blennerhassett } else { 599*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 600*719f82d3SEliot Blennerhassett obj_index].open_flag = 1; 601*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 602*719f82d3SEliot Blennerhassett obj_index].h_owner = h_owner; 603*719f82d3SEliot Blennerhassett memcpy(phr, 604*719f82d3SEliot Blennerhassett &rESP_HPI_OSTREAM_OPEN[phm->adapter_index] 605*719f82d3SEliot Blennerhassett [phm->obj_index], 606*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 607*719f82d3SEliot Blennerhassett } 608*719f82d3SEliot Blennerhassett } 609*719f82d3SEliot Blennerhassett hpios_msgxlock_un_lock(&msgx_lock); 610*719f82d3SEliot Blennerhassett } 611*719f82d3SEliot Blennerhassett 612*719f82d3SEliot Blennerhassett static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, 613*719f82d3SEliot Blennerhassett void *h_owner) 614*719f82d3SEliot Blennerhassett { 615*719f82d3SEliot Blennerhassett 616*719f82d3SEliot Blennerhassett struct hpi_message hm; 617*719f82d3SEliot Blennerhassett struct hpi_response hr; 618*719f82d3SEliot Blennerhassett 619*719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0); 620*719f82d3SEliot Blennerhassett 621*719f82d3SEliot Blennerhassett hpios_msgxlock_lock(&msgx_lock); 622*719f82d3SEliot Blennerhassett 623*719f82d3SEliot Blennerhassett if (h_owner == 624*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 625*719f82d3SEliot Blennerhassett obj_index].h_owner) { 626*719f82d3SEliot Blennerhassett /* HPI_DEBUG_LOG(INFO,"closing adapter %d " 627*719f82d3SEliot Blennerhassett "outstream %d owned by %p\n", 628*719f82d3SEliot Blennerhassett phm->wAdapterIndex, phm->wObjIndex, hOwner); */ 629*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 630*719f82d3SEliot Blennerhassett obj_index].h_owner = NULL; 631*719f82d3SEliot Blennerhassett hpios_msgxlock_un_lock(&msgx_lock); 632*719f82d3SEliot Blennerhassett /* issue a reset */ 633*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 634*719f82d3SEliot Blennerhassett HPI_OSTREAM_RESET); 635*719f82d3SEliot Blennerhassett hm.adapter_index = phm->adapter_index; 636*719f82d3SEliot Blennerhassett hm.obj_index = phm->obj_index; 637*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 638*719f82d3SEliot Blennerhassett hpios_msgxlock_lock(&msgx_lock); 639*719f82d3SEliot Blennerhassett if (hr.error) { 640*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 641*719f82d3SEliot Blennerhassett obj_index].h_owner = h_owner; 642*719f82d3SEliot Blennerhassett phr->error = hr.error; 643*719f82d3SEliot Blennerhassett } else { 644*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 645*719f82d3SEliot Blennerhassett obj_index].open_flag = 0; 646*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 647*719f82d3SEliot Blennerhassett obj_index].h_owner = NULL; 648*719f82d3SEliot Blennerhassett } 649*719f82d3SEliot Blennerhassett } else { 650*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(WARNING, 651*719f82d3SEliot Blennerhassett "%p trying to close %d outstream %d owned by %p\n", 652*719f82d3SEliot Blennerhassett h_owner, phm->adapter_index, phm->obj_index, 653*719f82d3SEliot Blennerhassett outstream_user_open[phm->adapter_index][phm-> 654*719f82d3SEliot Blennerhassett obj_index].h_owner); 655*719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_OBJ_NOT_OPEN; 656*719f82d3SEliot Blennerhassett } 657*719f82d3SEliot Blennerhassett hpios_msgxlock_un_lock(&msgx_lock); 658*719f82d3SEliot Blennerhassett } 659*719f82d3SEliot Blennerhassett 660*719f82d3SEliot Blennerhassett static u16 adapter_prepare(u16 adapter) 661*719f82d3SEliot Blennerhassett { 662*719f82d3SEliot Blennerhassett struct hpi_message hm; 663*719f82d3SEliot Blennerhassett struct hpi_response hr; 664*719f82d3SEliot Blennerhassett 665*719f82d3SEliot Blennerhassett /* Open the adapter and streams */ 666*719f82d3SEliot Blennerhassett u16 i; 667*719f82d3SEliot Blennerhassett 668*719f82d3SEliot Blennerhassett /* call to HPI_ADAPTER_OPEN */ 669*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 670*719f82d3SEliot Blennerhassett HPI_ADAPTER_OPEN); 671*719f82d3SEliot Blennerhassett hm.adapter_index = adapter; 672*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 673*719f82d3SEliot Blennerhassett memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr, 674*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_ADAPTER_OPEN[0])); 675*719f82d3SEliot Blennerhassett if (hr.error) 676*719f82d3SEliot Blennerhassett return hr.error; 677*719f82d3SEliot Blennerhassett 678*719f82d3SEliot Blennerhassett /* call to HPI_ADAPTER_GET_INFO */ 679*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 680*719f82d3SEliot Blennerhassett HPI_ADAPTER_GET_INFO); 681*719f82d3SEliot Blennerhassett hm.adapter_index = adapter; 682*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 683*719f82d3SEliot Blennerhassett if (hr.error) 684*719f82d3SEliot Blennerhassett return hr.error; 685*719f82d3SEliot Blennerhassett 686*719f82d3SEliot Blennerhassett aDAPTER_INFO[adapter].num_outstreams = hr.u.a.num_outstreams; 687*719f82d3SEliot Blennerhassett aDAPTER_INFO[adapter].num_instreams = hr.u.a.num_instreams; 688*719f82d3SEliot Blennerhassett aDAPTER_INFO[adapter].type = hr.u.a.adapter_type; 689*719f82d3SEliot Blennerhassett 690*719f82d3SEliot Blennerhassett gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list[adapter] = 691*719f82d3SEliot Blennerhassett hr.u.a.adapter_type; 692*719f82d3SEliot Blennerhassett gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters++; 693*719f82d3SEliot Blennerhassett if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters > HPI_MAX_ADAPTERS) 694*719f82d3SEliot Blennerhassett gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters = 695*719f82d3SEliot Blennerhassett HPI_MAX_ADAPTERS; 696*719f82d3SEliot Blennerhassett 697*719f82d3SEliot Blennerhassett /* call to HPI_OSTREAM_OPEN */ 698*719f82d3SEliot Blennerhassett for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) { 699*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 700*719f82d3SEliot Blennerhassett HPI_OSTREAM_OPEN); 701*719f82d3SEliot Blennerhassett hm.adapter_index = adapter; 702*719f82d3SEliot Blennerhassett hm.obj_index = i; 703*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 704*719f82d3SEliot Blennerhassett memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr, 705*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); 706*719f82d3SEliot Blennerhassett outstream_user_open[adapter][i].open_flag = 0; 707*719f82d3SEliot Blennerhassett outstream_user_open[adapter][i].h_owner = NULL; 708*719f82d3SEliot Blennerhassett } 709*719f82d3SEliot Blennerhassett 710*719f82d3SEliot Blennerhassett /* call to HPI_ISTREAM_OPEN */ 711*719f82d3SEliot Blennerhassett for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) { 712*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, 713*719f82d3SEliot Blennerhassett HPI_ISTREAM_OPEN); 714*719f82d3SEliot Blennerhassett hm.adapter_index = adapter; 715*719f82d3SEliot Blennerhassett hm.obj_index = i; 716*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 717*719f82d3SEliot Blennerhassett memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr, 718*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); 719*719f82d3SEliot Blennerhassett instream_user_open[adapter][i].open_flag = 0; 720*719f82d3SEliot Blennerhassett instream_user_open[adapter][i].h_owner = NULL; 721*719f82d3SEliot Blennerhassett } 722*719f82d3SEliot Blennerhassett 723*719f82d3SEliot Blennerhassett /* call to HPI_MIXER_OPEN */ 724*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN); 725*719f82d3SEliot Blennerhassett hm.adapter_index = adapter; 726*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 727*719f82d3SEliot Blennerhassett memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, 728*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_MIXER_OPEN[0])); 729*719f82d3SEliot Blennerhassett 730*719f82d3SEliot Blennerhassett return gRESP_HPI_SUBSYS_FIND_ADAPTERS.h.error; 731*719f82d3SEliot Blennerhassett } 732*719f82d3SEliot Blennerhassett 733*719f82d3SEliot Blennerhassett static void HPIMSGX__reset(u16 adapter_index) 734*719f82d3SEliot Blennerhassett { 735*719f82d3SEliot Blennerhassett int i; 736*719f82d3SEliot Blennerhassett u16 adapter; 737*719f82d3SEliot Blennerhassett struct hpi_response hr; 738*719f82d3SEliot Blennerhassett 739*719f82d3SEliot Blennerhassett if (adapter_index == HPIMSGX_ALLADAPTERS) { 740*719f82d3SEliot Blennerhassett /* reset all responses to contain errors */ 741*719f82d3SEliot Blennerhassett hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, 742*719f82d3SEliot Blennerhassett HPI_SUBSYS_FIND_ADAPTERS, 0); 743*719f82d3SEliot Blennerhassett memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr, 744*719f82d3SEliot Blennerhassett sizeof(&gRESP_HPI_SUBSYS_FIND_ADAPTERS)); 745*719f82d3SEliot Blennerhassett 746*719f82d3SEliot Blennerhassett for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) { 747*719f82d3SEliot Blennerhassett 748*719f82d3SEliot Blennerhassett hpi_init_response(&hr, HPI_OBJ_ADAPTER, 749*719f82d3SEliot Blennerhassett HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER); 750*719f82d3SEliot Blennerhassett memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr, 751*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_ADAPTER_OPEN[adapter])); 752*719f82d3SEliot Blennerhassett 753*719f82d3SEliot Blennerhassett hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN, 754*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ); 755*719f82d3SEliot Blennerhassett memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, 756*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_MIXER_OPEN[adapter])); 757*719f82d3SEliot Blennerhassett 758*719f82d3SEliot Blennerhassett for (i = 0; i < HPI_MAX_STREAMS; i++) { 759*719f82d3SEliot Blennerhassett hpi_init_response(&hr, HPI_OBJ_OSTREAM, 760*719f82d3SEliot Blennerhassett HPI_OSTREAM_OPEN, 761*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ); 762*719f82d3SEliot Blennerhassett memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], 763*719f82d3SEliot Blennerhassett &hr, 764*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_OSTREAM_OPEN[adapter] 765*719f82d3SEliot Blennerhassett [i])); 766*719f82d3SEliot Blennerhassett hpi_init_response(&hr, HPI_OBJ_ISTREAM, 767*719f82d3SEliot Blennerhassett HPI_ISTREAM_OPEN, 768*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ); 769*719f82d3SEliot Blennerhassett memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], 770*719f82d3SEliot Blennerhassett &hr, 771*719f82d3SEliot Blennerhassett sizeof(rESP_HPI_ISTREAM_OPEN[adapter] 772*719f82d3SEliot Blennerhassett [i])); 773*719f82d3SEliot Blennerhassett } 774*719f82d3SEliot Blennerhassett } 775*719f82d3SEliot Blennerhassett } else if (adapter_index < HPI_MAX_ADAPTERS) { 776*719f82d3SEliot Blennerhassett rESP_HPI_ADAPTER_OPEN[adapter_index].h.error = 777*719f82d3SEliot Blennerhassett HPI_ERROR_BAD_ADAPTER; 778*719f82d3SEliot Blennerhassett rESP_HPI_MIXER_OPEN[adapter_index].h.error = 779*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ; 780*719f82d3SEliot Blennerhassett for (i = 0; i < HPI_MAX_STREAMS; i++) { 781*719f82d3SEliot Blennerhassett rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error = 782*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ; 783*719f82d3SEliot Blennerhassett rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error = 784*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ; 785*719f82d3SEliot Blennerhassett } 786*719f82d3SEliot Blennerhassett if (gRESP_HPI_SUBSYS_FIND_ADAPTERS. 787*719f82d3SEliot Blennerhassett s.aw_adapter_list[adapter_index]) { 788*719f82d3SEliot Blennerhassett gRESP_HPI_SUBSYS_FIND_ADAPTERS. 789*719f82d3SEliot Blennerhassett s.aw_adapter_list[adapter_index] = 0; 790*719f82d3SEliot Blennerhassett gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters--; 791*719f82d3SEliot Blennerhassett } 792*719f82d3SEliot Blennerhassett } 793*719f82d3SEliot Blennerhassett } 794*719f82d3SEliot Blennerhassett 795*719f82d3SEliot Blennerhassett static u16 HPIMSGX__init(struct hpi_message *phm, 796*719f82d3SEliot Blennerhassett /* HPI_SUBSYS_CREATE_ADAPTER structure with */ 797*719f82d3SEliot Blennerhassett /* resource list or NULL=find all */ 798*719f82d3SEliot Blennerhassett struct hpi_response *phr 799*719f82d3SEliot Blennerhassett /* response from HPI_ADAPTER_GET_INFO */ 800*719f82d3SEliot Blennerhassett ) 801*719f82d3SEliot Blennerhassett { 802*719f82d3SEliot Blennerhassett hpi_handler_func *entry_point_func; 803*719f82d3SEliot Blennerhassett struct hpi_response hr; 804*719f82d3SEliot Blennerhassett 805*719f82d3SEliot Blennerhassett if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters >= HPI_MAX_ADAPTERS) 806*719f82d3SEliot Blennerhassett return HPI_ERROR_BAD_ADAPTER_NUMBER; 807*719f82d3SEliot Blennerhassett 808*719f82d3SEliot Blennerhassett /* Init response here so we can pass in previous adapter list */ 809*719f82d3SEliot Blennerhassett hpi_init_response(&hr, phm->object, phm->function, 810*719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OBJ); 811*719f82d3SEliot Blennerhassett memcpy(hr.u.s.aw_adapter_list, 812*719f82d3SEliot Blennerhassett gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list, 813*719f82d3SEliot Blennerhassett sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list)); 814*719f82d3SEliot Blennerhassett 815*719f82d3SEliot Blennerhassett entry_point_func = 816*719f82d3SEliot Blennerhassett hpi_lookup_entry_point_function(phm->u.s.resource.r.pci); 817*719f82d3SEliot Blennerhassett 818*719f82d3SEliot Blennerhassett if (entry_point_func) { 819*719f82d3SEliot Blennerhassett HPI_DEBUG_MESSAGE(DEBUG, phm); 820*719f82d3SEliot Blennerhassett entry_point_func(phm, &hr); 821*719f82d3SEliot Blennerhassett } else { 822*719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_PROCESSING_MESSAGE; 823*719f82d3SEliot Blennerhassett return phr->error; 824*719f82d3SEliot Blennerhassett } 825*719f82d3SEliot Blennerhassett if (hr.error == 0) { 826*719f82d3SEliot Blennerhassett /* the adapter was created succesfully 827*719f82d3SEliot Blennerhassett save the mapping for future use */ 828*719f82d3SEliot Blennerhassett hpi_entry_points[hr.u.s.adapter_index] = entry_point_func; 829*719f82d3SEliot Blennerhassett /* prepare adapter (pre-open streams etc.) */ 830*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, 831*719f82d3SEliot Blennerhassett "HPI_SUBSYS_CREATE_ADAPTER successful," 832*719f82d3SEliot Blennerhassett " preparing adapter\n"); 833*719f82d3SEliot Blennerhassett adapter_prepare(hr.u.s.adapter_index); 834*719f82d3SEliot Blennerhassett } 835*719f82d3SEliot Blennerhassett memcpy(phr, &hr, hr.size); 836*719f82d3SEliot Blennerhassett return phr->error; 837*719f82d3SEliot Blennerhassett } 838*719f82d3SEliot Blennerhassett 839*719f82d3SEliot Blennerhassett static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner) 840*719f82d3SEliot Blennerhassett { 841*719f82d3SEliot Blennerhassett int i, adapter, adapter_limit; 842*719f82d3SEliot Blennerhassett 843*719f82d3SEliot Blennerhassett if (!h_owner) 844*719f82d3SEliot Blennerhassett return; 845*719f82d3SEliot Blennerhassett 846*719f82d3SEliot Blennerhassett if (adapter_index == HPIMSGX_ALLADAPTERS) { 847*719f82d3SEliot Blennerhassett adapter = 0; 848*719f82d3SEliot Blennerhassett adapter_limit = HPI_MAX_ADAPTERS; 849*719f82d3SEliot Blennerhassett } else { 850*719f82d3SEliot Blennerhassett adapter = adapter_index; 851*719f82d3SEliot Blennerhassett adapter_limit = adapter + 1; 852*719f82d3SEliot Blennerhassett } 853*719f82d3SEliot Blennerhassett 854*719f82d3SEliot Blennerhassett for (; adapter < adapter_limit; adapter++) { 855*719f82d3SEliot Blennerhassett /* printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */ 856*719f82d3SEliot Blennerhassett for (i = 0; i < HPI_MAX_STREAMS; i++) { 857*719f82d3SEliot Blennerhassett if (h_owner == 858*719f82d3SEliot Blennerhassett outstream_user_open[adapter][i].h_owner) { 859*719f82d3SEliot Blennerhassett struct hpi_message hm; 860*719f82d3SEliot Blennerhassett struct hpi_response hr; 861*719f82d3SEliot Blennerhassett 862*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, 863*719f82d3SEliot Blennerhassett "close adapter %d ostream %d\n", 864*719f82d3SEliot Blennerhassett adapter, i); 865*719f82d3SEliot Blennerhassett 866*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, 867*719f82d3SEliot Blennerhassett HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET); 868*719f82d3SEliot Blennerhassett hm.adapter_index = (u16)adapter; 869*719f82d3SEliot Blennerhassett hm.obj_index = (u16)i; 870*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 871*719f82d3SEliot Blennerhassett 872*719f82d3SEliot Blennerhassett hm.function = HPI_OSTREAM_HOSTBUFFER_FREE; 873*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 874*719f82d3SEliot Blennerhassett 875*719f82d3SEliot Blennerhassett hm.function = HPI_OSTREAM_GROUP_RESET; 876*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 877*719f82d3SEliot Blennerhassett 878*719f82d3SEliot Blennerhassett outstream_user_open[adapter][i].open_flag = 0; 879*719f82d3SEliot Blennerhassett outstream_user_open[adapter][i].h_owner = 880*719f82d3SEliot Blennerhassett NULL; 881*719f82d3SEliot Blennerhassett } 882*719f82d3SEliot Blennerhassett if (h_owner == instream_user_open[adapter][i].h_owner) { 883*719f82d3SEliot Blennerhassett struct hpi_message hm; 884*719f82d3SEliot Blennerhassett struct hpi_response hr; 885*719f82d3SEliot Blennerhassett 886*719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, 887*719f82d3SEliot Blennerhassett "close adapter %d istream %d\n", 888*719f82d3SEliot Blennerhassett adapter, i); 889*719f82d3SEliot Blennerhassett 890*719f82d3SEliot Blennerhassett hpi_init_message_response(&hm, &hr, 891*719f82d3SEliot Blennerhassett HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET); 892*719f82d3SEliot Blennerhassett hm.adapter_index = (u16)adapter; 893*719f82d3SEliot Blennerhassett hm.obj_index = (u16)i; 894*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 895*719f82d3SEliot Blennerhassett 896*719f82d3SEliot Blennerhassett hm.function = HPI_ISTREAM_HOSTBUFFER_FREE; 897*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 898*719f82d3SEliot Blennerhassett 899*719f82d3SEliot Blennerhassett hm.function = HPI_ISTREAM_GROUP_RESET; 900*719f82d3SEliot Blennerhassett hw_entry_point(&hm, &hr); 901*719f82d3SEliot Blennerhassett 902*719f82d3SEliot Blennerhassett instream_user_open[adapter][i].open_flag = 0; 903*719f82d3SEliot Blennerhassett instream_user_open[adapter][i].h_owner = NULL; 904*719f82d3SEliot Blennerhassett } 905*719f82d3SEliot Blennerhassett } 906*719f82d3SEliot Blennerhassett } 907*719f82d3SEliot Blennerhassett } 908