static re_status unexp_stx(struct re_state *rxstate) { #ifdef ASSERTIONS_ENABLED __rt_warning("Unexpected stx\n"); #endif rxstate->crc = startCRC32; rxstate->index = 0; rxstate->rx_state = RST_TYP; rxstate->error = RE_U_STX; rxstate->field_c = 0; return RS_BAD_PKT; }
static re_status unexp_etx(struct re_state *rxstate) { #ifdef ASSERTIONS_ENABLED __rt_warning("Unexpected etx, rxstate: index= 0x%2x, field_c=0x%2x, state=0x%2x\n", rxstate->index, rxstate->field_c, rxstate->rx_state); #endif rxstate->crc = 0; rxstate->index = 0; rxstate->rx_state = RST_STX; rxstate->error = RE_U_ETX; rxstate->field_c = 0; return RS_BAD_PKT; }
re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet, struct re_state *rxstate) { /* * TODO: add the flow control bits in * Note: We test for the data field in a seperate case so we can * completely avoid entering the switch for most chars */ /* see if we're expecting a escaped char */ if ((rxstate->rx_state & RST_ESC) == RST_ESC) { /* unescape the char and unset the flag*/ new_ch &= ~serial_ESCAPE; #ifdef DO_TRACE __rt_trace("rxe-echar-%2x ", new_ch); #endif rxstate->rx_state &= ~RST_ESC; } else if ( (1 << new_ch) & rxstate->config->esc_set ) { /* see if the incoming char is a special one */ if (new_ch == rxstate->config->esc) { #ifdef DO_TRACE __rt_trace("rxe-esc "); #endif rxstate->rx_state |= RST_ESC; return RS_IN_PKT; } else { /* * must be a normal packet so do some unexpected etx/stx checking * we haven't been told to escape or received an escape so unless * we are expecting an stx or etx then we can take the unexpected * stx/etx trap */ if ((new_ch == (rxstate->config->stx)) && (rxstate->rx_state != RST_STX)) return unexp_stx(rxstate); if ((new_ch == (rxstate->config->etx)) && (rxstate->rx_state != RST_ETX)) return unexp_etx(rxstate); } } if (rxstate->rx_state == RST_DAT) { /* * do this to speed up the common case, no real penalty for * other cases */ #ifdef DO_TRACE __rt_trace("rxe-dat "); #endif rxstate->crc = crc32(&new_ch, 1, rxstate->crc); (packet->data)[rxstate->index++] = (unsigned int)new_ch & 0xff; if (rxstate->index == packet->len) rxstate->rx_state = RST_CRC; return RS_IN_PKT; } /* * Now that the common case is out of the way we can test for everything * else without worrying quite so much about the speed, changing the * order to len,crc,stx,etx,typ might gain a tiny bit of speed but lets * leave that for the moment */ switch (rxstate->rx_state) { case RST_STX: if (new_ch == rxstate->config->stx) { rxstate->rx_state = RST_TYP; rxstate->error = RE_OKAY; rxstate->crc = startCRC32; rxstate->index = 0; return RS_IN_PKT; } else { rxstate->error = RE_OKAY; return RS_WAIT_PKT; } case RST_TYP: packet->type = (DevChanID)new_ch; rxstate->rx_state = RST_LEN; rxstate->error = RE_OKAY; rxstate->field_c = 0; /* set up here for the length that follows */ #ifdef DO_TRACE __rt_trace("rxe-type-%2x ", packet->type); #endif rxstate->crc = crc32(&new_ch, 1, rxstate->crc); return RS_IN_PKT; case RST_LEN: rxstate->crc = crc32(&new_ch, 1, rxstate->crc); if (rxstate->field_c++ == 0) { /* first length byte */ packet->len = ((unsigned int)new_ch) << 8; return RS_IN_PKT; } else { /* got the whole legth */ packet->len |= new_ch; #ifdef DO_TRACE __rt_trace("rxe-len-%4x\n", packet->len); #endif /* check that the length is ok */ if (packet->len == 0) { /* empty pkt */ rxstate->field_c = 0; rxstate->rx_state = RST_CRC; return RS_IN_PKT; } else { if (packet->data == NULL) { /* need to alloc the data buffer */ if (!rxstate->config->ba_callback( packet, rxstate->config->ba_data)) { rxstate->rx_state = RST_STX; rxstate->error = RE_INTERNAL; return RS_BAD_PKT; } } if (packet->len > packet->buf_len) { /* pkt bigger than buffer */ rxstate->field_c = 0; rxstate->rx_state = RST_STX; rxstate->error = RE_LEN; return RS_BAD_PKT; } else { /* packet ok */ rxstate->field_c = 0; rxstate->rx_state = RST_DAT; return RS_IN_PKT; } } } case RST_DAT: /* dummy case (dealt with earlier) */ #ifdef ASSERTIONS_ENABLED __rt_warning("ERROR: hit RST_dat in switch\n"); #endif rxstate->rx_state = RST_STX; rxstate->error = RE_INTERNAL; return RS_BAD_PKT; case RST_CRC: if (rxstate->field_c == 0) packet->crc = 0; packet->crc |= (new_ch & 0xFF) << ((3 - rxstate->field_c) * 8); rxstate->field_c++; if (rxstate->field_c == 4) { /* last crc field */ rxstate->field_c = 0; rxstate->rx_state = RST_ETX; #ifdef DO_TRACE __rt_trace("rxe-rcrc-%8x ", packet->crc); #endif } return RS_IN_PKT; case RST_ETX: if (new_ch == rxstate->config->etx) { #if defined(DEBUG) && !defined(NO_PKT_DATA) { int c; # ifdef DO_TRACE __rt_trace("\n"); # endif __rt_info("RXE Data ="); for (c=0; c < packet->len; c++) __rt_info("%02x", packet->data[c]); __rt_info("\n"); } #endif /* check crc */ if (rxstate->crc == packet->crc) { /* crc ok */ rxstate->rx_state = RST_STX; rxstate->field_c = 0; return RS_GOOD_PKT; } else { #ifdef ASSERTIONS_ENABLED __rt_warning("Bad crc, rx calculates it should be 0x%x\n", rxstate->crc); #endif rxstate->rx_state = RST_STX; rxstate->error = RE_CRC; return RS_BAD_PKT; } } else if (new_ch == rxstate->config->stx) return unexp_stx(rxstate); else { rxstate->rx_state = RST_STX; rxstate->error = RE_NETX; return RS_BAD_PKT; } default: #ifdef ASSERTIONS_ENABLED __rt_warning("ERROR fell through rxengine\n"); #endif rxstate->rx_state = RST_STX; rxstate->error = RE_INTERNAL; return RS_BAD_PKT; } }
/* * Function: Angel_MatchParams * Purpose: find a configuration from the requested options which is * the best match from the supported options. * * see params.h for details */ const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested, const ParameterOptions *supported ) { static Parameter chosen_params[AP_NUM_PARAMS]; static ParameterConfig chosen_config = { AP_NUM_PARAMS, chosen_params }; unsigned int i; ASSERT( requested != NULL, "requested is NULL" ); ASSERT( requested != NULL, "requested is NULL" ); ASSERT( supported->num_param_lists <= AP_NUM_PARAMS, "supp_num too big" ); if ( requested->num_param_lists > supported->num_param_lists ) { WARN( "req_num exceeds supp_num" ); return NULL; } for ( i = 0; i < requested->num_param_lists; ++i ) { bool match; unsigned int j; const ParameterList *req_list = &requested->param_list[i]; ADP_Parameter req_type = req_list->type; const ParameterList *sup_list = Angel_FindParamList( supported, req_type ); if ( sup_list == NULL ) { #ifdef ASSERTIONS_ENABLED __rt_warning( "option %x not supported\n", req_type ); #endif /* ASSERTIONS_ENABLED */ return NULL; } for ( j = 0, match = FALSE; (j < req_list->num_options) && !match; ++j ) { unsigned int k; for ( k = 0; (k < sup_list->num_options) && !match; ++k ) { if ( req_list->option[j] == sup_list->option[k] ) { #ifdef DEBUG __rt_info( "chose value %d for option %x\n", req_list->option[j], req_type ); #endif /* DEBUG */ match = TRUE; chosen_config.param[i].type = req_type; chosen_config.param[i].value = req_list->option[j]; } } } if ( !match ) { #ifdef ASSERTIONS_ENABLED __rt_warning( "no match found for option %x\n", req_type ); #endif /* ASSERTIONS_ENABLED */ return NULL; } } chosen_config.num_parameters = i; INFO( "match succeeded" ); return &chosen_config; }