/** * Vp790InitDevice * This function initializes the device and all lines associated with this * device (if line profiles are passed to this function). * * Preconditions: * None (device context is not NULL and is of Vp790 type, which is handled in * higher level software) * * Postconditions: * This device is initialized to the configuration specified in the device * profile and the FXS lines associated with this device are initialized by the * FXS specific AC, DC, and Ringing profiles passed. This function returns an * error code if the device profile trying to be used for initialization is * VP_PTABLE_NULL (either passed or by a non-initialized index). */ VpStatusType Vp790InitDevice( VpDevCtxType *pDevCtx, VpProfilePtrType pDevProfile, /**< The profile pointer for the device * configuration parameters */ VpProfilePtrType pAcProfile, /**< The profile pointer (or index) for * the AC characteristic to apply to the * FXS lines */ VpProfilePtrType pDcProfile, /**< The profile pointer (or index) for * the DC characteristic to apply to the * FXS lines */ VpProfilePtrType pRingProfile, /**< The profile pointer (or index) for * the Ringing characteristic to apply to * the FXS lines */ VpProfilePtrType pFxoAcProfile, /**< The profile pointer (or index) for * the AC characteristic to apply to the * FXO lines */ VpProfilePtrType pFxoCfgProfile)/**< The profile pointer for the FXO * specific supervision paramaters. */ { VpLineCtxType *pLineCtx; Vp790DeviceObjectType *pDevObj = pDevCtx->pDevObj; VpDeviceIdType deviceId = pDevObj->deviceId; uint8 ecVal[] = {VP790_EC_CH1, VP790_EC_CH2, VP790_EC_CH3, VP790_EC_CH4}; uint8 gpioDir[] = {VP790_GIO_DIR_ALL_OUTPUT}; uint8 maxChan = pDevObj->staticInfo.maxChannels; VpProfilePtrType pDevProf; uint8 chan; VpStatusType status = VP_STATUS_SUCCESS; int profIndex = VpGetProfileIndex(pDevProfile); /* * Get Profile Index returns -1 if the profile passed is a pointer or * of VP_PTABLE_NULL type. Otherwise it returns the index */ if (profIndex < 0) { /* * A pointer is passed or VP_PTABLE_NULL. If it's a pointer, make * sure the content is valid for the profile type. */ if (pDevProfile != VP_PTABLE_NULL) { if(VpVerifyProfileType(VP_PROFILE_DEVICE, pDevProfile) != TRUE) { return VP_STATUS_ERR_PROFILE; } } pDevProf = pDevProfile; } else if (profIndex < VP_CSLAC_DEV_PROF_TABLE_SIZE) { pDevProf = pDevObj->devProfileTable.pDevProfileTable[profIndex]; if ((pDevProf == VP_PTABLE_NULL) || (!(pDevObj->profEntry.devProfEntry & (0x01 << profIndex)))) { return VP_STATUS_ERR_PROFILE; } } else { return VP_STATUS_ERR_PROFILE; } VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC); pDevObj->status.globStatReg = 0; pDevObj->status.calibrating = 0; pDevObj->timeStamp = 0; pDevObj->status.state = VP_DEV_INIT_IN_PROGRESS; if (pDevProf != VP_PTABLE_NULL) { pDevObj->devProfileData.pcmClkRate = (uint16)(((pDevProf[VP790_DEV_PROFILE_PCLK_MSB] << 8) & 0xFF00) | (pDevProf[VP790_DEV_PROFILE_PCLK_LSB] & 0x00FF)); pDevObj->devProfileData.devCfg1 = (uint8)(pDevProf[VP790_DEV_PROFILE_DEVCFG1]); pDevObj->devProfileData.mClkCorrection = (uint8)(pDevProf[VP790_DEV_PROFILE_MCLK_CORR]); pDevObj->devProfileData.clockSlot = (uint8)(pDevProf[VP790_DEV_PROFILE_CLOCK_SLOT]); pDevObj->devProfileData.maxNumInterrupts = (uint8)(pDevProf[VP790_DEV_PROFILE_MAX_EVENTS]); pDevObj->devProfileData.tickRate = (uint16)(((pDevProf[VP790_DEV_PROFILE_TICKRATE_MSB] << 8) & 0xFF00) | (pDevProf[VP790_DEV_PROFILE_TICKRATE_LSB] & 0x00FF)); pDevObj->devProfileData.calibrationTime = MS_TO_TICKRATE(20, pDevObj->devProfileData.tickRate); } else { pDevObj->status.state &= ~VP_DEV_INIT_IN_PROGRESS; VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_ERR_PROFILE; } /* Initialize device */ /* * If not successful, the Clock Fail bit did not clear so return error code */ if ((status = Vp790Init(pDevCtx)) != VP_STATUS_SUCCESS) { pDevObj->status.state &= ~(VP_DEV_INIT_IN_PROGRESS | VP_DEV_INIT_CMP); /* * Clear the tickRate, which is used by VpApiTick() to indicate VpInitDevice() was * completed. This prevents VpApiTick() from generating events on a non-initialized device * context/object. */ pDevObj->devProfileData.tickRate = 0; VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return status; } VpMpiCmdWrapper(deviceId, ecVal[0], VP790_GIO_DIR_WRT, VP790_GIO_DIR_LEN, gpioDir); if (pDevProf[VP_PROFILE_VERSION] >= VP_CSLAC_DEV_PROFILE_VERSION_LINECARD_PARAM) { /* This profile contains the Linecard parameters value */ VpMpiCmdWrapper(deviceId, ecVal[0], VP790_LINECARD_PARAM_WRT, VP790_LINECARD_PARAM_LEN, (VpProfileDataType *)(&pDevProf[VP790_DEV_PROFILE_LINECARD_PARAM_DATA0])); } /* Initialize each channel */ for (chan = 0; chan < maxChan; chan++) { /* * For Init Line to work, the device cannot be non-initialized because * the init line function tries to set the line state. Therefore, * temporarily set the device init flag to TRUE then immediately after * line init, set back to FALSE until device init is complete */ pLineCtx = pDevCtx->pLineCtx[chan]; if (pLineCtx != VP_NULL) { status = Vp790InitLine(pLineCtx, pAcProfile, pDcProfile, pRingProfile); if (status != VP_STATUS_SUCCESS) { pDevObj->status.state &= ~(VP_DEV_INIT_IN_PROGRESS | VP_DEV_INIT_CMP); /* * Clear the tickRate, which is used by VpApiTick() to indicate VpInitDevice() was * completed. This prevents VpApiTick() from generating events on a non-initialized * device context/object. */ pDevObj->devProfileData.tickRate = 0; VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return status; } } } VpImplementDefaultSettings(pDevCtx, VP_NULL); /* * This clears the Init Line Events and any other erroneous event that * may have been created due to initialization */ Vp790FlushEvents(pDevCtx); /* Start the device Calibration */ Vp790CalCodecInt(pDevCtx); VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_SUCCESS; } /* Vp790InitDevice */
/** * Vp790InitProfile * This function is used to initialize profile tables in Vp790. * * Preconditions: * The device associated with this line must be initialized. * * Postconditions: * The line pointed to by the line context passed is initialized with the * profile data specified. This function returns the success code if the device * associated with this line is initialized and the index being specified is * within the range of the device profile table. */ VpStatusType Vp790InitProfile( VpDevCtxType *pDevCtx, VpProfileType type, VpProfilePtrType pProfileIndex, VpProfilePtrType pProfile) { Vp790DeviceObjectType *pDevObj = pDevCtx->pDevObj; VpDeviceIdType deviceId = pDevObj->deviceId; VpStatusType status = VP_STATUS_SUCCESS; /* * If the profile passed is an index, indicated by Get Profile Index return * value of > -1, return an error (cannot init an indexed entry with an * index). */ int profileIndex = VpGetProfileIndex(pProfile); if (profileIndex >= 0) { return VP_STATUS_INVALID_ARG; } /* * If pProfileIndex is -1, the profile is of pointer type and invalid, * otherwise it is an index. If it's an index, make sure the range is * valid. */ profileIndex = VpGetProfileIndex(pProfileIndex); if (profileIndex < 0) { return VP_STATUS_INVALID_ARG; } VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC); /* * The correct types are passed, but check to make sure the specific profile * type being initialized is valid as well as the index value */ switch(type) { case VP_PROFILE_DEVICE: if (profileIndex > VP_CSLAC_DEV_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pDevProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_AC: if (profileIndex > VP_CSLAC_AC_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pAcProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_DC: if (profileIndex > VP_CSLAC_DC_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pDcProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_RING: if (profileIndex > VP_CSLAC_RINGING_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pRingingProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_RINGCAD: if (profileIndex > VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pRingingCadProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_TONE: if (profileIndex > VP_CSLAC_TONE_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pToneProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_TONECAD: if (profileIndex > VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pToneCadProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_METER: if (profileIndex > VP_CSLAC_METERING_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pMeteringProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_CID: if (profileIndex > VP_CSLAC_CALLERID_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pCallerIdProfileTable[profileIndex] = pProfile; } break; case VP_PROFILE_FXO_CONFIG: if (profileIndex > VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE) { status = VP_STATUS_INVALID_ARG; } else { pDevObj->devProfileTable.pFxoConfigProfileTable[profileIndex] = pProfile; } break; default: status = VP_STATUS_INVALID_ARG; break; } VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return status; } /* Vp790InitProfile() */
/** * Vp790ConfigLine * This function reloads a line of a device with the specified parameters. * * Preconditions: * The device associated with this line must be initialized. * * Postconditions: * The line pointed to by the line context passed is initialized with the * profile data specified. This function returns the success code if the device * associated with this line is initialized. */ VpStatusType Vp790ConfigLine( VpLineCtxType *pLineCtx, VpProfilePtrType pAcProfile, /**< Pointer to AC coefficient data or * profile index to be applied to this line. */ VpProfilePtrType pDcOrFxoProfile, /**< Pointer to DC Feed (FXS) or Cfg * (FX0) profile or profile index to be * applied to this line. */ VpProfilePtrType pRingProfile) /**< Pointer to Ringing profile or profile * index to apply to this line */ { Vp790LineObjectType *pLineObj = pLineCtx->pLineObj; VpDevCtxType *pDevCtx = pLineCtx->pDevCtx; Vp790DeviceObjectType *pDevObj = pDevCtx->pDevObj; VpProfileDataType *pCurrentProf; uint8 profIndex = VP_PROFILE_MPI_LEN; uint8 ioReg[VP790_IO_REG_LEN]; uint8 ccr4[VP790_CCR4_LEN], ccr4Temp[VP790_CCR4_LEN]; uint8 defaultVals[VP790_LOOP_SUP_LEN] = {0x0D, 0x64, 0x0D, 0x01, 0x30, 0x00, 0x10, 0x0D}; int profTableIndex; uint8 ecVal[] = {VP790_EC_CH1, VP790_EC_CH2, VP790_EC_CH3, VP790_EC_CH4}; uint8 channelId = pLineObj->channelId; VpDeviceIdType deviceId = pDevObj->deviceId; VpProfilePtrType pAcProf = VP_PTABLE_NULL; VpProfilePtrType pDcFxoCfgProf = VP_PTABLE_NULL; VpProfilePtrType pRingProf = VP_PTABLE_NULL; /* Proceed if initialized or in progress, and not calibrating */ if (pDevObj->status.state & (VP_DEV_INIT_CMP | VP_DEV_INIT_IN_PROGRESS)) { if (pDevObj->status.state & VP_DEV_IN_CAL) { return VP_STATUS_DEVICE_BUSY; } } else { return VP_STATUS_DEV_NOT_INITIALIZED; } profTableIndex = VpGetProfileIndex(pAcProfile); if (profTableIndex < 0) { /* * A pointer is passed or VP_PTABLE_NULL. If it's a pointer, make * sure the content is valid for the profile type. */ if (pAcProfile != VP_PTABLE_NULL) { if(VpVerifyProfileType(VP_PROFILE_AC, pAcProfile) != TRUE) { return VP_STATUS_ERR_PROFILE; } } /* If we're here, it's a valid profile pointer -- even if NULL */ pAcProf = pAcProfile; } else if (profTableIndex < VP_CSLAC_AC_PROF_TABLE_SIZE) { pAcProf = pDevObj->devProfileTable.pAcProfileTable[profTableIndex]; if (!(pDevObj->profEntry.acProfEntry & (0x01 << profTableIndex))) { return VP_STATUS_ERR_PROFILE; } } else { return VP_STATUS_ERR_PROFILE; } profTableIndex = VpGetProfileIndex(pDcOrFxoProfile); if (profTableIndex < 0) { /* * A pointer is passed or VP_PTABLE_NULL. If it's a pointer, make * sure the content is valid for the profile type. */ if (pDcOrFxoProfile != VP_PTABLE_NULL) { if (VpVerifyProfileType(VP_PROFILE_DC, pDcOrFxoProfile) != TRUE) { return VP_STATUS_ERR_PROFILE; } } /* If we're here, it's a valid profile pointer -- even if NULL */ pDcFxoCfgProf = pDcOrFxoProfile; } else if (profTableIndex < VP_CSLAC_DC_PROF_TABLE_SIZE) { pDcFxoCfgProf = pDevObj->devProfileTable.pDcProfileTable[profTableIndex]; if (!(pDevObj->profEntry.dcProfEntry & (0x01 << profTableIndex))) { return VP_STATUS_ERR_PROFILE; } } else { return VP_STATUS_ERR_PROFILE; } profTableIndex = VpGetProfileIndex(pRingProfile); if (profTableIndex < 0) { /* * A pointer is passed or VP_PTABLE_NULL. If it's a pointer, make * sure the content is valid for the profile type. */ if (pRingProfile != VP_PTABLE_NULL) { if(VpVerifyProfileType(VP_PROFILE_RING, pRingProfile) != TRUE) { return VP_STATUS_ERR_PROFILE; } } /* If we're here, it's a valid profile pointer -- even if NULL */ pRingProf = pRingProfile; } else if (profTableIndex < VP_CSLAC_RINGING_PROF_TABLE_SIZE) { pRingProf = pDevObj->devProfileTable.pRingingProfileTable[profTableIndex]; if (!(pDevObj->profEntry.ringingProfEntry & (0x01 << profTableIndex))) { return VP_STATUS_ERR_PROFILE; } } else { return VP_STATUS_ERR_PROFILE; } VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC); /* If no AC Profile exists use whatever exists in the device */ if (pAcProfile != VP_PTABLE_NULL) { pCurrentProf = (VpProfileDataType *)pAcProfile; VpMpiCmdWrapper(deviceId, ecVal[channelId], NOOP_CMD, pCurrentProf[profIndex], &pCurrentProf[profIndex + 1]); } /* * The Ring Profile may contain content (command 0x68) that affects * bits controlled only by the API-II. So read the register first, then * determine what bits are allowed to change, and set the register to * the new value. */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_CCR4_RD, VP790_CCR4_LEN, ccr4Temp); /* If no Ringing Profile exists use whatever exists in the device */ if (pRingProfile != VP_PTABLE_NULL) { pCurrentProf = (VpProfileDataType *)pRingProfile; VpMpiCmdWrapper(deviceId, ecVal[channelId], NOOP_CMD, pCurrentProf[profIndex], &pCurrentProf[profIndex + 1]); } /* * Read what ccr4 is now set to. We'll need to adjust because some bits * may not be allowed to be changed by the Ringing Profile */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_CCR4_RD, VP790_CCR4_LEN, ccr4); /* Zero out those bits not controlled by the profile */ ccr4[0] &= (VP790_EXT_RINGING | VP790_CCR4_RTM); /* * Or in the bits controlled by API-II as they existed before this profile * was sent. */ ccr4Temp[0] &= ~(VP790_EXT_RINGING | VP790_CCR4_RTM); ccr4[0] |= ccr4Temp[0]; /* * If we are set to external ringing, RD2 has to be set for auto mode. * Otherwise it's set for manual */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_IO_REG_RD, VP790_IO_REG_LEN, ioReg); /* Set remaining values of ccr4 based on API-II settings */ if (ccr4[0] & VP790_EXT_RINGING) { ioReg[0] |= VP790_IO_REG_RD2_AUTO; if(pLineObj->ringCtrl.zeroCross == VP_OPTION_ZC_NONE) { ccr4[0] |= VP790_CCR4_ZXR_DIS; } else { ccr4[0] &= ~VP790_CCR4_ZXR_DIS; } } else { ioReg[0] &= ~VP790_IO_REG_RD2_AUTO; if(pLineObj->ringCtrl.zeroCross == VP_OPTION_ZC_NONE) { ccr4[0] &= ~VP790_CCR4_ZXR_DIS; } else { ccr4[0] |= VP790_CCR4_ZXR_DIS; } } VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_CCR4_WRT, VP790_CCR4_LEN, ccr4); VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_IO_REG_WRT, VP790_IO_REG_LEN, ioReg); /* If no DC Feed Profile exists use whatever the device default value is */ if (pDcFxoCfgProf != VP_PTABLE_NULL) { pCurrentProf = (VpProfileDataType *)pDcFxoCfgProf; VpMpiCmdWrapper(deviceId, ecVal[channelId], NOOP_CMD, pCurrentProf[profIndex], &pCurrentProf[profIndex + 1]); } else { VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_LOOP_SUP_WRT, VP790_LOOP_SUP_LEN, defaultVals); } VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_SUCCESS; }