~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/asihpi/hpimsgx.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.10 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.83 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.153 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.200 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.200 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.76 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 19 Extended 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 
 31 static struct pci_device_id asihpi_pci_tbl[] = {
 32 #include "hpipcida.h"
 33 };
 34 
 35 static struct hpios_spinlock msgx_lock;
 36 
 37 static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
 38 
 39 static 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 
 71 static 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 
 82 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
 83 static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
 84 
 85 static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
 86 static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
 87 
 88 static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
 89         void *h_owner);
 90 static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
 91         void *h_owner);
 92 static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
 93         void *h_owner);
 94 static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
 95         void *h_owner);
 96 
 97 static void HPIMSGX__reset(u16 adapter_index);
 98 
 99 static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
100 static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
101 
102 #ifndef DISABLE_PRAGMA_PACK1
103 #pragma pack(push, 1)
104 #endif
105 
106 struct hpi_subsys_response {
107         struct hpi_response_header h;
108         struct hpi_subsys_res s;
109 };
110 
111 struct hpi_adapter_response {
112         struct hpi_response_header h;
113         struct hpi_adapter_res a;
114 };
115 
116 struct hpi_mixer_response {
117         struct hpi_response_header h;
118         struct hpi_mixer_res m;
119 };
120 
121 struct hpi_stream_response {
122         struct hpi_response_header h;
123         struct hpi_stream_res d;
124 };
125 
126 struct adapter_info {
127         u16 type;
128         u16 num_instreams;
129         u16 num_outstreams;
130 };
131 
132 struct 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 */
142 static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
143 
144 static struct hpi_stream_response
145         rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
146 
147 static struct hpi_stream_response
148         rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
149 
150 static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
151 
152 static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
153 
154 /* use these to keep track of opens from user mode apps/DLLs */
155 static struct asi_open_state
156         outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
157 
158 static struct asi_open_state
159         instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
160 
161 static 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 
221 static 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 
250 static 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 
265 static 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 
287 static 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  */
312 void 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 
359 static 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 
366 static 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 
372 static 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 
378 static 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 
383 static 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 
433 static 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 
480 static 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 
530 static 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 
578 static 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 
644 static 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 
694 static 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 
732 static 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp