Logo Search packages:      
Sourcecode: alsa-driver version File versions

hpimsgx.c

/******************************************************************************

    AudioScience HPI driver
    Copyright (C) 1997-2003  AudioScience Inc. <support@audioscience.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of version 2 of the GNU General Public License as
    published by the Free Software Foundation;

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Extended Message Function With Response Cacheing

(C) Copyright AudioScience Inc. 2002
*****************************************************************************/
#define SOURCEFILE_NAME "hpimsgx.c"
#include "hpi_internal.h"
#include "hpimsginit.h"
#include "hpimsgx.h"
#include "hpidebug.h"

static struct pci_device_id asihpi_pci_tbl[] = {
#include "hpipcida.h"
};

static struct hpios_spinlock msgxLock;

static HPI_HandlerFunc *hpi_entry_points[HPI_MAX_ADAPTERS];

static HPI_HandlerFunc *HPI_LookupEntryPointFunction(
      struct hpi_pci *PciInfo
)
{

      int i;

      for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
            if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
                  && asihpi_pci_tbl[i].vendor != PciInfo->wVendorId)
                  continue;
            if (asihpi_pci_tbl[i].device != PCI_ANY_ID
                  && asihpi_pci_tbl[i].device != PciInfo->wDeviceId)
                  continue;
            if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
                  && asihpi_pci_tbl[i].subvendor !=
                  PciInfo->wSubSysVendorId)
                  continue;
            if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
                  && asihpi_pci_tbl[i].subdevice !=
                  PciInfo->wSubSysDeviceId)
                  continue;

            HPI_DEBUG_LOG(DEBUG, " %x,%lu\n", i,
                  asihpi_pci_tbl[i].driver_data);
            return (HPI_HandlerFunc *) asihpi_pci_tbl[i].driver_data;
      }

      return NULL;
}

static inline void HW_EntryPoint(
      struct hpi_message *phm,
      struct hpi_response *phr
)
{

      HPI_HandlerFunc *ep;

      if (phm->wAdapterIndex < HPI_MAX_ADAPTERS) {
            ep = (HPI_HandlerFunc *) hpi_entry_points[phm->wAdapterIndex];
            if (ep) {
                  HPI_DEBUG_MESSAGE(DEBUG, phm);
                  ep(phm, phr);
                  HPI_DEBUG_RESPONSE(phr);
                  return;
            }
      }
      HPI_InitResponse(phr, phm->wObject, phm->wFunction,
            HPI_ERROR_PROCESSING_MESSAGE);
}

static void AdapterOpen(
      struct hpi_message *phm,
      struct hpi_response *phr
);
static void AdapterClose(
      struct hpi_message *phm,
      struct hpi_response *phr
);

static void MixerOpen(
      struct hpi_message *phm,
      struct hpi_response *phr
);
static void MixerClose(
      struct hpi_message *phm,
      struct hpi_response *phr
);

static void OutStreamOpen(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
);
static void OutStreamClose(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
);
static void InStreamOpen(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
);
static void InStreamClose(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
);

static void HPIMSGX_Reset(
      u16 wAdapterIndex
);
static u16 HPIMSGX_Init(
      struct hpi_message *phm,
      struct hpi_response *phr
);
static void HPIMSGX_Cleanup(
      u16 wAdapterIndex,
      void *hOwner
);

#ifndef DISABLE_PRAGMA_PACK1
#pragma pack(push, 1)
#endif

struct hpi_subsys_response {
      struct hpi_response_header h;
      struct hpi_subsys_res s;
};

struct hpi_adapter_response {
      struct hpi_response_header h;
      struct hpi_adapter_res a;
};

struct hpi_mixer_response {
      struct hpi_response_header h;
      struct hpi_mixer_res m;
};

struct hpi_stream_response {
      struct hpi_response_header h;
      struct hpi_stream_res d;
};

struct adapter_info {
      u16 wType;
      u16 wNumInStreams;
      u16 wNumOutStreams;
};

struct asi_open_state {
      int nOpenFlag;
      void *hOwner;
      u16 wDspIndex;
};

#ifndef DISABLE_PRAGMA_PACK1
#pragma pack(pop)
#endif

/* Globals */
static struct hpi_adapter_response aRESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];

static struct hpi_stream_response
      aRESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];

static struct hpi_stream_response
      aRESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];

static struct hpi_mixer_response aRESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];

static struct hpi_subsys_response gRESP_HPI_SUBSYS_FIND_ADAPTERS;

static struct adapter_info aADAPTER_INFO[HPI_MAX_ADAPTERS];

/* use these to keep track of opens from user mode apps/DLLs */
static struct asi_open_state
      aOStreamUserOpen[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];

static struct asi_open_state
      aIStreamUserOpen[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];

static void SubSysMessage(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{
      switch (phm->wFunction) {
      case HPI_SUBSYS_GET_VERSION:
            HPI_InitResponse(phr, HPI_OBJ_SUBSYSTEM,
                  HPI_SUBSYS_GET_VERSION, 0);
            phr->u.s.dwVersion = HPI_VER >> 8;  /* return major.minor */
            phr->u.s.dwData = HPI_VER;    /* return major.minor.release */
            break;
      case HPI_SUBSYS_OPEN:
            /*do not propagate the message down the chain */
            HPI_InitResponse(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0);
            break;
      case HPI_SUBSYS_CLOSE:
            /*do not propagate the message down the chain */
            HPI_InitResponse(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE, 0);
            HPIMSGX_Cleanup(HPIMSGX_ALLADAPTERS, hOwner);
            break;
      case HPI_SUBSYS_DRIVER_LOAD:
            /* Initialize this module's internal state */
            HpiOs_Msgxlock_Init(&msgxLock);
            memset(&hpi_entry_points, 0, sizeof(hpi_entry_points));
            HpiOs_LockedMem_Init();
            /* Init subsys_findadapters response to no-adapters */
            HPIMSGX_Reset(HPIMSGX_ALLADAPTERS);
            HPI_InitResponse(phr, HPI_OBJ_SUBSYSTEM,
                  HPI_SUBSYS_DRIVER_LOAD, 0);
            /* individual HPIs dont implement driver load */
            HPI_COMMON(phm, phr);
            break;
      case HPI_SUBSYS_DRIVER_UNLOAD:
            HPI_COMMON(phm, phr);
            HPIMSGX_Cleanup(HPIMSGX_ALLADAPTERS, hOwner);
            HpiOs_LockedMem_FreeAll();
            HPI_InitResponse(phr, HPI_OBJ_SUBSYSTEM,
                  HPI_SUBSYS_DRIVER_UNLOAD, 0);
            return;

      case HPI_SUBSYS_GET_INFO:
            HPI_COMMON(phm, phr);
            break;

      case HPI_SUBSYS_FIND_ADAPTERS:
            memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
                  sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
            break;
      case HPI_SUBSYS_GET_NUM_ADAPTERS:
            memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
                  sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
            phr->wFunction = HPI_SUBSYS_GET_NUM_ADAPTERS;
            break;
      case HPI_SUBSYS_GET_ADAPTER:
            {
                  int nCount = phm->wAdapterIndex;
                  int nIndex = 0;
                  HPI_InitResponse(phr, HPI_OBJ_SUBSYSTEM,
                        HPI_SUBSYS_GET_ADAPTER, 0);

                  /* This is complicated by the fact that we want to
                   * "skip" 0's in the adapter list.
                   * First, make sure we are pointing to a
                   * non-zero adapter type.
                   */
                  while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
                        awAdapterList[nIndex] == 0) {
                        nIndex++;
                        if (nIndex >= HPI_MAX_ADAPTERS)
                              break;
                  }
                  while (nCount) {
                        /* move on to the next adapter */
                        nIndex++;
                        if (nIndex >= HPI_MAX_ADAPTERS)
                              break;
                        while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
                              awAdapterList[nIndex] == 0) {
                              nIndex++;
                              if (nIndex >= HPI_MAX_ADAPTERS)
                                    break;
                        }
                        nCount--;
                  }

                  if (nIndex < HPI_MAX_ADAPTERS) {
                        phr->u.s.wAdapterIndex = (u16)nIndex;
                        phr->u.s.awAdapterList[0] =
                              gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
                              awAdapterList[nIndex];
                  } else {
                        phr->u.s.wAdapterIndex = 0;
                        phr->u.s.awAdapterList[0] = 0;
                        phr->wError = HPI_ERROR_BAD_ADAPTER_NUMBER;
                  }
                  break;
            }
      case HPI_SUBSYS_CREATE_ADAPTER:
            HPIMSGX_Init(phm, phr);
            break;
      case HPI_SUBSYS_DELETE_ADAPTER:
            HPIMSGX_Cleanup(phm->wAdapterIndex, hOwner);
            {
                  struct hpi_message hm;
                  struct hpi_response hr;
                  /* call to HPI_ADAPTER_CLOSE */
                  HPI_InitMessage(&hm, HPI_OBJ_ADAPTER,
                        HPI_ADAPTER_CLOSE);
                  hm.wAdapterIndex = phm->wAdapterIndex;
                  HW_EntryPoint(&hm, &hr);
            }
            HW_EntryPoint(phm, phr);
            gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.awAdapterList[phm->
                  wAdapterIndex]
                  = 0;
            hpi_entry_points[phm->wAdapterIndex] = NULL;
            break;
      default:
            HW_EntryPoint(phm, phr);
            break;
      }
}

static void AdapterMessage(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{
      switch (phm->wFunction) {
      case HPI_ADAPTER_OPEN:
            AdapterOpen(phm, phr);
            break;
      case HPI_ADAPTER_CLOSE:
            AdapterClose(phm, phr);
            break;
      default:
            HW_EntryPoint(phm, phr);
            break;
      }
}

static void MixerMessage(
      struct hpi_message *phm,
      struct hpi_response *phr
)
{
      switch (phm->wFunction) {
      case HPI_MIXER_OPEN:
            MixerOpen(phm, phr);
            break;
      case HPI_MIXER_CLOSE:
            MixerClose(phm, phr);
            break;
      default:
            HW_EntryPoint(phm, phr);
            break;
      }
}

static void OStreamMessage(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{
      if (phm->u.d.wStreamIndex >=
            aADAPTER_INFO[phm->wAdapterIndex].wNumOutStreams) {
            HPI_InitResponse(phr, HPI_OBJ_OSTREAM, phm->wFunction,
                  HPI_ERROR_INVALID_OBJ_INDEX);
            return;
      }

      switch (phm->wFunction) {
      case HPI_OSTREAM_OPEN:
            OutStreamOpen(phm, phr, hOwner);
            break;
      case HPI_OSTREAM_CLOSE:
            OutStreamClose(phm, phr, hOwner);
            break;
      default:
            HW_EntryPoint(phm, phr);
            break;
      }
}

static void IStreamMessage(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{
      if (phm->u.d.wStreamIndex >=
            aADAPTER_INFO[phm->wAdapterIndex].wNumInStreams) {
            HPI_InitResponse(phr, HPI_OBJ_ISTREAM, phm->wFunction,
                  HPI_ERROR_INVALID_OBJ_INDEX);
            return;
      }

      switch (phm->wFunction) {
      case HPI_ISTREAM_OPEN:
            InStreamOpen(phm, phr, hOwner);
            break;
      case HPI_ISTREAM_CLOSE:
            InStreamClose(phm, phr, hOwner);
            break;
      default:
            HW_EntryPoint(phm, phr);
            break;
      }
}

/* NOTE: HPI_Message() must be defined in the driver as a wrapper for
 * HPI_MessageEx so that functions in hpifunc.c compile.
 */
void HPI_MessageEx(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{
      HPI_DEBUG_MESSAGE(DEBUG, phm);

      if (phm->wType != HPI_TYPE_MESSAGE) {
            HPI_InitResponse(phr, phm->wObject, phm->wFunction,
                  HPI_ERROR_INVALID_TYPE);
            return;
      }

      if (phm->wAdapterIndex >= HPI_MAX_ADAPTERS &&
            phm->wAdapterIndex != HPIMSGX_ALLADAPTERS) {
            HPI_InitResponse(phr, phm->wObject, phm->wFunction,
                  HPI_ERROR_BAD_ADAPTER_NUMBER);
            return;
      }

      switch (phm->wObject) {
      case HPI_OBJ_SUBSYSTEM:
            SubSysMessage(phm, phr, hOwner);
            break;

      case HPI_OBJ_ADAPTER:
            AdapterMessage(phm, phr, hOwner);
            break;

      case HPI_OBJ_MIXER:
            MixerMessage(phm, phr);
            break;

      case HPI_OBJ_OSTREAM:
            OStreamMessage(phm, phr, hOwner);
            break;

      case HPI_OBJ_ISTREAM:
            IStreamMessage(phm, phr, hOwner);
            break;

      default:
            HW_EntryPoint(phm, phr);
            break;
      }
      HPI_DEBUG_RESPONSE(phr);
#if 1
      if (phr->wError >= HPI_ERROR_BACKEND_BASE) {
            void *ep = NULL;
            char *ep_name;

            HPI_DEBUG_MESSAGE(ERROR, phm);

            ep = hpi_entry_points[phm->wAdapterIndex];

            /* Don't need this? Have adapter index in debug info
               Know at driver load time index->backend mapping */
            if (ep == HPI_6000)
                  ep_name = "HPI_6000";
            else if (ep == HPI_6205)
                  ep_name = "HPI_6205";
            else
                  ep_name = "unknown";

            HPI_DEBUG_LOG(ERROR,
                  "HPI %s Response - error# %d\n",
                  ep_name, phr->wError);

            if (hpiDebugLevel >= HPI_DEBUG_LEVEL_VERBOSE)
                  hpi_debug_data((u16 *)phm,
                        sizeof(*phm) / sizeof(u16));
      }
#endif
}

static void AdapterOpen(
      struct hpi_message *phm,
      struct hpi_response *phr
)
{
      HPI_DEBUG_LOG(VERBOSE, "AdapterOpen\n");
      memcpy(phr, &aRESP_HPI_ADAPTER_OPEN[phm->wAdapterIndex],
            sizeof(aRESP_HPI_ADAPTER_OPEN[0]));
}

static void AdapterClose(
      struct hpi_message *phm,
      struct hpi_response *phr
)
{
      HPI_DEBUG_LOG(VERBOSE, "AdapterClose\n");
      HPI_InitResponse(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0);
}

static void MixerOpen(
      struct hpi_message *phm,
      struct hpi_response *phr
)
{
      memcpy(phr, &aRESP_HPI_MIXER_OPEN[phm->wAdapterIndex],
            sizeof(aRESP_HPI_MIXER_OPEN[0]));
}

static void MixerClose(
      struct hpi_message *phm,
      struct hpi_response *phr
)
{
      HPI_InitResponse(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0);
}

static void InStreamOpen(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{

      struct hpi_message hm;
      struct hpi_response hr;

      HPI_InitResponse(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0);

      HpiOs_Msgxlock_Lock(&msgxLock);

      if (aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.wStreamIndex].
            nOpenFlag)
            phr->wError = HPI_ERROR_OBJ_ALREADY_OPEN;
      else if (aRESP_HPI_ISTREAM_OPEN[phm->wAdapterIndex]
            [phm->u.d.wStreamIndex].h.wError)
            memcpy(phr,
                  &aRESP_HPI_ISTREAM_OPEN[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex],
                  sizeof(aRESP_HPI_ISTREAM_OPEN[0][0]));
      else {
            aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.wStreamIndex].
                  nOpenFlag = 1;
            HpiOs_Msgxlock_UnLock(&msgxLock);

            /* issue a reset */
            memcpy(&hm, phm, sizeof(hm));
            hm.wFunction = HPI_ISTREAM_RESET;
            HW_EntryPoint(&hm, &hr);

            HpiOs_Msgxlock_Lock(&msgxLock);
            if (hr.wError) {
                  aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].nOpenFlag = 0;
                  phr->wError = hr.wError;
            } else {
                  aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].nOpenFlag = 1;
                  aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].hOwner = hOwner;
                  memcpy(phr,
                        &aRESP_HPI_ISTREAM_OPEN[phm->
                              wAdapterIndex][phm->u.
                              d.
                              wStreamIndex],
                        sizeof(aRESP_HPI_ISTREAM_OPEN[0][0]));
            }
      }
      HpiOs_Msgxlock_UnLock(&msgxLock);
}

static void InStreamClose(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{

      struct hpi_message hm;
      struct hpi_response hr;

      HPI_InitResponse(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0);

      HpiOs_Msgxlock_Lock(&msgxLock);
      if (hOwner ==
            aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.wStreamIndex].
            hOwner) {
            /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
               "instream %d owned by %p\n",
               phm->wAdapterIndex, phm->u.d.wStreamIndex, hOwner); */
            aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.wStreamIndex].
                  hOwner = NULL;
            HpiOs_Msgxlock_UnLock(&msgxLock);
            /* issue a reset */
            memcpy(&hm, phm, sizeof(hm));
            hm.wFunction = HPI_ISTREAM_RESET;
            HW_EntryPoint(&hm, &hr);
            HpiOs_Msgxlock_Lock(&msgxLock);
            if (hr.wError) {
                  aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].hOwner = hOwner;
                  phr->wError = hr.wError;
            } else {
                  aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].nOpenFlag = 0;
                  aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].hOwner = NULL;
            }
      } else {
            HPI_DEBUG_LOG(WARNING,
                  "%p trying to close %d instream %d owned by %p\n",
                  hOwner, phm->wAdapterIndex,
                  phm->u.d.wStreamIndex,
                  aIStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].hOwner);
            phr->wError = HPI_ERROR_OBJ_NOT_OPEN;
      }
      HpiOs_Msgxlock_UnLock(&msgxLock);
}

static void OutStreamOpen(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{

      struct hpi_message hm;
      struct hpi_response hr;

      HPI_InitResponse(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0);

      HpiOs_Msgxlock_Lock(&msgxLock);

      if (aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.wStreamIndex].
            nOpenFlag)
            phr->wError = HPI_ERROR_OBJ_ALREADY_OPEN;
      else if (aRESP_HPI_OSTREAM_OPEN[phm->wAdapterIndex]
            [phm->u.d.wStreamIndex].h.wError)
            memcpy(phr,
                  &aRESP_HPI_OSTREAM_OPEN[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex],
                  sizeof(aRESP_HPI_OSTREAM_OPEN[0][0]));
      else {
            aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.wStreamIndex].
                  nOpenFlag = 1;
            HpiOs_Msgxlock_UnLock(&msgxLock);

            /* issue a reset */
            memcpy(&hm, phm, sizeof(hm));
            hm.wFunction = HPI_OSTREAM_RESET;
            HW_EntryPoint(&hm, &hr);

            HpiOs_Msgxlock_Lock(&msgxLock);
            if (hr.wError) {
                  aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].nOpenFlag = 0;
                  phr->wError = hr.wError;
            } else {
                  aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].nOpenFlag = 1;
                  aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].hOwner = hOwner;
                  memcpy(phr,
                        &aRESP_HPI_OSTREAM_OPEN[phm->
                              wAdapterIndex][phm->u.
                              d.
                              wStreamIndex],
                        sizeof(aRESP_HPI_OSTREAM_OPEN[0][0]));
            }
      }
      HpiOs_Msgxlock_UnLock(&msgxLock);
}

static void OutStreamClose(
      struct hpi_message *phm,
      struct hpi_response *phr,
      void *hOwner
)
{

      struct hpi_message hm;
      struct hpi_response hr;

      HPI_InitResponse(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0);

      HpiOs_Msgxlock_Lock(&msgxLock);

      if (hOwner ==
            aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.wStreamIndex].
            hOwner) {
            /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
               "outstream %d owned by %p\n",
               phm->wAdapterIndex, phm->u.d.wStreamIndex, hOwner); */
            aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.wStreamIndex].
                  hOwner = NULL;
            HpiOs_Msgxlock_UnLock(&msgxLock);
            /* issue a reset */
            memcpy(&hm, phm, sizeof(hm));
            hm.wFunction = HPI_OSTREAM_RESET;
            HW_EntryPoint(&hm, &hr);
            HpiOs_Msgxlock_Lock(&msgxLock);
            if (hr.wError) {
                  aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].hOwner = hOwner;
                  phr->wError = hr.wError;
            } else {
                  aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].nOpenFlag = 0;
                  aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].hOwner = NULL;
            }
      } else {
            HPI_DEBUG_LOG(WARNING,
                  "%p trying to close %d outstream %d owned by %p\n",
                  hOwner, phm->wAdapterIndex,
                  phm->u.d.wStreamIndex,
                  aOStreamUserOpen[phm->wAdapterIndex][phm->u.d.
                        wStreamIndex].hOwner);
            phr->wError = HPI_ERROR_OBJ_NOT_OPEN;
      }
      HpiOs_Msgxlock_UnLock(&msgxLock);
}

static u16 AdapterPrepare(
      u16 wAdapter
)
{
      struct hpi_message hm;
      struct hpi_response hr;

      /* Open the adapter and streams */
      u16 i;

      /* call to HPI_ADAPTER_OPEN */
      HPI_InitMessage(&hm, HPI_OBJ_ADAPTER, HPI_ADAPTER_OPEN);
      hm.wAdapterIndex = wAdapter;
      HW_EntryPoint(&hm, &hr);
      memcpy(&aRESP_HPI_ADAPTER_OPEN[wAdapter], &hr,
            sizeof(aRESP_HPI_ADAPTER_OPEN[0]));
      if (hr.wError)
            return hr.wError;

      /* call to HPI_ADAPTER_GET_INFO */
      HPI_InitMessage(&hm, HPI_OBJ_ADAPTER, HPI_ADAPTER_GET_INFO);
      hm.wAdapterIndex = wAdapter;
      HW_EntryPoint(&hm, &hr);
      if (hr.wError)
            return hr.wError;

      aADAPTER_INFO[wAdapter].wNumOutStreams = hr.u.a.wNumOStreams;
      aADAPTER_INFO[wAdapter].wNumInStreams = hr.u.a.wNumIStreams;
      aADAPTER_INFO[wAdapter].wType = hr.u.a.wAdapterType;

      gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.awAdapterList[wAdapter] =
            hr.u.a.wAdapterType;
      gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.wNumAdapters++;
      if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.wNumAdapters > HPI_MAX_ADAPTERS)
            gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.wNumAdapters =
                  HPI_MAX_ADAPTERS;

      /* call to HPI_OSTREAM_OPEN */
      for (i = 0; i < aADAPTER_INFO[wAdapter].wNumOutStreams; i++) {
            HPI_InitMessage(&hm, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN);
            hm.wAdapterIndex = wAdapter;
            hm.u.d.wStreamIndex = i;
            HW_EntryPoint(&hm, &hr);
            memcpy(&aRESP_HPI_OSTREAM_OPEN[wAdapter][i], &hr,
                  sizeof(aRESP_HPI_OSTREAM_OPEN[0][0]));
            aOStreamUserOpen[wAdapter][i].nOpenFlag = 0;
            aOStreamUserOpen[wAdapter][i].hOwner = NULL;
      }

      /* call to HPI_ISTREAM_OPEN */
      for (i = 0; i < aADAPTER_INFO[wAdapter].wNumInStreams; i++) {
            HPI_AdapterFindObject(NULL, wAdapter, HPI_OBJ_ISTREAM, i,
                  &aIStreamUserOpen[wAdapter][i].wDspIndex);
            HPI_InitMessage(&hm, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN);
            hm.wAdapterIndex = wAdapter;
            hm.u.d.wStreamIndex = i;
            hm.wDspIndex = aIStreamUserOpen[wAdapter][i].wDspIndex;
            HW_EntryPoint(&hm, &hr);
            memcpy(&aRESP_HPI_ISTREAM_OPEN[wAdapter][i], &hr,
                  sizeof(aRESP_HPI_ISTREAM_OPEN[0][0]));
            aIStreamUserOpen[wAdapter][i].nOpenFlag = 0;
            aIStreamUserOpen[wAdapter][i].hOwner = NULL;
      }

      /* call to HPI_MIXER_OPEN */
      HPI_InitMessage(&hm, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
      hm.wAdapterIndex = wAdapter;
      HW_EntryPoint(&hm, &hr);
      memcpy(&aRESP_HPI_MIXER_OPEN[wAdapter], &hr,
            sizeof(aRESP_HPI_MIXER_OPEN[0]));

      return gRESP_HPI_SUBSYS_FIND_ADAPTERS.h.wError;
}

static void HPIMSGX_Reset(
      u16 wAdapterIndex
)
{
      int i;
      u16 wAdapter;
      struct hpi_response hr;

      if (wAdapterIndex == HPIMSGX_ALLADAPTERS) {
            /* reset all responses to contain errors */
            HPI_InitResponse(&hr, HPI_OBJ_SUBSYSTEM,
                  HPI_SUBSYS_FIND_ADAPTERS, 0);
            memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
                  sizeof(&gRESP_HPI_SUBSYS_FIND_ADAPTERS));

            for (wAdapter = 0; wAdapter < HPI_MAX_ADAPTERS; wAdapter++) {

                  HPI_InitResponse(&hr, HPI_OBJ_ADAPTER,
                        HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER);
                  memcpy(&aRESP_HPI_ADAPTER_OPEN[wAdapter], &hr,
                        sizeof(aRESP_HPI_ADAPTER_OPEN[wAdapter]));

                  HPI_InitResponse(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN,
                        HPI_ERROR_INVALID_OBJ);
                  memcpy(&aRESP_HPI_MIXER_OPEN[wAdapter], &hr,
                        sizeof(aRESP_HPI_MIXER_OPEN[wAdapter]));

                  for (i = 0; i < HPI_MAX_STREAMS; i++) {
                        HPI_InitResponse(&hr, HPI_OBJ_OSTREAM,
                              HPI_OSTREAM_OPEN,
                              HPI_ERROR_INVALID_OBJ);
                        memcpy(&aRESP_HPI_OSTREAM_OPEN[wAdapter][i],
                              &hr,
                              sizeof(aRESP_HPI_OSTREAM_OPEN
                                    [wAdapter]
                                    [i]));
                        HPI_InitResponse(&hr, HPI_OBJ_ISTREAM,
                              HPI_ISTREAM_OPEN,
                              HPI_ERROR_INVALID_OBJ);
                        memcpy(&aRESP_HPI_ISTREAM_OPEN[wAdapter][i],
                              &hr,
                              sizeof(aRESP_HPI_ISTREAM_OPEN
                                    [wAdapter]
                                    [i]));
                  }
            }
      } else if (wAdapterIndex < HPI_MAX_ADAPTERS) {
            aRESP_HPI_ADAPTER_OPEN[wAdapterIndex].h.wError =
                  HPI_ERROR_BAD_ADAPTER;
            aRESP_HPI_MIXER_OPEN[wAdapterIndex].h.wError =
                  HPI_ERROR_INVALID_OBJ;
            for (i = 0; i < HPI_MAX_STREAMS; i++) {
                  aRESP_HPI_OSTREAM_OPEN[wAdapterIndex][i].h.wError =
                        HPI_ERROR_INVALID_OBJ;
                  aRESP_HPI_ISTREAM_OPEN[wAdapterIndex][i].h.wError =
                        HPI_ERROR_INVALID_OBJ;
            }
            if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
                  awAdapterList[wAdapterIndex]) {
                  gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
                        awAdapterList[wAdapterIndex] = 0;
                  gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.wNumAdapters--;
            }
      }
}

static u16 HPIMSGX_Init(
      struct hpi_message *phm,
      /* HPI_SUBSYS_CREATE_ADAPTER structure with */
      /* resource list or NULL=find all */
      struct hpi_response *phr
      /* response from HPI_ADAPTER_GET_INFO */
)
{
      HPI_HandlerFunc *entry_point_func;
      struct hpi_response hr;

      if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.wNumAdapters >= HPI_MAX_ADAPTERS)
            return HPI_ERROR_BAD_ADAPTER_NUMBER;

      /* Init response here so we can pass in previous adapter list */
      HPI_InitResponse(&hr, phm->wObject, phm->wFunction,
            HPI_ERROR_INVALID_OBJ);
      memcpy(hr.u.s.awAdapterList,
            gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.awAdapterList,
            sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.awAdapterList));

      entry_point_func =
            HPI_LookupEntryPointFunction(phm->u.s.Resource.r.Pci);

      if (entry_point_func) {
            HPI_DEBUG_MESSAGE(DEBUG, phm);
            entry_point_func(phm, &hr);
      } else {
            phr->wError = HPI_ERROR_PROCESSING_MESSAGE;
            return phr->wError;
      }
      if (hr.wError == 0) {
            /* the adapter was created succesfully
               save the mapping for future use */
            hpi_entry_points[hr.u.s.wAdapterIndex] = entry_point_func;
            /* prepare adapter (pre-open streams etc.) */
            HPI_DEBUG_LOG(DEBUG,
                  "HPI_SUBSYS_CREATE_ADAPTER successful,"
                  " preparing adapter\n");
            AdapterPrepare(hr.u.s.wAdapterIndex);
      }
      memcpy(phr, &hr, hr.wSize);
      return phr->wError;
}

static void HPIMSGX_Cleanup(
      u16 wAdapterIndex,
      void *hOwner
)
{
      int i, wAdapter, wAdapterLimit;

      if (!hOwner)
            return;

      if (wAdapterIndex == HPIMSGX_ALLADAPTERS) {
            wAdapter = 0;
            wAdapterLimit = HPI_MAX_ADAPTERS;
      } else {
            wAdapter = wAdapterIndex;
            wAdapterLimit = wAdapter + 1;
      }

      for (; wAdapter < wAdapterLimit; wAdapter++) {
            /*      printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */
            for (i = 0; i < HPI_MAX_STREAMS; i++) {
                  if (hOwner == aOStreamUserOpen[wAdapter][i].hOwner) {
                        struct hpi_message hm;
                        struct hpi_response hr;

                        HPI_DEBUG_LOG(DEBUG,
                              "Close adapter %d ostream %d\n",
                              wAdapter, i);

                        HPI_InitMessage(&hm, HPI_OBJ_OSTREAM,
                              HPI_OSTREAM_RESET);
                        hm.wAdapterIndex = (u16)wAdapter;
                        hm.u.d.wStreamIndex = (u16)i;
                        /* hm.wDspIndex = Always 0 for Ostream */
                        HW_EntryPoint(&hm, &hr);

                        hm.wFunction = HPI_OSTREAM_HOSTBUFFER_FREE;
                        HW_EntryPoint(&hm, &hr);

                        hm.wFunction = HPI_OSTREAM_GROUP_RESET;
                        HW_EntryPoint(&hm, &hr);

                        aOStreamUserOpen[wAdapter][i].nOpenFlag = 0;
                        aOStreamUserOpen[wAdapter][i].hOwner = NULL;
                  }
                  if (hOwner == aIStreamUserOpen[wAdapter][i].hOwner) {
                        struct hpi_message hm;
                        struct hpi_response hr;

                        HPI_DEBUG_LOG(DEBUG,
                              "Close adapter %d istream %d\n",
                              wAdapter, i);

                        HPI_InitMessage(&hm, HPI_OBJ_ISTREAM,
                              HPI_ISTREAM_RESET);
                        hm.wAdapterIndex = (u16)wAdapter;
                        hm.u.d.wStreamIndex = (u16)i;
                        hm.wDspIndex =
                              aIStreamUserOpen[wAdapter][i].
                              wDspIndex;
                        HW_EntryPoint(&hm, &hr);

                        hm.wFunction = HPI_ISTREAM_HOSTBUFFER_FREE;
                        HW_EntryPoint(&hm, &hr);

                        hm.wFunction = HPI_ISTREAM_GROUP_RESET;
                        HW_EntryPoint(&hm, &hr);

                        aIStreamUserOpen[wAdapter][i].nOpenFlag = 0;
                        aIStreamUserOpen[wAdapter][i].hOwner = NULL;
                  }
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index