| 1 | /*************************************************************************** |
|---|
| 2 | * Copyright (c) 2003-2012, Broadcom Corporation |
|---|
| 3 | * All Rights Reserved |
|---|
| 4 | * Confidential Property of Broadcom Corporation |
|---|
| 5 | * |
|---|
| 6 | * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE |
|---|
| 7 | * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR |
|---|
| 8 | * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 9 | * |
|---|
| 10 | * $brcm_Workfile: bxpt_packetsub.c $ |
|---|
| 11 | * $brcm_Revision: Hydra_Software_Devel/8 $ |
|---|
| 12 | * $brcm_Date: 1/12/12 2:40p $ |
|---|
| 13 | * |
|---|
| 14 | * Porting interface code for the data transport core. |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: /magnum/portinginterface/xpt/base2/bxpt_packetsub.c $ |
|---|
| 19 | * |
|---|
| 20 | * Hydra_Software_Devel/8 1/12/12 2:40p gmullen |
|---|
| 21 | * SW7425-2138: Fixed incorrect parser band index |
|---|
| 22 | * |
|---|
| 23 | * Hydra_Software_Devel/7 12/16/11 2:10p gmullen |
|---|
| 24 | * SW7405-5573: Check that packetsub channel is not already open |
|---|
| 25 | * |
|---|
| 26 | * Hydra_Software_Devel/6 12/15/11 9:50a gmullen |
|---|
| 27 | * SW7425-1589: Merged to Hydra_Software_Devel |
|---|
| 28 | * |
|---|
| 29 | * Hydra_Software_Devel/SW7425-1589/1 12/12/11 4:35p gmullen |
|---|
| 30 | * SW7425-1589: Added BXPT_PacketSub_GetEobIntId() |
|---|
| 31 | * |
|---|
| 32 | * Hydra_Software_Devel/5 8/22/11 5:45p gmullen |
|---|
| 33 | * SW7231-319: Merged to Hydra branch |
|---|
| 34 | * |
|---|
| 35 | * Hydra_Software_Devel/SW7231-319/1 8/16/11 2:15p gmullen |
|---|
| 36 | * SW7231-319: Initial support for B0 |
|---|
| 37 | * |
|---|
| 38 | * Hydra_Software_Devel/4 5/12/11 4:59p gmullen |
|---|
| 39 | * SW7231-128: Merged to mainline |
|---|
| 40 | * |
|---|
| 41 | * Hydra_Software_Devel/SW7231-128/1 5/10/11 1:40p gmohile |
|---|
| 42 | * SW7231-128 : Add power management support |
|---|
| 43 | * |
|---|
| 44 | * Hydra_Software_Devel/3 1/25/11 3:10p rjlewis |
|---|
| 45 | * SW7420-879: supply a means to provide an output rate default on open. |
|---|
| 46 | * Get defaults provides the default value. |
|---|
| 47 | * |
|---|
| 48 | * Hydra_Software_Devel/2 10/28/10 2:08p gmullen |
|---|
| 49 | * SW7422-20: Checkin ported files |
|---|
| 50 | * |
|---|
| 51 | * Hydra_Software_Devel/15 8/17/10 4:52p gmullen |
|---|
| 52 | * SW7403-924: Merged to Hydra_Software_Devel |
|---|
| 53 | * |
|---|
| 54 | * Hydra_Software_Devel/SW7403-924/5 8/17/10 4:42p gmullen |
|---|
| 55 | * SW7403-924: Reduce MAX_PID_CHANNELS when PSUB PID channels are not |
|---|
| 56 | * changed |
|---|
| 57 | * |
|---|
| 58 | * Hydra_Software_Devel/SW7403-924/4 8/11/10 2:12p gmullen |
|---|
| 59 | * SW7403-924: Set MAX_PID_CHANNEL to 249 during all PID/SPID writes. |
|---|
| 60 | * |
|---|
| 61 | * Hydra_Software_Devel/SW7403-924/3 8/11/10 10:53a gmullen |
|---|
| 62 | * SW7403-924: New method: change band_num in PSUB |
|---|
| 63 | * |
|---|
| 64 | * Hydra_Software_Devel/SW7403-924/2 8/10/10 1:51p gmullen |
|---|
| 65 | * SW7403-924: Set max PID channel before writing to PID/SPID table |
|---|
| 66 | * |
|---|
| 67 | * Hydra_Software_Devel/SW7403-924/1 8/9/10 9:07a gmullen |
|---|
| 68 | * SW7403-924: See the JIRA for the workaround notes |
|---|
| 69 | * |
|---|
| 70 | * Hydra_Software_Devel/14 5/14/10 5:53p gmullen |
|---|
| 71 | * SW7420-750: Merged change to Hydra_Software_Devel |
|---|
| 72 | * |
|---|
| 73 | * Hydra_Software_Devel/SW7420-750/1 5/14/10 4:37p gmullen |
|---|
| 74 | * SW7420-750: Added playback support to BXPT_PacketSub_SetPidChanNum() |
|---|
| 75 | * |
|---|
| 76 | * Hydra_Software_Devel/13 6/17/09 6:46p gmullen |
|---|
| 77 | * PR56110: Added support.xpt/7550/uif_image/a0 |
|---|
| 78 | * |
|---|
| 79 | * Hydra_Software_Devel/12 4/7/09 5:25p piyushg |
|---|
| 80 | * PR52986: Add support for 7635 |
|---|
| 81 | * Added directory element "7635". |
|---|
| 82 | * |
|---|
| 83 | * Hydra_Software_Devel/11 1/27/09 1:09p gmullen |
|---|
| 84 | * PR51625: Added 7336 support |
|---|
| 85 | * |
|---|
| 86 | * Hydra_Software_Devel/10 12/15/08 2:36p gmullen |
|---|
| 87 | * PR48908: Removed power management code from XPT PI. |
|---|
| 88 | * |
|---|
| 89 | * Hydra_Software_Devel/9 11/26/08 4:14p gmullen |
|---|
| 90 | * PR47755: Added support for 7420. |
|---|
| 91 | * |
|---|
| 92 | * Hydra_Software_Devel/8 10/28/08 4:58p gmullen |
|---|
| 93 | * PR46544: Added power management support, default to disabled for now. |
|---|
| 94 | * |
|---|
| 95 | * Hydra_Software_Devel/7 3/26/08 11:24a gmullen |
|---|
| 96 | * PR38954: Added 3548 support to XPT PI. |
|---|
| 97 | * |
|---|
| 98 | * Hydra_Software_Devel/6 11/28/07 11:24a gmullen |
|---|
| 99 | * PR36900: Added 7335 support |
|---|
| 100 | * |
|---|
| 101 | * Hydra_Software_Devel/5 10/30/07 3:11p gmullen |
|---|
| 102 | * PR35018: Added support for 7325 |
|---|
| 103 | * |
|---|
| 104 | * Hydra_Software_Devel/4 7/17/06 5:19p gmullen |
|---|
| 105 | * PR20624: Added code for 7118. |
|---|
| 106 | * |
|---|
| 107 | * Hydra_Software_Devel/3 7/10/06 9:32a gmullen |
|---|
| 108 | * PR18998: Fixed void * dereference warning. |
|---|
| 109 | * |
|---|
| 110 | * Hydra_Software_Devel/2 2/1/06 10:19a gmullen |
|---|
| 111 | * PR18998: Fixed overflow issue in RAVE ITB/CDB, added support for PB |
|---|
| 112 | * channels. |
|---|
| 113 | * |
|---|
| 114 | * Hydra_Software_Devel/1 1/16/06 2:09p gmullen |
|---|
| 115 | * PR18998: Initial checkin for 7400 |
|---|
| 116 | * |
|---|
| 117 | * Hydra_Software_Devel/3 1/6/06 2:22p gmullen |
|---|
| 118 | * PR18489: Added PID destination workaround for hardware PR 18919. |
|---|
| 119 | * |
|---|
| 120 | * Hydra_Software_Devel/2 12/2/05 3:24p gmullen |
|---|
| 121 | * PR15309: Saved updates for ccase server move |
|---|
| 122 | * |
|---|
| 123 | * Hydra_Software_Devel/1 7/28/05 3:40p gmullen |
|---|
| 124 | * PR15309: Initial version for building. |
|---|
| 125 | * |
|---|
| 126 | * |
|---|
| 127 | ***************************************************************************/ |
|---|
| 128 | |
|---|
| 129 | #include "bstd.h" |
|---|
| 130 | #include "bxpt_priv.h" |
|---|
| 131 | #include "bxpt_packetsub.h" |
|---|
| 132 | #include "bkni.h" |
|---|
| 133 | |
|---|
| 134 | #if BCHP_PWR_SUPPORT |
|---|
| 135 | #include "bchp_pwr.h" |
|---|
| 136 | #endif |
|---|
| 137 | |
|---|
| 138 | #include "bchp_xpt_fe.h" |
|---|
| 139 | #include "bchp_int_id_xpt_bus_if.h" |
|---|
| 140 | #include "bchp_xpt_psub.h" |
|---|
| 141 | |
|---|
| 142 | /* Size of an individual packetsub module register space, in bytes */ |
|---|
| 143 | #ifdef BCHP_XPT_PSUB_PSUB1_CTRL0 |
|---|
| 144 | #define PACKET_SUB_REGISTER_STEP ( BCHP_XPT_PSUB_PSUB1_CTRL0 - BCHP_XPT_PSUB_PSUB0_CTRL0 ) |
|---|
| 145 | #else |
|---|
| 146 | #define PACKET_SUB_REGISTER_STEP ( BCHP_XPT_PSUB_PSUB0_STAT2 - BCHP_XPT_PSUB_PSUB0_CTRL0 ) |
|---|
| 147 | #endif |
|---|
| 148 | |
|---|
| 149 | #define BXPT_P_PSUB_DEFAULT_PACKET_LEN ( 188 ) |
|---|
| 150 | #define BXPT_P_PSUB_DEFAULT_BAND_NUM ( 0 ) |
|---|
| 151 | #define BXPT_P_PSUB_DEFAULT_DMA_PRIORITY BXPT_PacketSubDmaPriority_eLow |
|---|
| 152 | #define BXPT_P_MAX_PSUB_OUTPUT_RATE ( 1000000 ) |
|---|
| 153 | #define BXPT_NUM_OUTPUT_RATE_REGISTER_VALUE ( 65535 ) |
|---|
| 154 | |
|---|
| 155 | #if( BDBG_DEBUG_BUILD == 1 ) |
|---|
| 156 | BDBG_MODULE( xpt_packetsub ); |
|---|
| 157 | #endif |
|---|
| 158 | |
|---|
| 159 | static void BXPT_PacketSub_P_WriteReg( |
|---|
| 160 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 161 | uint32_t Reg0Addr, |
|---|
| 162 | uint32_t RegVal |
|---|
| 163 | ); |
|---|
| 164 | |
|---|
| 165 | static uint32_t BXPT_PacketSub_P_ReadReg( |
|---|
| 166 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 167 | uint32_t Reg0Addr |
|---|
| 168 | ); |
|---|
| 169 | |
|---|
| 170 | BERR_Code BXPT_PacketSub_GetTotalChannels( |
|---|
| 171 | BXPT_Handle hXpt, /* [in] Handle for this transport */ |
|---|
| 172 | unsigned int *TotalChannels /* [out] The number of PacketSub channels. */ |
|---|
| 173 | ) |
|---|
| 174 | { |
|---|
| 175 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 176 | |
|---|
| 177 | BDBG_ASSERT( hXpt ); |
|---|
| 178 | |
|---|
| 179 | *TotalChannels = hXpt->MaxPacketSubs; |
|---|
| 180 | |
|---|
| 181 | return( ExitCode ); |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | BERR_Code BXPT_PacketSub_GetChannelDefaultSettings( |
|---|
| 185 | BXPT_Handle hXpt, /* [in] Handle for this transport */ |
|---|
| 186 | unsigned int ChannelNo, /* [in] Which channel to get defaults from. */ |
|---|
| 187 | BXPT_PacketSub_ChannelSettings *ChannelSettings /* [out] The defaults */ |
|---|
| 188 | ) |
|---|
| 189 | { |
|---|
| 190 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 191 | |
|---|
| 192 | BDBG_ASSERT( hXpt ); |
|---|
| 193 | BDBG_ASSERT( ChannelSettings ); |
|---|
| 194 | |
|---|
| 195 | if( ChannelNo >= hXpt->MaxPacketSubs ) |
|---|
| 196 | { |
|---|
| 197 | /* Bad PID channel number. Complain. */ |
|---|
| 198 | BDBG_ERR(( "ChannelNo %lu is out of range!", ( unsigned long ) ChannelNo )); |
|---|
| 199 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 200 | } |
|---|
| 201 | else |
|---|
| 202 | { |
|---|
| 203 | ChannelSettings->PacketLen = BXPT_P_PSUB_DEFAULT_PACKET_LEN; |
|---|
| 204 | ChannelSettings->ForcedInsertionEn = false; |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | ChannelSettings->OutputRate = 0xBC * 1649; /* this will produce a register value of 0xBC the hardware default */ |
|---|
| 208 | |
|---|
| 209 | return( ExitCode ); |
|---|
| 210 | } |
|---|
| 211 | |
|---|
| 212 | BERR_Code BXPT_PacketSub_OpenChannel( |
|---|
| 213 | BXPT_Handle hXpt, /* [in] Handle for this transport */ |
|---|
| 214 | BXPT_PacketSub_Handle *hPSub, /* [out] Handle for opened packet sub channel */ |
|---|
| 215 | unsigned int ChannelNo, /* [in] Which channel to open. */ |
|---|
| 216 | BXPT_PacketSub_ChannelSettings *ChannelSettings /* [in] The defaults to use */ |
|---|
| 217 | ) |
|---|
| 218 | { |
|---|
| 219 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 220 | BXPT_PacketSub_Handle hLocal = ( BXPT_PacketSub_Handle ) NULL; |
|---|
| 221 | |
|---|
| 222 | BDBG_ASSERT( hXpt ); |
|---|
| 223 | BDBG_ASSERT( ChannelSettings ); |
|---|
| 224 | |
|---|
| 225 | if( ChannelNo >= BXPT_NUM_PACKETSUBS ) |
|---|
| 226 | { |
|---|
| 227 | /* Bad playback channel number. Complain. */ |
|---|
| 228 | BDBG_ERR(( "ChannelNo %lu is out of range!", ( unsigned long ) ChannelNo )); |
|---|
| 229 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 230 | } |
|---|
| 231 | else if( hXpt->PacketSubHandles[ ChannelNo ].Opened ) |
|---|
| 232 | { |
|---|
| 233 | BDBG_ERR(( "PacketSub channel %u already opened.", ChannelNo )); |
|---|
| 234 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 235 | } |
|---|
| 236 | else |
|---|
| 237 | { |
|---|
| 238 | uint32_t Reg; |
|---|
| 239 | |
|---|
| 240 | /* |
|---|
| 241 | ** Use the address of the first register in the packet sub block as the |
|---|
| 242 | ** base address of the entire block. |
|---|
| 243 | */ |
|---|
| 244 | uint32_t BaseAddr = BCHP_XPT_PSUB_PSUB0_CTRL0 + ( ChannelNo * PACKET_SUB_REGISTER_STEP ); |
|---|
| 245 | |
|---|
| 246 | /* Create the packet sub channel handle. */ |
|---|
| 247 | hLocal = &hXpt->PacketSubHandles[ ChannelNo ]; |
|---|
| 248 | hLocal->hChip = hXpt->hChip; |
|---|
| 249 | hLocal->hRegister = hXpt->hRegister; |
|---|
| 250 | hLocal->hMemory = hXpt->hMemory; |
|---|
| 251 | hLocal->BaseAddr = BaseAddr; |
|---|
| 252 | hLocal->ChannelNo = ChannelNo; |
|---|
| 253 | hLocal->LastDescriptor = 0; |
|---|
| 254 | hLocal->Running = false; |
|---|
| 255 | hLocal->vhXpt = (void *) hXpt; |
|---|
| 256 | |
|---|
| 257 | /* Do a sanity check on the defaults they passed in, then load them. */ |
|---|
| 258 | if( ChannelSettings->PacketLen > 255 ) |
|---|
| 259 | { |
|---|
| 260 | BDBG_ERR(( "PacketLen %lu is out of range!. Clamped to 255.", |
|---|
| 261 | ( unsigned long ) ChannelSettings->PacketLen )); |
|---|
| 262 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 263 | ChannelSettings->PacketLen = 255; |
|---|
| 264 | } |
|---|
| 265 | |
|---|
| 266 | /* Use their value for a default output rate. Don't fail if this value is out of range */ |
|---|
| 267 | BXPT_PacketSub_SetOutputRate( hLocal, ChannelSettings->OutputRate ); |
|---|
| 268 | |
|---|
| 269 | Reg = BXPT_PacketSub_P_ReadReg( hLocal, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 270 | Reg &= ~( |
|---|
| 271 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, PACKET_LENGTH ) | |
|---|
| 272 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, DATA_ENDIAN_CTRL ) | |
|---|
| 273 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, FORCED_INSERTION_EN ) |
|---|
| 274 | ); |
|---|
| 275 | Reg |= ( |
|---|
| 276 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, PACKET_LENGTH, ChannelSettings->PacketLen ) | |
|---|
| 277 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, DATA_ENDIAN_CTRL, hXpt->IsLittleEndian == true ? 1 : 0 ) | |
|---|
| 278 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, FORCED_INSERTION_EN, ChannelSettings->ForcedInsertionEn == true ? 1 : 0 ) |
|---|
| 279 | ); |
|---|
| 280 | BXPT_PacketSub_P_WriteReg( hLocal, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 281 | hLocal->Opened = true; |
|---|
| 282 | } |
|---|
| 283 | |
|---|
| 284 | *hPSub = hLocal; |
|---|
| 285 | return( ExitCode ); |
|---|
| 286 | } |
|---|
| 287 | |
|---|
| 288 | void BXPT_PacketSub_CloseChannel( |
|---|
| 289 | BXPT_PacketSub_Handle hPSub /* [in] Handle for the channel to close*/ |
|---|
| 290 | ) |
|---|
| 291 | { |
|---|
| 292 | uint32_t Reg; |
|---|
| 293 | |
|---|
| 294 | BDBG_ASSERT( hPSub ); |
|---|
| 295 | |
|---|
| 296 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 297 | Reg &= ~( |
|---|
| 298 | BCHP_MASK( XPT_PSUB_PSUB0_STAT0, WAKE_MODE ) | |
|---|
| 299 | BCHP_MASK( XPT_PSUB_PSUB0_STAT0, RUN ) | |
|---|
| 300 | BCHP_MASK( XPT_PSUB_PSUB0_STAT0, WAKE ) |
|---|
| 301 | ); |
|---|
| 302 | Reg |= ( |
|---|
| 303 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, WAKE_MODE, 0 ) | |
|---|
| 304 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, RUN, 0 ) | |
|---|
| 305 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, WAKE, 0 ) |
|---|
| 306 | ); |
|---|
| 307 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0, Reg ); |
|---|
| 308 | |
|---|
| 309 | hPSub->Opened = false; |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | |
|---|
| 313 | unsigned int BXPT_PacketSub_GetPidChanNum( |
|---|
| 314 | BXPT_PacketSub_Handle hPSub /* [in] Handle for the channel. */ |
|---|
| 315 | ) |
|---|
| 316 | { |
|---|
| 317 | unsigned int PidChannelNum; |
|---|
| 318 | BXPT_Handle hXpt; /* [in] Handle for this transport */ |
|---|
| 319 | |
|---|
| 320 | BDBG_ASSERT( hPSub ); |
|---|
| 321 | |
|---|
| 322 | hXpt = (BXPT_Handle) hPSub->vhXpt; |
|---|
| 323 | BXPT_AllocPidChannel( hXpt, false, &PidChannelNum ); |
|---|
| 324 | |
|---|
| 325 | return PidChannelNum; |
|---|
| 326 | } |
|---|
| 327 | |
|---|
| 328 | BERR_Code BXPT_PacketSub_SetPidChanNum( |
|---|
| 329 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 330 | unsigned int PidChanNum, /* [in] Which PID channel to assign the output to. */ |
|---|
| 331 | unsigned int BandNum /* [in] Which band number to assign the output to */ |
|---|
| 332 | ) |
|---|
| 333 | { |
|---|
| 334 | uint32_t Reg; |
|---|
| 335 | |
|---|
| 336 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 337 | bool IsPbBand = BXPT_P_IS_PB( BandNum ); |
|---|
| 338 | |
|---|
| 339 | BDBG_ASSERT( hPSub ); |
|---|
| 340 | |
|---|
| 341 | BXPT_P_CLEAR_PB_FLAG( BandNum ); |
|---|
| 342 | |
|---|
| 343 | if( PidChanNum >= BXPT_NUM_PID_CHANNELS ) |
|---|
| 344 | { |
|---|
| 345 | /* Bad PID channel number. Complain. */ |
|---|
| 346 | BDBG_ERR(( "PidChanNum %lu is out of range!", ( unsigned long ) PidChanNum )); |
|---|
| 347 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 348 | } |
|---|
| 349 | else if( !IsPbBand && BandNum > BXPT_NUM_PID_PARSERS ) |
|---|
| 350 | { |
|---|
| 351 | BDBG_ERR(( "Input band BandNum %lu is out of range!", ( unsigned long ) BandNum )); |
|---|
| 352 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 353 | } |
|---|
| 354 | else if( IsPbBand && BandNum > BXPT_NUM_PLAYBACKS ) |
|---|
| 355 | { |
|---|
| 356 | BDBG_ERR(( "Playback band BandNum %lu is out of range!", ( unsigned long ) BandNum )); |
|---|
| 357 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 358 | } |
|---|
| 359 | else |
|---|
| 360 | { |
|---|
| 361 | /* For playbacks, band numbers are mapped beginning at an architecture-specific offset. */ |
|---|
| 362 | BandNum = IsPbBand ? (BandNum + BXPT_PB_PARSER_BAND_BASE) : BandNum; |
|---|
| 363 | |
|---|
| 364 | #ifdef BCHP_XPT_PSUB_PSUB0_CTRL1_OUTPUT_CH_NUM_MASK |
|---|
| 365 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 366 | Reg &= ~( |
|---|
| 367 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, BAND_SEL ) |
|---|
| 368 | ); |
|---|
| 369 | Reg |= ( |
|---|
| 370 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, BAND_SEL, BandNum ) |
|---|
| 371 | ); |
|---|
| 372 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 373 | |
|---|
| 374 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL1 ); |
|---|
| 375 | Reg &= ~( |
|---|
| 376 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL1, OUTPUT_CH_NUM ) |
|---|
| 377 | ); |
|---|
| 378 | Reg |= ( |
|---|
| 379 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL1, OUTPUT_CH_NUM, PidChanNum ) |
|---|
| 380 | ); |
|---|
| 381 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL1, Reg ); |
|---|
| 382 | #else |
|---|
| 383 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 384 | Reg &= ~( |
|---|
| 385 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, BAND_SEL ) | |
|---|
| 386 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, OUTPUT_CH_NUM ) |
|---|
| 387 | ); |
|---|
| 388 | Reg |= ( |
|---|
| 389 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, BAND_SEL, BandNum ) | |
|---|
| 390 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, OUTPUT_CH_NUM, PidChanNum ) |
|---|
| 391 | ); |
|---|
| 392 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 393 | #endif |
|---|
| 394 | } |
|---|
| 395 | |
|---|
| 396 | return( ExitCode ); |
|---|
| 397 | } |
|---|
| 398 | |
|---|
| 399 | BERR_Code BXPT_PacketSub_SetForcedOutput( |
|---|
| 400 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 401 | bool Enable /* [in] Force output immediately if TRUE */ |
|---|
| 402 | ) |
|---|
| 403 | { |
|---|
| 404 | uint32_t Reg; |
|---|
| 405 | |
|---|
| 406 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 407 | |
|---|
| 408 | BDBG_ASSERT( hPSub ); |
|---|
| 409 | |
|---|
| 410 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 411 | Reg &= ~( |
|---|
| 412 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, FORCED_OUTPUT_ENABLE ) |
|---|
| 413 | ); |
|---|
| 414 | Reg |= ( |
|---|
| 415 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, FORCED_OUTPUT_ENABLE, Enable == true ? 1 : 0 ) |
|---|
| 416 | ); |
|---|
| 417 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 418 | |
|---|
| 419 | return( ExitCode ); |
|---|
| 420 | } |
|---|
| 421 | |
|---|
| 422 | BERR_Code BXPT_PacketSub_SetForcedInsertion( |
|---|
| 423 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 424 | bool Enable /* [in] Force output immediately if TRUE */ |
|---|
| 425 | ) |
|---|
| 426 | { |
|---|
| 427 | uint32_t Reg; |
|---|
| 428 | |
|---|
| 429 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 430 | |
|---|
| 431 | BDBG_ASSERT( hPSub ); |
|---|
| 432 | |
|---|
| 433 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 434 | Reg &= ~( |
|---|
| 435 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, FORCED_INSERTION_EN ) |
|---|
| 436 | ); |
|---|
| 437 | Reg |= ( |
|---|
| 438 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, FORCED_INSERTION_EN, Enable == true ? 1 : 0 ) |
|---|
| 439 | ); |
|---|
| 440 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 441 | |
|---|
| 442 | return( ExitCode ); |
|---|
| 443 | } |
|---|
| 444 | |
|---|
| 445 | BERR_Code BXPT_PacketSub_SetFullRateOutput( |
|---|
| 446 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 447 | bool Enable /* [in] Use full rate if TRUE */ |
|---|
| 448 | ) |
|---|
| 449 | { |
|---|
| 450 | uint32_t Reg; |
|---|
| 451 | |
|---|
| 452 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 453 | |
|---|
| 454 | BDBG_ASSERT( hPSub ); |
|---|
| 455 | |
|---|
| 456 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 457 | Reg &= ~( |
|---|
| 458 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, FULL_RATE_OUTPUT_ENABLE ) |
|---|
| 459 | ); |
|---|
| 460 | Reg |= ( |
|---|
| 461 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, FULL_RATE_OUTPUT_ENABLE, Enable == true ? 1 : 0 ) |
|---|
| 462 | ); |
|---|
| 463 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 464 | |
|---|
| 465 | return( ExitCode ); |
|---|
| 466 | } |
|---|
| 467 | |
|---|
| 468 | BERR_Code BXPT_PacketSub_SetOutputRate( |
|---|
| 469 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 470 | uint32_t OutputRate /* [in] The output rate, in bits/second */ |
|---|
| 471 | ) |
|---|
| 472 | { |
|---|
| 473 | uint32_t Reg; |
|---|
| 474 | uint32_t NewRate; |
|---|
| 475 | |
|---|
| 476 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 477 | |
|---|
| 478 | BDBG_ASSERT( hPSub ); |
|---|
| 479 | |
|---|
| 480 | /* |
|---|
| 481 | See SW7420-879 for details. The time between each packet substitution (sec) = 0.912 / OUTPUT_RATE. |
|---|
| 482 | We are given the insertion rate in (the OutputRate argument) bits/sec, and we need to solve for |
|---|
| 483 | the OUTPUT_RATE register setting. |
|---|
| 484 | packets/sec = OUTPUT_RATE/0.912 |
|---|
| 485 | bits/sec = (188*8) bits/packet * OUTPUT_RATE/0.912 |
|---|
| 486 | OUTPUT_RATE = bits/sec * 0.912/1504 |
|---|
| 487 | OUTPUT_RATE = OutputRate / 1649 |
|---|
| 488 | */ |
|---|
| 489 | |
|---|
| 490 | if( OutputRate > BXPT_P_MAX_PSUB_OUTPUT_RATE ) |
|---|
| 491 | { |
|---|
| 492 | BDBG_ERR(( "OutputRate %lu is out of range! Clamped to %lu", |
|---|
| 493 | ( unsigned long ) OutputRate, BXPT_P_MAX_PSUB_OUTPUT_RATE )); |
|---|
| 494 | NewRate = 65535; /* Max value this bitfield can hold */ |
|---|
| 495 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 496 | } |
|---|
| 497 | else |
|---|
| 498 | { |
|---|
| 499 | NewRate = (uint32_t) OutputRate / 1649; |
|---|
| 500 | } |
|---|
| 501 | if( NewRate == 0 ) |
|---|
| 502 | NewRate = 1; /* Handle round-down condition */ |
|---|
| 503 | |
|---|
| 504 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL1 ); |
|---|
| 505 | Reg &= ~( |
|---|
| 506 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL1, OUTPUT_RATE ) |
|---|
| 507 | ); |
|---|
| 508 | Reg |= ( |
|---|
| 509 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL1, OUTPUT_RATE, NewRate ) |
|---|
| 510 | ); |
|---|
| 511 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL1, Reg ); |
|---|
| 512 | |
|---|
| 513 | return( ExitCode ); |
|---|
| 514 | } |
|---|
| 515 | |
|---|
| 516 | BERR_Code BXPT_PacketSub_PauseChannel( |
|---|
| 517 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 518 | bool Pause /* [in] Pause channel if TRUE, continue if FALSE */ |
|---|
| 519 | ) |
|---|
| 520 | { |
|---|
| 521 | uint32_t Reg; |
|---|
| 522 | |
|---|
| 523 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 524 | |
|---|
| 525 | BDBG_ASSERT( hPSub ); |
|---|
| 526 | |
|---|
| 527 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 528 | Reg &= ~( |
|---|
| 529 | BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, PAUSE ) |
|---|
| 530 | ); |
|---|
| 531 | Reg |= ( |
|---|
| 532 | BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, PAUSE, Pause == true ? 1 : 0 ) |
|---|
| 533 | ); |
|---|
| 534 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 535 | |
|---|
| 536 | return( ExitCode ); |
|---|
| 537 | } |
|---|
| 538 | |
|---|
| 539 | BERR_Code BXPT_PacketSub_CreateDesc( |
|---|
| 540 | BXPT_Handle hXpt, /* [in] Handle for this transport */ |
|---|
| 541 | BXPT_PacketSub_Descriptor * const Desc, /* [in] Descriptor to initialize */ |
|---|
| 542 | uint8_t *Buffer, /* [in] Data buffer. */ |
|---|
| 543 | uint32_t BufferLength, /* [in] Size of buffer (in bytes). */ |
|---|
| 544 | bool IntEnable, /* [in] Interrupt when done? */ |
|---|
| 545 | BXPT_PacketSub_Descriptor * const NextDesc /* [in] Next descriptor, or NULL */ |
|---|
| 546 | ) |
|---|
| 547 | { |
|---|
| 548 | uint32_t BufferPhysicalAddr; |
|---|
| 549 | uint32_t ThisDescPhysicalAddr; |
|---|
| 550 | |
|---|
| 551 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 552 | |
|---|
| 553 | BDBG_ASSERT( hXpt ); |
|---|
| 554 | BDBG_ASSERT( Desc ); |
|---|
| 555 | BDBG_ASSERT( Buffer ); |
|---|
| 556 | |
|---|
| 557 | /* Get the physical address for this buffer. Verify its on a 4-byte boundary*/ |
|---|
| 558 | BMEM_ConvertAddressToOffset( hXpt->hMemory, ( void * ) Buffer, &BufferPhysicalAddr ); |
|---|
| 559 | if( BufferPhysicalAddr % 4 ) |
|---|
| 560 | { |
|---|
| 561 | BDBG_ERR(( "Buffer is not 32-bit aligned!" )); |
|---|
| 562 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 563 | |
|---|
| 564 | /* Force the alignment. */ |
|---|
| 565 | BufferPhysicalAddr += ( BufferPhysicalAddr % 4 ); |
|---|
| 566 | } |
|---|
| 567 | |
|---|
| 568 | /* Verify that the buffer length is multiple of 4 bytes (i.e. a word). */ |
|---|
| 569 | if( BufferLength % 4 ) |
|---|
| 570 | { |
|---|
| 571 | BDBG_ERR(( "BufferLength is not 32-bit aligned!" )); |
|---|
| 572 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 573 | |
|---|
| 574 | /* Force the alignment. */ |
|---|
| 575 | BufferLength += ( BufferLength % 4 ); |
|---|
| 576 | } |
|---|
| 577 | |
|---|
| 578 | /* Verify that the descriptor we're creating sits on a 16-byte boundary. */ |
|---|
| 579 | BMEM_ConvertAddressToOffset( hXpt->hMemory, ( void * ) Desc, &ThisDescPhysicalAddr ); |
|---|
| 580 | if( ThisDescPhysicalAddr % 16 ) |
|---|
| 581 | { |
|---|
| 582 | BDBG_ERR(( "Desc is not 32-bit aligned!" )); |
|---|
| 583 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 584 | } |
|---|
| 585 | |
|---|
| 586 | /* Load the descriptor's buffer address, length, and flags. */ |
|---|
| 587 | Desc->BufferStartAddr = BufferPhysicalAddr; |
|---|
| 588 | Desc->BufferLength = BufferLength; |
|---|
| 589 | |
|---|
| 590 | /* Clear everything, then set the ones we want below. */ |
|---|
| 591 | Desc->Flags = 0; |
|---|
| 592 | |
|---|
| 593 | if( IntEnable == true ) |
|---|
| 594 | Desc->Flags |= TRANS_DESC_INT_FLAG; |
|---|
| 595 | |
|---|
| 596 | /* Load the pointer to the next descriptor in the chain, if there is one. */ |
|---|
| 597 | if( NextDesc != 0 ) |
|---|
| 598 | { |
|---|
| 599 | /* There is a another descriptor in the chain after this one. */ |
|---|
| 600 | uint32_t NextDescPhysAddr; |
|---|
| 601 | |
|---|
| 602 | BMEM_ConvertAddressToOffset( hXpt->hMemory, ( void * ) NextDesc, &NextDescPhysAddr ); |
|---|
| 603 | if( NextDescPhysAddr % 16 ) |
|---|
| 604 | { |
|---|
| 605 | BDBG_ERR(( "NextDescDesc is not 32-bit aligned!" )); |
|---|
| 606 | ExitCode = BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 607 | } |
|---|
| 608 | |
|---|
| 609 | /* Next descriptor address must be 16-byte aligned. */ |
|---|
| 610 | NextDescPhysAddr &= ~( 0xF ); |
|---|
| 611 | Desc->NextDescAddr = NextDescPhysAddr; |
|---|
| 612 | } |
|---|
| 613 | else |
|---|
| 614 | { |
|---|
| 615 | /* There is NOT another descriptor. Set the Last Descriptor bit. */ |
|---|
| 616 | Desc->NextDescAddr = TRANS_DESC_LAST_DESCR_IND; |
|---|
| 617 | } |
|---|
| 618 | |
|---|
| 619 | return( ExitCode ); |
|---|
| 620 | } |
|---|
| 621 | |
|---|
| 622 | BERR_Code BXPT_PacketSub_AddDescriptors( |
|---|
| 623 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 624 | BXPT_PacketSub_Descriptor *LastDesc, /* [in] Last descriptor in new chain */ |
|---|
| 625 | BXPT_PacketSub_Descriptor *FirstDesc /* [in] First descriptor in new chain */ |
|---|
| 626 | ) |
|---|
| 627 | { |
|---|
| 628 | uint32_t ChanFinished, Reg; |
|---|
| 629 | uint32_t RunBit; |
|---|
| 630 | |
|---|
| 631 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 632 | |
|---|
| 633 | BDBG_ASSERT( hPSub ); |
|---|
| 634 | BDBG_ASSERT( LastDesc ); |
|---|
| 635 | BDBG_ASSERT( FirstDesc ); |
|---|
| 636 | |
|---|
| 637 | BDBG_MSG(("Adding Desc Addr 0x%08lX to Packet Sub Channel %d", ( unsigned long ) FirstDesc, |
|---|
| 638 | hPSub->ChannelNo )); |
|---|
| 639 | |
|---|
| 640 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 641 | ChanFinished = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT0, FINISHED ); |
|---|
| 642 | |
|---|
| 643 | if( ChanFinished ) |
|---|
| 644 | { |
|---|
| 645 | /* Channel has finished, so start over at the beginning of the chain. */ |
|---|
| 646 | Reg &= ~ ( BCHP_MASK( XPT_PSUB_PSUB0_STAT0, WAKE_MODE ) ); |
|---|
| 647 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, WAKE_MODE, 1 ); |
|---|
| 648 | hPSub->LastDescriptor = 0; |
|---|
| 649 | } |
|---|
| 650 | else |
|---|
| 651 | { |
|---|
| 652 | /* Channel has NOT finished, so start over at the end of the chain. */ |
|---|
| 653 | Reg &= ~ ( BCHP_MASK( XPT_PSUB_PSUB0_STAT0, WAKE_MODE ) ); |
|---|
| 654 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, WAKE_MODE, 0 ); |
|---|
| 655 | } |
|---|
| 656 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0, Reg ); |
|---|
| 657 | |
|---|
| 658 | /* Do we already have a list going? */ |
|---|
| 659 | if( hPSub->LastDescriptor ) |
|---|
| 660 | { |
|---|
| 661 | uint32_t DescPhysAddr; |
|---|
| 662 | |
|---|
| 663 | /* |
|---|
| 664 | ** Yes, there is list already. Append this descriptor to the last descriptor, |
|---|
| 665 | ** then set the wake bit. |
|---|
| 666 | */ |
|---|
| 667 | BXPT_PacketSub_Descriptor *LastDescriptor = ( BXPT_PacketSub_Descriptor * ) hPSub->LastDescriptor; |
|---|
| 668 | |
|---|
| 669 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 670 | RunBit = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT0, RUN ); |
|---|
| 671 | |
|---|
| 672 | /* Set the last descriptor in the chain to point to the descriptor we're adding. */ |
|---|
| 673 | BMEM_ConvertAddressToOffset( hPSub->hMemory, ( void * ) FirstDesc, &DescPhysAddr ); |
|---|
| 674 | LastDescriptor->NextDescAddr = ( uint32_t ) DescPhysAddr; |
|---|
| 675 | |
|---|
| 676 | /* If the channel is running, we need to set the wake bit to let the hardware know we added a new buffer */ |
|---|
| 677 | if( RunBit ) |
|---|
| 678 | { |
|---|
| 679 | /* PR 16985: Need to write 0 after writing a 1 */ |
|---|
| 680 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, WAKE, 1 ); |
|---|
| 681 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0, Reg ); |
|---|
| 682 | |
|---|
| 683 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, WAKE, 0 ); |
|---|
| 684 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0, Reg ); |
|---|
| 685 | } |
|---|
| 686 | } |
|---|
| 687 | else |
|---|
| 688 | { |
|---|
| 689 | /* |
|---|
| 690 | ** If this is the first descriptor (the channel has not been started) |
|---|
| 691 | ** then load the address into the first descriptor register |
|---|
| 692 | */ |
|---|
| 693 | uint32_t DescPhysAddr; |
|---|
| 694 | |
|---|
| 695 | /* This is our first descriptor, so we must load the first descriptor register */ |
|---|
| 696 | BMEM_ConvertAddressToOffset( hPSub->hMemory, ( void * ) FirstDesc, &DescPhysAddr ); |
|---|
| 697 | |
|---|
| 698 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL2 ); |
|---|
| 699 | |
|---|
| 700 | Reg &= ~( BCHP_MASK( XPT_PSUB_PSUB0_CTRL2, FIRST_DESC_ADDR ) ); |
|---|
| 701 | |
|---|
| 702 | /* |
|---|
| 703 | ** The descriptor address field in the hardware register is wants the address |
|---|
| 704 | ** in 16-byte blocks. See the RDB HTML for details. So, we must shift the |
|---|
| 705 | ** address 4 bits to the right before writing it to the hardware. Note that |
|---|
| 706 | ** the RDB macros will shift the value 4 bits to the left, since the address |
|---|
| 707 | ** bitfield starts at bit 4. Confusing, but thats what the hardware and the |
|---|
| 708 | ** RDB macros require to make this work. |
|---|
| 709 | */ |
|---|
| 710 | DescPhysAddr >>= 4; |
|---|
| 711 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL2, FIRST_DESC_ADDR, DescPhysAddr ); |
|---|
| 712 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL2, Reg ); |
|---|
| 713 | |
|---|
| 714 | /* |
|---|
| 715 | ** If this channel has been started, we need to kick off the hardware |
|---|
| 716 | ** by setting the RUN bit. |
|---|
| 717 | */ |
|---|
| 718 | if( hPSub->Running == true ) |
|---|
| 719 | { |
|---|
| 720 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 721 | RunBit = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT0, RUN ); |
|---|
| 722 | |
|---|
| 723 | if( RunBit ) |
|---|
| 724 | { |
|---|
| 725 | /* |
|---|
| 726 | ** Since the channel was already running in hardware, this means that we |
|---|
| 727 | ** are reloading the first descriptor address due to the channel |
|---|
| 728 | ** finishing before a new descriptor was added. Therefore |
|---|
| 729 | ** we use the wake bit (as we previously set the WAKE_MODE above. |
|---|
| 730 | */ |
|---|
| 731 | Reg &= ~( BCHP_MASK( XPT_PSUB_PSUB0_STAT0, WAKE ) ); |
|---|
| 732 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, WAKE, 1 ); |
|---|
| 733 | } |
|---|
| 734 | else |
|---|
| 735 | { |
|---|
| 736 | Reg &= ~( BCHP_MASK( XPT_PSUB_PSUB0_STAT0, RUN ) ); |
|---|
| 737 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, RUN, 1 ); |
|---|
| 738 | } |
|---|
| 739 | |
|---|
| 740 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0, Reg ); |
|---|
| 741 | } |
|---|
| 742 | } |
|---|
| 743 | |
|---|
| 744 | /* This descriptor is always the new last descriptor */ |
|---|
| 745 | hPSub->LastDescriptor = ( uint32_t ) LastDesc; |
|---|
| 746 | |
|---|
| 747 | return( ExitCode ); |
|---|
| 748 | } |
|---|
| 749 | |
|---|
| 750 | BERR_Code BXPT_PacketSub_GetCurrentDescriptorAddress( |
|---|
| 751 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 752 | BXPT_PacketSub_Descriptor **LastDesc /* [in] Address of the current descriptor. */ |
|---|
| 753 | ) |
|---|
| 754 | { |
|---|
| 755 | uint32_t Reg, CurrentDescAddr; |
|---|
| 756 | void *UserDescAddr; |
|---|
| 757 | |
|---|
| 758 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 759 | |
|---|
| 760 | BDBG_ASSERT( hPSub ); |
|---|
| 761 | |
|---|
| 762 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT1 ); |
|---|
| 763 | CurrentDescAddr = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT1, CURR_DESC_ADDR ); |
|---|
| 764 | CurrentDescAddr <<= 4; /* Convert to byte-address. */ |
|---|
| 765 | BERR_TRACE( BMEM_ConvertOffsetToAddress( hPSub->hMemory, CurrentDescAddr, ( void ** ) &UserDescAddr ) ); |
|---|
| 766 | *LastDesc = ( BXPT_PacketSub_Descriptor * ) UserDescAddr; |
|---|
| 767 | |
|---|
| 768 | return( ExitCode ); |
|---|
| 769 | } |
|---|
| 770 | |
|---|
| 771 | BERR_Code BXPT_PacketSub_CheckHeadDescriptor( |
|---|
| 772 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 773 | BXPT_PacketSub_Descriptor *Desc, /* [in] Descriptor to check. */ |
|---|
| 774 | bool *InUse, /* [out] Is descriptor in use? */ |
|---|
| 775 | uint32_t *BufferSize /* [out] Size of the buffer (in bytes). */ |
|---|
| 776 | ) |
|---|
| 777 | { |
|---|
| 778 | uint32_t Reg, ChanBusy, CurrentDescAddr, CandidateDescPhysAddr; |
|---|
| 779 | |
|---|
| 780 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 781 | |
|---|
| 782 | BDBG_ASSERT( hPSub ); |
|---|
| 783 | |
|---|
| 784 | /* |
|---|
| 785 | ** Check if the current descriptor being processed by the |
|---|
| 786 | ** playback hardware is the first on our hardware list |
|---|
| 787 | ** (which means this descriptor is still being used) |
|---|
| 788 | */ |
|---|
| 789 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT1 ); |
|---|
| 790 | |
|---|
| 791 | CurrentDescAddr = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT1, CURR_DESC_ADDR ); |
|---|
| 792 | CurrentDescAddr <<= 4; /* Convert to byte-address. */ |
|---|
| 793 | |
|---|
| 794 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 795 | ChanBusy = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT0, BUSY ); |
|---|
| 796 | |
|---|
| 797 | BMEM_ConvertAddressToOffset( hPSub->hMemory, ( void * ) Desc, &CandidateDescPhysAddr ); |
|---|
| 798 | |
|---|
| 799 | if( CurrentDescAddr == CandidateDescPhysAddr ) |
|---|
| 800 | { |
|---|
| 801 | if( ChanBusy ) |
|---|
| 802 | { |
|---|
| 803 | /* The candidate descriptor is being used by hardware. */ |
|---|
| 804 | *InUse = true; |
|---|
| 805 | } |
|---|
| 806 | else |
|---|
| 807 | { |
|---|
| 808 | *InUse = false; |
|---|
| 809 | } |
|---|
| 810 | } |
|---|
| 811 | else |
|---|
| 812 | { |
|---|
| 813 | /* |
|---|
| 814 | ** The candidate descriptor isn't being processed. If this is the head descriptor |
|---|
| 815 | ** we can conclude that the hardware is finished with the descriptor. |
|---|
| 816 | */ |
|---|
| 817 | *InUse = false; |
|---|
| 818 | } |
|---|
| 819 | |
|---|
| 820 | if( *InUse == false ) |
|---|
| 821 | { |
|---|
| 822 | if( ChanBusy ) |
|---|
| 823 | { |
|---|
| 824 | *BufferSize = Desc->BufferLength; |
|---|
| 825 | } |
|---|
| 826 | else |
|---|
| 827 | { |
|---|
| 828 | /* |
|---|
| 829 | ** Since there is valid data in the record channel even after it is stopped, |
|---|
| 830 | ** we are unable to detect if we are done or not with a specific descriptor |
|---|
| 831 | ** after the record channel has been halted. |
|---|
| 832 | ** This check needs to be performed at a higher level |
|---|
| 833 | */ |
|---|
| 834 | *BufferSize = 0; |
|---|
| 835 | *InUse = true; |
|---|
| 836 | } |
|---|
| 837 | } |
|---|
| 838 | else |
|---|
| 839 | { |
|---|
| 840 | *BufferSize = 0; |
|---|
| 841 | } |
|---|
| 842 | |
|---|
| 843 | return( ExitCode ); |
|---|
| 844 | } |
|---|
| 845 | |
|---|
| 846 | BERR_Code BXPT_PacketSub_StartChannel( |
|---|
| 847 | BXPT_PacketSub_Handle hPSub /* [in] Handle for the channel. */ |
|---|
| 848 | ) |
|---|
| 849 | { |
|---|
| 850 | uint32_t Reg; |
|---|
| 851 | |
|---|
| 852 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 853 | |
|---|
| 854 | BDBG_ASSERT( hPSub ); |
|---|
| 855 | |
|---|
| 856 | BDBG_MSG(( "Starting Packet Sub channel %d", ( unsigned long ) hPSub->ChannelNo )); |
|---|
| 857 | |
|---|
| 858 | if( hPSub->Running == true ) |
|---|
| 859 | { |
|---|
| 860 | BDBG_ERR(( "Packet Sub channel %d cannot be started because it's already running!", |
|---|
| 861 | ( unsigned long ) hPSub->ChannelNo )); |
|---|
| 862 | ExitCode = BERR_TRACE( BXPT_ERR_CHANNEL_ALREADY_RUNNING ); |
|---|
| 863 | } |
|---|
| 864 | |
|---|
| 865 | #ifdef BCHP_PWR_RESOURCE_XPT_PACKETSUB |
|---|
| 866 | if( hPSub->Running == false ) |
|---|
| 867 | { |
|---|
| 868 | BCHP_PWR_AcquireResource(hPSub->hChip, BCHP_PWR_RESOURCE_XPT_PACKETSUB); |
|---|
| 869 | } |
|---|
| 870 | #endif |
|---|
| 871 | |
|---|
| 872 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 873 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_CTRL0, PSUB_ENABLE, 1 ); |
|---|
| 874 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 875 | |
|---|
| 876 | /* Check if we have buffers already loaded for this channel */ |
|---|
| 877 | if( hPSub->LastDescriptor ) |
|---|
| 878 | { |
|---|
| 879 | /* Since we already have some buffers loaded, we can start the pvr channel */ |
|---|
| 880 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 881 | Reg |= BCHP_FIELD_DATA( XPT_PSUB_PSUB0_STAT0, RUN, 1 ); |
|---|
| 882 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0, Reg ); |
|---|
| 883 | } |
|---|
| 884 | |
|---|
| 885 | hPSub->Running = true; |
|---|
| 886 | |
|---|
| 887 | return( ExitCode ); |
|---|
| 888 | } |
|---|
| 889 | |
|---|
| 890 | BERR_Code BXPT_PacketSub_StopChannel( |
|---|
| 891 | BXPT_PacketSub_Handle hPSub /* [in] Handle for the channel. */ |
|---|
| 892 | ) |
|---|
| 893 | { |
|---|
| 894 | uint32_t Reg, ChanBusy, WaitCount; |
|---|
| 895 | |
|---|
| 896 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 897 | |
|---|
| 898 | BDBG_ASSERT( hPSub ); |
|---|
| 899 | |
|---|
| 900 | BDBG_MSG(( "Stopping Packet Sub channel %d", ( unsigned long ) hPSub->ChannelNo )); |
|---|
| 901 | |
|---|
| 902 | if( hPSub->Running == false ) |
|---|
| 903 | { |
|---|
| 904 | BDBG_ERR(( "Packet Sub channel %d cannot be stopped because it's not running!", |
|---|
| 905 | ( unsigned long ) hPSub->ChannelNo )); |
|---|
| 906 | ExitCode = BERR_TRACE( BXPT_ERR_CHANNEL_ALREADY_STOPPED ); |
|---|
| 907 | } |
|---|
| 908 | |
|---|
| 909 | /* Stop the channel hardware */ |
|---|
| 910 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 911 | Reg &= ~( BCHP_MASK( XPT_PSUB_PSUB0_STAT0, RUN ) ); |
|---|
| 912 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0, Reg ); |
|---|
| 913 | |
|---|
| 914 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0 ); |
|---|
| 915 | Reg &= ~( BCHP_MASK( XPT_PSUB_PSUB0_CTRL0, PSUB_ENABLE ) ); |
|---|
| 916 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL0, Reg ); |
|---|
| 917 | |
|---|
| 918 | BKNI_Sleep( 1 ); |
|---|
| 919 | |
|---|
| 920 | /* Clear the first desc addr (for cleaner debugging) */ |
|---|
| 921 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL2 ); |
|---|
| 922 | Reg &= ~( BCHP_MASK( XPT_PSUB_PSUB0_CTRL2, FIRST_DESC_ADDR ) ); |
|---|
| 923 | BXPT_PacketSub_P_WriteReg( hPSub, BCHP_XPT_PSUB_PSUB0_CTRL2, Reg ); |
|---|
| 924 | |
|---|
| 925 | WaitCount = 100; |
|---|
| 926 | do |
|---|
| 927 | { |
|---|
| 928 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 929 | ChanBusy = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT0, BUSY ); |
|---|
| 930 | if( ChanBusy ) |
|---|
| 931 | { |
|---|
| 932 | WaitCount--; |
|---|
| 933 | if( !WaitCount ) |
|---|
| 934 | { |
|---|
| 935 | BDBG_ERR(("Busy is still set when Packet Sub chan %d has been stopped!", |
|---|
| 936 | ( unsigned long ) hPSub->ChannelNo )); |
|---|
| 937 | return BERR_TRACE( BERR_TIMEOUT ); |
|---|
| 938 | } |
|---|
| 939 | |
|---|
| 940 | BKNI_Sleep( 1 ); |
|---|
| 941 | } |
|---|
| 942 | } |
|---|
| 943 | while( ChanBusy ); |
|---|
| 944 | |
|---|
| 945 | hPSub->LastDescriptor = 0; |
|---|
| 946 | |
|---|
| 947 | #ifdef BCHP_PWR_RESOURCE_XPT_PACKETSUB |
|---|
| 948 | if (hPSub->Running==true) |
|---|
| 949 | { |
|---|
| 950 | BCHP_PWR_ReleaseResource(hPSub->hChip, BCHP_PWR_RESOURCE_XPT_PACKETSUB); |
|---|
| 951 | } |
|---|
| 952 | #endif |
|---|
| 953 | |
|---|
| 954 | hPSub->Running = false; |
|---|
| 955 | |
|---|
| 956 | return( ExitCode ); |
|---|
| 957 | } |
|---|
| 958 | |
|---|
| 959 | BERR_Code BXPT_PacketSub_GetChannelStatus( |
|---|
| 960 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 961 | BXPT_PacketSub_ChannelStatus *Status /* [out] Channel status. */ |
|---|
| 962 | ) |
|---|
| 963 | { |
|---|
| 964 | uint32_t Reg; |
|---|
| 965 | |
|---|
| 966 | BERR_Code ExitCode = BERR_SUCCESS; |
|---|
| 967 | |
|---|
| 968 | BDBG_ASSERT( hPSub ); |
|---|
| 969 | BDBG_ASSERT( Status ); |
|---|
| 970 | |
|---|
| 971 | Reg = BXPT_PacketSub_P_ReadReg( hPSub, BCHP_XPT_PSUB_PSUB0_STAT0 ); |
|---|
| 972 | Status->Finished = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT0, FINISHED ) ? true : false; |
|---|
| 973 | Status->Busy = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT0, BUSY ) ? true : false; |
|---|
| 974 | Status->Run = BCHP_GET_FIELD_DATA( Reg, XPT_PSUB_PSUB0_STAT0, RUN ) ? true : false; |
|---|
| 975 | |
|---|
| 976 | return( ExitCode ); |
|---|
| 977 | } |
|---|
| 978 | |
|---|
| 979 | void BXPT_PacketSub_P_WriteReg( |
|---|
| 980 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 981 | uint32_t Reg0Addr, |
|---|
| 982 | uint32_t RegVal |
|---|
| 983 | ) |
|---|
| 984 | { |
|---|
| 985 | /* |
|---|
| 986 | ** The address is the offset of the register from the beginning of the |
|---|
| 987 | ** block, plus the base address of the block ( which changes from |
|---|
| 988 | ** channel to channel ). |
|---|
| 989 | */ |
|---|
| 990 | uint32_t RegAddr = Reg0Addr - BCHP_XPT_PSUB_PSUB0_CTRL0 + hPSub->BaseAddr; |
|---|
| 991 | |
|---|
| 992 | BREG_Write32( hPSub->hRegister, RegAddr, RegVal ); |
|---|
| 993 | } |
|---|
| 994 | |
|---|
| 995 | |
|---|
| 996 | uint32_t BXPT_PacketSub_P_ReadReg( |
|---|
| 997 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 998 | uint32_t Reg0Addr |
|---|
| 999 | ) |
|---|
| 1000 | { |
|---|
| 1001 | /* |
|---|
| 1002 | ** The address is the offset of the register from the beginning of the |
|---|
| 1003 | ** block, plus the base address of the block ( which changes from |
|---|
| 1004 | ** channel to channel ). |
|---|
| 1005 | */ |
|---|
| 1006 | uint32_t RegAddr = Reg0Addr - BCHP_XPT_PSUB_PSUB0_CTRL0 + hPSub->BaseAddr; |
|---|
| 1007 | |
|---|
| 1008 | return( BREG_Read32( hPSub->hRegister, RegAddr )); |
|---|
| 1009 | } |
|---|
| 1010 | |
|---|
| 1011 | BERR_Code BXPT_PacketSub_GetEobIntId( |
|---|
| 1012 | BXPT_PacketSub_Handle hPSub, /* [in] Handle for the channel. */ |
|---|
| 1013 | BINT_Id *IntId |
|---|
| 1014 | ) |
|---|
| 1015 | { |
|---|
| 1016 | BDBG_ASSERT( hPSub ); |
|---|
| 1017 | BDBG_ASSERT( IntId ); |
|---|
| 1018 | |
|---|
| 1019 | switch( hPSub->ChannelNo ) |
|---|
| 1020 | { |
|---|
| 1021 | case 0: *IntId = BCHP_INT_ID_PSUB0_EOB_INT; break; |
|---|
| 1022 | case 1: *IntId = BCHP_INT_ID_PSUB1_EOB_INT; break; |
|---|
| 1023 | case 2: *IntId = BCHP_INT_ID_PSUB2_EOB_INT; break; |
|---|
| 1024 | |
|---|
| 1025 | #ifdef BCHP_INT_ID_PSUB3_EOB_INT |
|---|
| 1026 | case 3: *IntId = BCHP_INT_ID_PSUB3_EOB_INT; break; |
|---|
| 1027 | #endif |
|---|
| 1028 | |
|---|
| 1029 | #ifdef BCHP_INT_ID_PSUB4_EOB_INT |
|---|
| 1030 | case 4: *IntId = BCHP_INT_ID_PSUB4_EOB_INT; break; |
|---|
| 1031 | #endif |
|---|
| 1032 | |
|---|
| 1033 | #ifdef BCHP_INT_ID_PSUB5_EOB_INT |
|---|
| 1034 | case 5: *IntId = BCHP_INT_ID_PSUB5_EOB_INT; break; |
|---|
| 1035 | #endif |
|---|
| 1036 | |
|---|
| 1037 | #ifdef BCHP_INT_ID_PSUB6_EOB_INT |
|---|
| 1038 | case 6: *IntId = BCHP_INT_ID_PSUB6_EOB_INT; break; |
|---|
| 1039 | #endif |
|---|
| 1040 | |
|---|
| 1041 | #ifdef BCHP_INT_ID_PSUB7_EOB_INT |
|---|
| 1042 | case 7: *IntId = BCHP_INT_ID_PSUB7_EOB_INT; break; |
|---|
| 1043 | #endif |
|---|
| 1044 | |
|---|
| 1045 | default: |
|---|
| 1046 | return BERR_TRACE( BERR_INVALID_PARAMETER ); |
|---|
| 1047 | } |
|---|
| 1048 | |
|---|
| 1049 | return BERR_SUCCESS; |
|---|
| 1050 | } |
|---|
| 1051 | |
|---|
| 1052 | /* end of file */ |
|---|
| 1053 | |
|---|