/** * VpMake790LineObject() * This function initializes a line context using the information that is * passed. This function is like a C++ constructor. It initializes the passed * line context and line object based on the paramters provided. The passed line * object type should match with the type of device object type. See VP-API * reference guide for more information. * * Preconditions: * This function assumes device context has already been created and * initialized. This function should only be called after downloading the boot * image the device when applicable (like for VCP class of devices). * * Postconditions: * This function initializes the line context/line object. Line related VP-API * functions can be called after calling this function. */ VpStatusType Vp790MakeLineObject( VpTermType termType, uint8 channelId, VpLineCtxType *pLineCtx, void *pVoidLineObj, VpDevCtxType *pDevCtx) { Vp790LineObjectType *pLineObj = pVoidLineObj; Vp790DeviceObjectType *pDevObj = pDevCtx->pDevObj; VpDeviceIdType deviceId = pDevObj->deviceId; if (channelId >= pDevObj->staticInfo.maxChannels) { return VP_STATUS_INVALID_ARG; } VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC); Vp790InitLineObject(pLineObj); switch (termType) { case VP_TERM_FXS_GENERIC: case VP_TERM_FXS_75282: case VP_TERM_FXS_TO_TL: case VP_TERM_FXS_RR: pLineObj->termType = termType; break; default: VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_INVALID_ARG; } pLineCtx->pLineObj = pLineObj; pLineCtx->pDevCtx = pDevCtx; pDevCtx->pLineCtx[channelId] = pLineCtx; pLineObj->channelId = channelId; VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); /* Everything else done by device/line specific functions */ return VP_STATUS_SUCCESS; }
/** * VpMpiCmd() * This function executes a Device MPI command through the MPI port. It * executes both read and write commands. The read or write operation is * determined by the "cmd" argument (odd = read, even = write). The caller must * ensure that the data array is large enough to hold the data being collected. * Because this command used hardware resources, this procedure is not * re-entrant. * * Note: For API-II to support multi-threading, this function has to write to * the EC register of the device to set the line being controlled, in addition * to the command being passed. The EC register write/read command is the same * for every CSLAC device and added to this function. The only exception is * if the calling function is accessing the EC register (read), in which case * the EC write cannot occur. * * This example assumes the implementation of two byte level commands: * * MpiReadByte(VpDeviceIdType deviceId, uint8 *data); * MpiWriteByte(VpDeviceIdType deviceId, uint8 data); * * Preconditions: * The device must be initialized. * * Postconditions: * The data pointed to by dataPtr, using the command "cmd", with length * "cmdLen" has been sent to the MPI bus via the chip select associated with * deviceId. */ void VpMpiCmd( VpDeviceIdType deviceId, /**< Chip select, connector and 3 or 4 wire * interface for command */ uint8 ecVal, /**< Value to write to the EC register */ uint8 cmd, /**< Command number */ uint8 cmdLen, /**< Number of bytes used by command (cmd) */ uint8 *dataPtr) /**< Pointer to the data location */ { zarlink_device_id_t *z = (zarlink_device_id_t *)(deviceId); uint8 isRead = (cmd & READ_COMMAND); uint8 buf[4]; uint8 buf_len = 0; #define CSLAC_EC_REG_RD 0x4B /* Same for all CSLAC devices */ #define CSLAC_EC_REG_WRT 0x4A /* Same for all CSLAC devices */ #define CSLAC_EC_REG_LEN 0x01 /* Same for all CSLAC devices */ /* Configure glue logic as necessary to talk to the device */ /* Start critical section for MPI access */ VpSysEnterCritical(deviceId, VP_MPI_CRITICAL_SEC); /* If a EC read is being preformed don't set the EC register */ if (CSLAC_EC_REG_RD != cmd) { buf[buf_len] = CSLAC_EC_REG_WRT; buf_len += 1; buf[buf_len] = ecVal; buf_len += 1; } /* Write the command byte to MPI. */ buf[buf_len] = cmd; buf_len += 1; if (isRead) { bcm_mpi_read(z->mpi, dataPtr, cmdLen, buf, buf_len); } else { /* If writing, access data from buffer passed and write to MPI */ bcm_mpi_write(z->mpi, buf, buf_len); bcm_mpi_write(z->mpi, dataPtr, cmdLen); } VpSysExitCritical(deviceId, VP_MPI_CRITICAL_SEC); return; } /* End VpMpiCmd */
/** * 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}; 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; } /* Check the legality of the AC profile */ if (!VpCSLACIsProfileValid(VP_PROFILE_AC, VP_CSLAC_AC_PROF_TABLE_SIZE, pDevObj->profEntry.acProfEntry, pDevObj->devProfileTable.pAcProfileTable, pAcProfile, &pAcProf)) { return VP_STATUS_ERR_PROFILE; } /* Check the legality of the DC profile */ if (!VpCSLACIsProfileValid(VP_PROFILE_DC, VP_CSLAC_DC_PROF_TABLE_SIZE, pDevObj->profEntry.dcProfEntry, pDevObj->devProfileTable.pDcProfileTable, pDcOrFxoProfile, &pDcFxoCfgProf)) { return VP_STATUS_ERR_PROFILE; } /* Check the legality of the Ringing profile */ if (!VpCSLACIsProfileValid(VP_PROFILE_RING, VP_CSLAC_RINGING_PROF_TABLE_SIZE, pDevObj->profEntry.ringingProfEntry, pDevObj->devProfileTable.pRingingProfileTable, pRingProfile, &pRingProf)) { 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] &= (uint8)(~(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; }
/** * Vp790InitLine * This function initializes a line of a device with the specified parameters * and API default values. It is a "Line Reset". * * Preconditions: * The device associated with this line must be initialized. * * Postconditions: * The line pointed to be 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 Vp790InitLine( 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; uint8 ecVal[] = {VP790_EC_CH1, VP790_EC_CH2, VP790_EC_CH3, VP790_EC_CH4}; uint8 channelId = pLineObj->channelId; uint8 data; #ifdef VP_CSLAC_SEQ_EN uint8 seqByte; #endif uint8 ioReg[VP790_IO_REG_LEN]; uint8 disableVals[VP790_LOOP_SUP_LEN] = {0x0D, 0x64, 0x0D, 0x01, 0x30, 0x00, 0x00, 0x7F}; VpDeviceIdType deviceId = pDevObj->deviceId; /* 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; } VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC); #ifdef VP_CSLAC_SEQ_EN for (seqByte = 0; seqByte < VP790_INT_SEQ_LEN; seqByte++) { pLineObj->intSequence[seqByte] = 0x00; } pLineObj->callerId.status = VP_CID_RESET_VALUE; pLineObj->thisFskCid = FALSE; #endif pLineObj->pRingingCadence = VP_PTABLE_NULL; pLineObj->pCidProfileType1 = VP_PTABLE_NULL; pLineObj->pCidProfileType2 = VP_PTABLE_NULL; pLineObj->lineState.currentState = VP_LINE_DISCONNECT; pLineObj->lineState.previous = VP_LINE_DISCONNECT; pLineObj->codec = VP_NUM_OPTION_CODEC_TYPE_IDS; pLineObj->lineTimers.type = VP_CSLAC_FXS_TIMER; InitTimerVars(pLineCtx); #ifdef VP_CSLAC_SEQ_EN VpMemSet(&pLineObj->cadence, 0, sizeof(VpSeqDataType)); #endif /* Software reset the channel */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_SW_RESET_CMD, NO_DATA, &data); VpSysWait(3); VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_LOOP_SUP_WRT, VP790_LOOP_SUP_LEN, disableVals); VpSysWait(1); /* Set the default line state */ Vp790SetLineState(pLineCtx, VP_LINE_DISCONNECT); /* Deactiveate the CODEC for the channel */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_DEACTIVATE_CMD, NO_DATA, &data); /***************** C3 Operational Issue 3 ******************/ /* This errata fix does not harm D3 operation */ data = 0x00; VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_CCR9_WRT, VP790_CCR9_LEN, &data); /* We've already deactivated the device */ VpSysWait(3); /**************** End Operational Issue 3 ******************/ pLineObj->ringCtrl.zeroCross = VP_OPTION_DEFAULT_ZERO_CROSS; Vp790ConfigLine(pLineCtx, pAcProfile, pDcOrFxoProfile, pRingProfile); VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_IO_REG_RD, VP790_IO_REG_LEN, ioReg); ioReg[0] |= VP790_IO_REG_RD1_MANUAL; VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_IO_REG_WRT, VP790_IO_REG_LEN, ioReg); VpImplementDefaultSettings(VP_NULL, pLineCtx); /* Force an initial test of the hook state */ pLineObj->lineState.condition = VP_CSLAC_STATUS_INVALID; pLineObj->dpStruct.hookSt = FALSE; VpInitDP(&pLineObj->dpStruct); /* Re-activate the channel due to a silicon bug -- and it doesn't hurt */ VpMpiCmdWrapper(deviceId, ecVal[channelId], VP790_ACTIVATE_CMD, NO_DATA, VP_NULL); /* Post the line init complete event */ pLineObj->lineEvents.response |= VP_LINE_EVID_LINE_INIT_CMP; VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_SUCCESS; } /* Vp790InitLine */
/** * 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 */
/******************************************************************************* * Vp890MakeLineObject() * This function * * Arguments: * * Preconditions: * * Postconditions: ******************************************************************************/ VpStatusType Vp890MakeLineObject( VpTermType termType, uint8 channelId, VpLineCtxType *pLineCtx, void *pVoidLineObj, VpDevCtxType *pDevCtx) { Vp890LineObjectType *pLineObj = pVoidLineObj; Vp890DeviceObjectType *pDevObj = pDevCtx->pDevObj; VpDeviceIdType deviceId = pDevObj->deviceId; /* Basic error checking */ if (channelId >= pDevObj->staticInfo.maxChannels) { VP_ERROR(VpDevCtxType, pDevCtx, ("Vp890MakeLineObject() - Bad channelId")); return VP_STATUS_INVALID_ARG; } if (VP_NUM_TERM_TYPES < termType) { VP_ERROR(VpDevCtxType, pDevCtx, ("Vp890MakeLineObject() - Termination type outside range")); return VP_STATUS_ERR_VTD_CODE; } VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC); InitLineObject(pLineObj); /* Figure out if the line is an FXO or FXS */ switch (termType) { case VP_TERM_FXO_GENERIC: if (channelId != 1) { VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_INVALID_ARG; } pLineObj->status |= VP890_IS_FXO; /* FXO is always physical line 1 ([0:1] range). */ pLineObj->channelId = 1; break; case VP_TERM_FXS_ISOLATE_LP: case VP_TERM_FXS_LOW_PWR: case VP_TERM_FXS_SPLITTER_LP: pDevObj->stateInt |= (VP890_LINE0_LP | VP890_LINE1_LP); case VP_TERM_FXS_GENERIC: case VP_TERM_FXS_SPLITTER: case VP_TERM_FXS_ISOLATE: pLineObj->channelId = channelId; pLineObj->status = VP890_INIT_STATUS; break; default: VP_ERROR(VpDevCtxType, pDevCtx, ("Vp890MakeLineObject() - Unsupported termination type")); VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_ERR_VTD_CODE; } /* Initialize line context */ pLineCtx->pLineObj = pLineObj; pLineCtx->pDevCtx = pDevCtx; /* Establish the link between device context to line context */ pDevCtx->pLineCtx[channelId] = pLineCtx; /* Initialize line object */ pLineObj->termType = termType; /* Note that we are not initializing the 'lineId' member because we do not * know what it should be initialized (that information is not provided * through the VpMakeLineObj() function) and the basic type of this member * is defined by the customer and hence this variable could not have one * default value. */ VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC); return VP_STATUS_SUCCESS; } /* Vp890MakeLineObject() */