/*=========================================================================== FUNCTION DIAGCOMM_SMD_SEND DESCRIPTION Sends a packet over SMD channel PARAMETERS req_pkt - packet to send pkt_len - length of 'req_pkt' port_num - channel to send pkt on RETURN VALUE None ===========================================================================*/ void diagcomm_smd_send( void *req_pkt, uint16 pkt_len, diagcomm_enum_port_type port_num ) { diagcomm_io_tx_params_type tx_params; dsm_item_type *app_req_item_ptr = NULL; if( diagcomm_status() && diagcomm_smd_status(port_num) ) { ASSERT(req_pkt != NULL); if( dsm_pushdown_tail(&app_req_item_ptr, req_pkt, pkt_len, DSM_DIAG_SMD_RX_ITEM_POOL) == pkt_len ) { tx_params.dsm_ptr = app_req_item_ptr; diagcomm_io_transmit( &diagcomm_io_conn[DIAGCOMM_PORT_SMD][port_num], &tx_params, FALSE ); diag_sleep_vote(DIAG_SLEEP_DIAG, TRUE); } else { dsm_free_packet(&app_req_item_ptr); MSG(MSG_SSID_DIAG, MSG_LEGACY_HIGH, "diagcomm_smd_send - Ran out of DSM items"); } } } /* diagcomm_smd_send */
/*=========================================================================== FUNCTION DSRLPDEL_ADD DESCRIPTION Adds an element to the frame detection array. Puts it in order in the array. DEPENDENCIES None RETURN VALUE None SIDE EFFECTS None ===========================================================================*/ void dsrlpdel_add ( dsrlpi_sess_ctl_blk_type *rscb_ptr, dsm_item_type *fr_item_ptr, dsrlpi_curr_fr_info_type *curr_info_ptr ) { rlpdel_fr_array_type *fr_arr_ptr; /* points to array to add to */ rlpdel_fr_detect_type *fr_detect_ptr;/* points to delay frame struct */ byte curr_idx; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ASSERT(rscb_ptr->state.del_fr_id < DSRLPI_MAX_SESSIONS); ASSERT(rlpdel_fr_detect[rscb_ptr->state.del_fr_id].used == TRUE); if (fr_item_ptr == NULL) { ERR("Passed null item ptr",0,0,0); return; } fr_detect_ptr = &(rlpdel_fr_detect[rscb_ptr->state.del_fr_id]); fr_arr_ptr = &(fr_detect_ptr->del_fr_arr[fr_detect_ptr->add_idx]); if (fr_arr_ptr->index >= RLP_MAX_FWD_PDU) { ERR("too many items in del. fr array",0,0,0); dsm_free_packet(&fr_item_ptr); return; } curr_idx = fr_arr_ptr->index; fr_arr_ptr->index++; /*------------------------------------------------------------------------- Insert this frame into the array, in sorted order. If the loop terminates, then this frame goes into the first slot. -------------------------------------------------------------------------*/ while(curr_idx > 0) { if(DSRLPSEQ_GE_SEQ_CHECK(curr_info_ptr->seq_num, fr_arr_ptr->fr_arr[curr_idx - 1].curr_info.seq_num, rscb_ptr->ver_ptr->seq_modulus)) { fr_arr_ptr->fr_arr[curr_idx].fr_item_ptr = fr_item_ptr; fr_arr_ptr->fr_arr[curr_idx].curr_info = *curr_info_ptr; return; } else { fr_arr_ptr->fr_arr[curr_idx] = fr_arr_ptr->fr_arr[curr_idx - 1]; curr_idx--; } } /* while */ fr_arr_ptr->fr_arr[0].fr_item_ptr = fr_item_ptr; fr_arr_ptr->fr_arr[0].curr_info = *curr_info_ptr; } /* dsrlpdel_add() */
/*=========================================================================== FUNCTION dsmutili_new_packet DESCRIPTION Based on the dsm_size_requested, this function will allocate a dsm items which can hold 'dsm_size_requested'. This function will do necessary chaining of DSM items if requested size doesnt fit in one DSM item. Total Size of the DSM chain is expected to be equal or greater than requested size. DEPENDENCIES None PARAMETERS pool_id - DSM Pool from which new item should be allocated dsm_size_requested - requested size of the buffer RETURN VALUE Chain of DSM pointers w/ empty payload such that total size of chain is equal to or greater than dsm_size_requested. It returns NULL if it fails to allocate requested size. SIDE EFFECTS Caller of this function is expected to have necessary handling whenever this function returns chain of DSM items. ===========================================================================*/ dsm_item_type *dsmutili_new_packet ( dsm_mempool_id_type pool_id, uint32 dsm_size_requested, const char * file, uint32 line ) { dsm_item_type *head_dsm_ptr = NULL, *tail_dsm_ptr = NULL; dsm_item_type *allocated_dsm_ptr = NULL; int16 remaining_size = (int16) dsm_size_requested; uint16 allocated_dsm_size = DSM_POOL_ITEM_SIZE(pool_id); while (remaining_size > 0) { if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(pool_id, file, line))) { /* No free DSM items are available in a given pool id, exit out of the loop */ break; } if (remaining_size != (int16) dsm_size_requested) { tail_dsm_ptr->pkt_ptr = allocated_dsm_ptr; tail_dsm_ptr = allocated_dsm_ptr; } else { head_dsm_ptr = allocated_dsm_ptr; tail_dsm_ptr = allocated_dsm_ptr; } /* update remaining size */ remaining_size -= allocated_dsm_size; } /* check whether a given pool has run out of the free items. If yes, then free any allocated dsm items */ if (NULL != allocated_dsm_ptr) { return(head_dsm_ptr); } else { dsm_free_packet(&head_dsm_ptr); head_dsm_ptr = NULL; return(head_dsm_ptr); } }
/*=========================================================================== FUNCTION DSSICMP_CLOSE() DESCRIPTION This function is the ICMP specific dss_close() function. It simply sets the socket state to DSSOCKI_NULL and frees up the socket control block and related data structures. DEPENDENCIES None. RETURN VALUE DSS_SUCCESS on success; DSS_ERROR otherwise. SIDE EFFECTS None. ===========================================================================*/ extern sint15 dssicmp_close ( struct scb_s* scb_ptr, /* Ptr to socket control block for the socket */ sint15 *dss_errno /* error condition value */ ) { struct icmp_cb *icmp_cb_ptr; /* ICMP protocol control block */ dsm_item_type *item_ptr; /* temporary item ptr */ /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /*------------------------------------------------------------------------- Assert that a valid ptr to a dss_errno variable was specified - Prevents dereferencing of NULL ptrs. -------------------------------------------------------------------------*/ if (dss_errno == NULL) { ASSERT(0); return(DSS_ERROR); } *dss_errno = DSS_SUCCESS; icmp_cb_ptr = (struct icmp_cb *) scb_ptr->protocol_ctl_blk.icb; /*------------------------------------------------------------------------- Free the receive queue for the ICMP control block. ------------------------------------------------------------------------*/ while(( item_ptr = (dsm_item_type *) q_get( &(icmp_cb_ptr->rcvq))) != NULL) { dsm_free_packet(&item_ptr); } /*------------------------------------------------------------------------- Free the ICMP control block. ------------------------------------------------------------------------*/ dssicmpi_free_icmp_cb(icmp_cb_ptr); /*------------------------------------------------------------------------- Free the socket control block. ------------------------------------------------------------------------*/ dssocki_freescb(scb_ptr); return (DSS_SUCCESS); } /* dssicmp_close () */
/*=========================================================================== FUNCTION DSM_SDU_TO_PKT_CHAIN_BYTE DESCRIPTION Copy the given SDU to an allocating DSM item packet in size bytes. DEPENDENCIES None. RETURN VALUE The allocated dsm item packet chain pointer. If failed, it returns NULL pointer. SIDE EFFECTS None ===========================================================================*/ dsm_item_type *dsm_sdu_to_pkt_chain_byte ( void *buf, /* Ptr. to bytes to copy */ word size /* size in bytes of copying */ ) { dsm_item_type *pkt_head_ptr = NULL; /* Address of ptr to head of packet */ if ((dsm_pushdown_tail(&pkt_head_ptr, buf, size, DSM_DS_SMALL_ITEM_POOL)) != size) { /* Failed to allocated needed dsm items. Release those dsm */ /* item being allocated and set pkt_head_ptr to NULL */ dsm_free_packet(&pkt_head_ptr); pkt_head_ptr = NULL; MSG(MSG_SSID_DFLT, MSG_LEGACY_ERROR,"Failed to obtain enough memory"); } return (pkt_head_ptr); }
/*=========================================================================== FUNCTION DSRLPDEL_RESET DESCRIPTION Cleans up the arrays, and resets struct back to initial state. DEPENDENCIES None RETURN VALUE NONE SIDE EFFECTS None ===========================================================================*/ void dsrlpdel_reset ( uint32 rlpdel_id ) { rlpdel_fr_array_type* fr_arr_ptr; /* points to struct to clean up */ word i, j; /* for loop indices */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ASSERT(rlpdel_id < DSRLPI_MAX_SESSIONS); ASSERT(rlpdel_fr_detect[rlpdel_id].used == TRUE); for (i = 0; i < RLPDEL_ARR_SIZ; i++) { fr_arr_ptr = &(rlpdel_fr_detect[rlpdel_id].del_fr_arr[i]); for( j = 0; j < fr_arr_ptr->index; j++) { dsm_free_packet( &( fr_arr_ptr->fr_arr[j].fr_item_ptr)); } fr_arr_ptr->index = 0; } rlpdel_fr_detect[rlpdel_id].add_idx =0; rlpdel_fr_detect[rlpdel_id].remove_idx =0; }
sint15 send_tcp ( register struct tcb *tcb, /* ptr to TCP Control Block */ dsm_item_type *new_item_ptr /* ptr to data item for TCP output */ ) { word cnt; /* holds count of new data bytes */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef FEATURE_DSM_MEM_CHK /*--------------------------------------------------------- Set tracer to indicate where the item is being stored ---------------------------------------------------------*/ new_item_ptr->tracer = DSM_TCP_SNDQ; #endif if(tcb == NULL || new_item_ptr == NULL) { dsm_free_packet( &new_item_ptr); return -1; } cnt = 0; switch(tcb->state) { case TCP_CLOSED: dsm_free_packet( &new_item_ptr); return -1; case TCP_LISTEN: /* -------------------------------------------------------------- If any remote address is 0, then it is a passive connection (LtoM). We stay in LISTEN state till we receive TCP packets from the IWF. Earlier the remote address was set to 0 in psmgr.c, so we enter the if when we are in passive mode and don't have dest. port # yet ----------------------------------------------------------------*/ if(tcb->conn.remote.address == 0 || tcb->conn.remote.port == 0) { /* Save data for later */ cnt = append_to_sndq( tcb, new_item_ptr); break; } /* Change state from passive to active */ tcb->flags.active = 1; send_syn(tcb); setstate(tcb,TCP_SYN_SENT); /* Note fall-thru */ case TCP_SYN_SENT: case TCP_SYN_RECEIVED: case TCP_ESTABLISHED: case TCP_CLOSE_WAIT: cnt = append_to_sndq( tcb, new_item_ptr); tcp_output(tcb); break; case TCP_FINWAIT1: case TCP_FINWAIT2: case TCP_CLOSING: case TCP_LAST_ACK: case TCP_TIME_WAIT: dsm_free_packet( &new_item_ptr); return -1; } return cnt; }
/*=========================================================================== FUNCTION DSSICMP_READ() DESCRIPTION Reads 'nbytes' bytes into the buffer from the ICMP transport. Fills in address structure with values from who sent the data in fromaddr. This function asserts that fromaddr is not NULL. This function is the ICMP specific dss_recvfrom() DEPENDENCIES None. PARAMETERS struct scb_s* scb_ptr - Ptr to socket control block for the socket void *buffer - user buffer from which to copy the data uint16 nbytes - number of bytes app wants to read struct sockaddr_in *fromaddr - source address sint15 *dss_errno - error condition value RETURN VALUE n - the number of bytes to be written, which could be less than the number of bytes specified. On error, return DSS_ERROR and places the error condition value in *dss_errno. Errno Values ------------ DS_EWOULDBLOCK operation would block SIDE EFFECTS None. ===========================================================================*/ extern sint15 dssicmp_read ( struct scb_s* scb_ptr, /* Ptr to socket control block for the socket */ struct iovec * iov, /* user buffer from which to copy the data */ uint16 iovcount, /* length of the iovec array */ struct sockaddr_in *fromaddr, /* source address */ sint15 *dss_errno /* error condition value */ ) { struct icmp_cb *icmp_cb_ptr; /* ICMP protocol control block */ dsm_item_type *item_ptr; /* ptr to head of dsm memory pool items */ uint16 cnt=0; /* tmp # of bytes retrieved */ uint16 bytes_read =0; /* # of bytes to read from rcvq */ uint16 read_cnt=0; /* # of bytes read in each iteration */ uint16 payload_len=0; /* packet length */ int i; /* local loop index */ uint16 bytes_requested; /* # of bytes requested in each iteration */ /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ MSG_LOW("In dssicmp_read()", 0, 0, 0); /*------------------------------------------------------------------------- Ensure that the "from address" is not NULL. This function fills in this structure, thus, needs to ASSERT against dereferencing a NULL pointer. ------------------------------------------------------------------------*/ ASSERT( fromaddr != NULL); /*------------------------------------------------------------------------- Set the socket and ICMP control block pointers, and set the family to AF_INET. -------------------------------------------------------------------------*/ icmp_cb_ptr = scb_ptr->protocol_ctl_blk.icb; fromaddr->sin_family = AF_INET; MSG_LOW("ICMP CB pointer successfully set", 0, 0, 0); /*------------------------------------------------------------------------- Check if there is anything in the ICMP receive queue. If not, return DS_EWOULDBLOCK. -------------------------------------------------------------------------*/ if ( (item_ptr = (dsm_item_type *) q_get( (&(icmp_cb_ptr->rcvq)))) == NULL) { MSG_LOW("Nothing on ICMP revq", 0, 0, 0); *dss_errno = DS_EWOULDBLOCK; return (DSS_ERROR); } MSG_LOW("There is indeed something on the ICMP rcvq", 0, 0, 0); /*------------------------------------------------------------------------- Extract the payload length, server's IP address and store in fromaddr. ASSERT that bytes to read, are equal to the number of bytes pulled up. The port field will be undefined in the fromaddr structure returned to the application. -------------------------------------------------------------------------*/ cnt = dsm_pullup(&item_ptr, &(fromaddr->sin_addr), sizeof(fromaddr->sin_addr)); ASSERT( cnt == sizeof(fromaddr->sin_addr) ); MSG_MED("extracted server's IP %x", fromaddr->sin_addr.s_addr, 0, 0); /*------------------------------------------------------------------------- Extract the number of bytes which the application wants to read. -------------------------------------------------------------------------*/ payload_len = dsm_length_packet( item_ptr ); for(i=0;i< iovcount && payload_len > 0 ; i++) { /*----------------------------------------------------------------------- Extract the number of bytes which the application wants to read. -----------------------------------------------------------------------*/ bytes_requested = MIN( payload_len, iov[i].iov_len); if(bytes_requested > 0) { read_cnt = dsm_pullup( &(item_ptr), iov[i].iov_base, bytes_requested); } /*----------------------------------------------------------------------- ASSERT that we read the expected number of bytes from the buffer. -----------------------------------------------------------------------*/ ASSERT(read_cnt == bytes_requested); payload_len -= read_cnt; bytes_read += read_cnt; read_cnt = 0; } if (payload_len > 0 ) { ERR("User provided buffer is smaller than received datagram (%d bytes)", bytes_read + payload_len, 0, 0); } MSG_LOW("Successfully read nbytes of data in DSSICMP_READ", 0, 0, 0); /*------------------------------------------------------------------------- Free the packet in dsm buffer. -------------------------------------------------------------------------*/ dsm_free_packet ( &item_ptr ); MSG_LOW("Packet is successfully freed in DSSICMP_READ", 0, 0, 0); /*------------------------------------------------------------------------- Check if there are any remaining ICMP packets in the receive queue. Set the readable flag to FALSE, if there are no remaining ICMP packets. Access to global SCB array item is protected through INTLOCK()/INTFREE(). -------------------------------------------------------------------------*/ if ( (item_ptr = (dsm_item_type *) q_check( &(icmp_cb_ptr->rcvq))) == NULL) { INTLOCK(); scb_ptr->data_available = FALSE; INTFREE(); } /*------------------------------------------------------------------------- Convert the server IP address into the Network byte order. Note, only the IP address is in host order, the port number is not. -------------------------------------------------------------------------*/ (fromaddr->sin_addr).s_addr = dss_htonl( (fromaddr->sin_addr).s_addr); /*------------------------------------------------------------------------- Return the number of bytes read from the buffer. -------------------------------------------------------------------------*/ MSG_LOW("DONE ICMPREAD", 0, 0, 0); return ( (sint15) bytes_read); } /* dssudp_read() */
/*=========================================================================== FUNCTION LCP_CHECK() DESCRIPTION This function will Check the options, updating the working values. DEPENDENCIES None RETURN VALUE Returns -1 if ran out of data, ACK/NAK/REJ as appropriate. SIDE EFFECTS None ===========================================================================*/ static int lcp_check ( ppp_fsm_type *fsm_ptr, struct option_hdr *ohp, dsm_item_type **bpp, int request ) { lcp_value_type * lworkp; lcp_value_type * rworkp; ppp_fsm_side_type * side_p; lcp_value_type * s_want_ptr; lcp_value_type * s_work_ptr; int used = 0; int option_result = CONFIG_ACK; /* Assume good values */ int n_type = 0; int16 rx_chap_digest; /* chap digest from peer */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if( bpp == NULL ) { MSG_ERROR("Invalid DSM", 0, 0, 0); return -1; } if( fsm_ptr == NULL || ohp == NULL || ohp->length < OPTION_HDR_LEN || fsm_ptr->device >= PPP_MAX_DEV ) { MSG_ERROR("Invalid args", 0, 0, 0); dsm_free_packet(bpp); return -1; } used = ohp->length - OPTION_HDR_LEN; n_type = fsm_n_option(fsm_ptr->pdc,ohp->type); lworkp = (lcp_value_type *)fsm_ptr->local.work_pdv; rworkp = (lcp_value_type *)fsm_ptr->remote.work_pdv; side_p = (ppp_fsm_side_type *)(request ? &(fsm_ptr->remote) : &(fsm_ptr->local)); s_want_ptr = (lcp_value_type *)side_p->want_pdv; s_work_ptr = (lcp_value_type *)side_p->work_pdv; /*------------------------------------------------------------------------- see if we allow this option -------------------------------------------------------------------------*/ if (ohp->type > LCP_OPTION_LIMIT || ohp->length < option_length[n_type] || !((side_p->will | side_p->want) & (1 << n_type))) { /*----------------------------------------------------------------------- toss any bytes in option -----------------------------------------------------------------------*/ while( used-- > 0 ) { if ( dsm_pull8(bpp) == -1 ) { return -1; } } return CONFIG_REJ; } /* if(unsupported option) */ switch(ohp->type) { case LCP_MRU: /* max receive unit */ s_work_ptr->mru = dsm_pull16(bpp); used -= 2; /*----------------------------------------------------------------------- Check if new value is appropriate -----------------------------------------------------------------------*/ if(s_work_ptr->mru < LCP_MRU_LO) { s_work_ptr->mru = LCP_MRU_LO; option_result = CONFIG_NAK; } else if (s_work_ptr->mru > LCP_MRU_HI) { s_work_ptr->mru = LCP_MRU_HI; option_result = CONFIG_NAK; } if(request && (side_p->want & LCP_N_MRU) && s_work_ptr->mru > s_want_ptr->mru) { /*--------------------------------------------------------------------- send a smaller packet anyway -----------------------------------------------------------------------*/ s_work_ptr->mru = s_want_ptr->mru; } break; case LCP_ACCM: /* async control character map */ s_work_ptr->accm = dsm_pull32(bpp); used -= 4; /*----------------------------------------------------------------------- Remote host may ask to escape more control characters than we require, but must escape at least the control chars that we require. -----------------------------------------------------------------------*/ if ((side_p->want & LCP_N_ACCM) && s_work_ptr->accm != (s_work_ptr->accm | s_want_ptr->accm)) { s_work_ptr->accm |= s_want_ptr->accm; option_result = CONFIG_NAK; } break; case LCP_AP: /* Authentication protocol */ s_work_ptr->authentication = dsm_pull16(bpp); /* get the protocol */ used -= 2; /*----------------------------------------------------------------------- Check if requested authentication protocol is PAP or CHAP or NONE -----------------------------------------------------------------------*/ switch (s_work_ptr->authentication) { case PPP_PAP_PROTOCOL: /*--------------------------------------------------------------------- Setting it to send PAP pkts in auth. phase. ---------------------------------------------------------------------*/ ppp_cb_array[fsm_ptr->device].auth.mode = PPP_DO_PAP; MSG_MED(" Received Config. Req. with PAP option",0,0,0); break; case PPP_CHAP_PROTOCOL: /*--------------------------------------------------------------------- Setting it to send CHAP pkts in auth. phase. ---------------------------------------------------------------------*/ ppp_cb_array[fsm_ptr->device].auth.mode = PPP_DO_CHAP; /*--------------------------------------------------------------------- In the incoming packet the CHAP protocol has algorithm field attached to it, i.e. C223 for CHAP and 05 for MD5 or 80 for MD4. Since the current implementation implements only MD5, check if the algorithm is MD5. Since we pulled out one more byte from the incoming packet reduce the used field by one. If the algorithm is not MD5, then send a Config NAK to the base station and request for the MD5. ---------------------------------------------------------------------*/ rx_chap_digest = dsm_pull8(bpp); if(rx_chap_digest == -1) { return -1; } used--; if((s_work_ptr->chap_digest = (uint8)rx_chap_digest) != PPP_CHAP_MD5) { s_work_ptr->chap_digest = PPP_CHAP_MD5; option_result = CONFIG_NAK; } MSG_MED("dev %d got C-req with chap digest: %d", fsm_ptr->device, rx_chap_digest, 0); break; default: /*--------------------------------------------------------------------- Got an unrecognized authentication protocol. Ask for CHAP/PAP in the nak and Send a config_nak which asks for CHAP as the authentication protocol. ---------------------------------------------------------------------*/ MSG_MED("Rxd Unknown Auth proto:0x%x ",s_work_ptr->authentication,0,0); s_work_ptr->authentication = PPP_CHAP_PROTOCOL; s_work_ptr->chap_digest = PPP_CHAP_MD5; option_result = CONFIG_NAK; break; } /* switch(auth type in req) */ break; /* case LCP_AP */ case LCP_MAGIC: /* magic number */ s_work_ptr->magic_number = dsm_pull32(bpp); used -= 4; /*----------------------------------------------------------------------- Ensure that magic numbers are different -----------------------------------------------------------------------*/ if ( s_work_ptr->magic_number == 0L ) { s_work_ptr->magic_number = (uint32)s_work_ptr; option_result = CONFIG_NAK; } else if ( rworkp->magic_number == lworkp->magic_number ) { s_work_ptr->magic_number += msclock(); option_result = CONFIG_NAK; } break; case LCP_PFC: /* protocol field compression */ case LCP_ACFC: /* addr/control field compression */ /* nothing to store here */ break; default: option_result = CONFIG_REJ; break; } /* switch(option type) */ if ( used < 0 ) { return -1; } /*------------------------------------------------------------------------- if there are extra bytes in option toss them. -------------------------------------------------------------------------*/ if ( used > 0 ) { while( used-- > 0 ) { if ( dsm_pull8(bpp) == -1 ) { return -1; } } } return (option_result); } /* lcp_check() */
/*=========================================================================== FUNCTION DIAGCOMM_BUFFER_ENQUEUE_STREAM DESCRIPTION This function enqueues data onto the sio_tx_wmq depending on the current mode. PARAMETERS item_ptr - pointer to the DSM item that has to be enqueued port_type - Control channel port type (SIO/SMD) stream_id - Specifies which stream should the data be enqueued RETURN VALUE None ===========================================================================*/ void diagcomm_buffer_enqueue_stream( dsm_item_type ** item_ptr, diagcomm_port_type port_type, uint8 stream_id ) { dsm_item_type * dsm_dequeue_item_ptr = NULL; dsm_item_type * dsm_chained_ptr = NULL; uint32 dsm_cnt = 0; uint32 dsm_dropped_cnt = 0; uint32 bytes_dropped_cnt = 0; uint32 dsm_alloc_cnt = 0; uint32 bytes_alloc_cnt = 0; uint8 stream_index = 0; if( (stream_id < DIAG_MIN_STREAM_ID) || (stream_id > DIAG_MAX_STREAM_ID) ) { MSG_1(MSG_SSID_DIAG, MSG_LEGACY_ERROR, "diagcomm_buffer_enqueue_stream - Invalid stream_id (%d)", stream_id); return; } stream_index = DIAG_ID_TO_INDEX(stream_id); /* Dequeue and count dropped DSMs only in Buffered Cir mode. */ if( diag_tx_mode[stream_index].mode == DIAG_TX_MODE_BUFFERED_CIR ) { dsm_cnt = diag_buffering_pool_used_cnt( stream_id ); diag_tx_mode[stream_index].cur_dsm_cnt[port_type] = dsm_cnt; //Save dsm count read if( DIAG_BUFFERED_DSM_CNT_TO_BYTES(dsm_cnt) >= diag_tx_mode[stream_index].buffered_many_bytes_mark ) { if( port_type == DIAGCOMM_PORT_SMD ) dsm_dequeue_item_ptr = diagcomm_io_dequeue_rx_wmq( &diagcomm_io_conn[port_type][DIAGCOMM_PORT_1] ); else if( port_type == DIAGCOMM_PORT_SIO ) dsm_dequeue_item_ptr = diagcomm_io_dequeue_tx_wmq( &diagcomm_io_conn[port_type][DIAGCOMM_PORT_1], 0 ); ASSERT( dsm_dequeue_item_ptr != NULL ); //bytes_dropped_cnt += dsm_length_packet( dsm_dequeue_item_ptr ); dsm_chained_ptr = dsm_dequeue_item_ptr; do { dsm_dropped_cnt += 1; bytes_dropped_cnt += dsm_chained_ptr->used; // Point to next DSM in the chain dsm_chained_ptr = dsm_chained_ptr->pkt_ptr; // Continue to count chained DSMs } while( dsm_chained_ptr != NULL ); //} while( (dsm_chained_ptr != NULL) && (dsm_chained_ptr->data_ptr != NULL) && (dsm_chained_ptr->used > 0) ); // Update dropped count health statistics if( (diag_tx_mode[stream_index].dsm_dropped_cnt + dsm_dropped_cnt) >= MAX_VALUE_UINT32 ) diag_tx_mode[stream_index].dsm_dropped_cnt = MAX_VALUE_UINT32; else diag_tx_mode[stream_index].dsm_dropped_cnt += dsm_dropped_cnt; if( (diag_tx_mode[stream_index].byte_dropped_cnt + bytes_dropped_cnt) >= MAX_VALUE_UINT32 ) diag_tx_mode[stream_index].byte_dropped_cnt = MAX_VALUE_UINT32; else diag_tx_mode[stream_index].byte_dropped_cnt += bytes_dropped_cnt; // Free the dequeued DSM item, including it's chained items dsm_free_packet( &dsm_dequeue_item_ptr ); } } /* We don't drop/dequeue DSMs in Buffered Threshold mode. Just count alloc counts and enqueue. */ if( (diag_tx_mode[stream_index].mode == DIAG_TX_MODE_BUFFERED_THRESH) || (diag_tx_mode[stream_index].mode == DIAG_TX_MODE_BUFFERED_CIR) ) { //bytes_alloc_cnt += dsm_length_packet( *item_ptr ); dsm_chained_ptr = *item_ptr; do { dsm_alloc_cnt += 1; bytes_alloc_cnt += dsm_chained_ptr->used; // Point to next DSM in the chain dsm_chained_ptr = dsm_chained_ptr->pkt_ptr; // Continue to count chained DSMs } while( dsm_chained_ptr != NULL ); // Update alloc count health statistics if( (diag_tx_mode[stream_index].dsm_alloc_cnt + dsm_alloc_cnt) >= MAX_VALUE_UINT32 ) diag_tx_mode[stream_index].dsm_alloc_cnt = MAX_VALUE_UINT32; else diag_tx_mode[stream_index].dsm_alloc_cnt += dsm_alloc_cnt; if( (diag_tx_mode[stream_index].byte_alloc_cnt + bytes_alloc_cnt) >= MAX_VALUE_UINT32 ) diag_tx_mode[stream_index].byte_alloc_cnt = MAX_VALUE_UINT32; else diag_tx_mode[stream_index].byte_alloc_cnt += bytes_alloc_cnt; #ifdef DIAG_SIO_SUPPORT if( port_type == DIAGCOMM_PORT_SMD ) dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.sio_params.params.rx_queue, item_ptr); else if( port_type == DIAGCOMM_PORT_SIO ) dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.sio_params.params.tx_queue, item_ptr); #elif defined (DIAG_SMDL_SUPPORT) dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.smdl_params.tx_queue, item_ptr); #endif } else { /* Streaming mode; Just enqueue it. */ #ifdef DIAG_SIO_SUPPORT if( port_type == DIAGCOMM_PORT_SMD ) dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.sio_params.params.rx_queue, item_ptr); else if( port_type == DIAGCOMM_PORT_SIO ) dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.sio_params.params.tx_queue, item_ptr); #elif defined (DIAG_SMDL_SUPPORT) dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.smdl_params.tx_queue, item_ptr); #endif } } /* diagcomm_buffer_enqueue_stream */
/*=========================================================================== FUNCTION dsm_new_packet_flexible DESCRIPTION Based on the dsm_size_requested, function dsmutili_new_packet_flexible() will identify the best pool (SMALL or LARGE) and allocates first item from that pool. This function will return a pointer to the DSM item chain based on the size requested. Total Size of the DSM chain is expected to be equal or greater than requested size. DEPENDENCIES None PARAMETERS dsm_size_requested - requested size of the buffer RETURN VALUE Chain of DSM pointers w/ empty payload such that total size of chain is equal to or greater than dsm_size_requested. It returns NULL if it fails to allocate requested size. SIDE EFFECTS Caller of this function is expected to have necessary handling whenever this function returns chain of DSM items. ===========================================================================*/ dsm_item_type *dsmutili_new_packet_flexible ( dsm_mempool_id_type pool_id, uint32 dsm_size_requested, const char * file, uint32 line ) { #ifdef FEATURE_DSM_DYNAMIC_POOL_SELECTION dsm_item_type *head_dsm_ptr = NULL, *tail_dsm_ptr = NULL; dsm_item_type *allocated_dsm_ptr = NULL; int16 remaining_size = dsm_size_requested; uint16 allocated_size = 0; while (remaining_size > 0) { /* select pool if according to the memory size requested */ if (remaining_size > DSM_FLEXIBLE_LARGE_ITEM_THRESHOLD) { allocated_size = DSM_DS_LARGE_ITEM_SIZ; if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(DSM_DS_LARGE_ITEM_POOL, file, line))) { allocated_size = DSM_DS_SMALL_ITEM_SIZ; if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(DSM_DS_SMALL_ITEM_POOL, file, line))) { /* All the free items have been consumed from both the pools, exit out of the loop */ break; } } } else /* allocate SMALL Item */ { allocated_size = DSM_DS_SMALL_ITEM_SIZ; if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(DSM_DS_SMALL_ITEM_POOL, file, line))) { allocated_size = DSM_DS_LARGE_ITEM_SIZ; if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(DSM_DS_LARGE_ITEM_POOL, file, line))) { /* All the free items have been consumed from both the pools, exit out of do..while loop */ break; } } } if ((uint32)remaining_size != dsm_size_requested) { tail_dsm_ptr->pkt_ptr = allocated_dsm_ptr; tail_dsm_ptr = allocated_dsm_ptr; } else { head_dsm_ptr = allocated_dsm_ptr; tail_dsm_ptr = allocated_dsm_ptr; } /* update remaining size */ remaining_size -= allocated_size; } /* check whether both the pools have run out of the free items. If yes, then free any allocated dsm items */ if (NULL != allocated_dsm_ptr) { return(head_dsm_ptr); } else { dsm_free_packet(&head_dsm_ptr); head_dsm_ptr = NULL; return(head_dsm_ptr); } #else return (dsmutili_new_packet(pool_id, dsm_size_requested, __FILE__,__LINE__)); #endif }