diff options
Diffstat (limited to 'xpp/xproto.c')
-rw-r--r-- | xpp/xproto.c | 125 |
1 files changed, 75 insertions, 50 deletions
diff --git a/xpp/xproto.c b/xpp/xproto.c index ebd9bba..5b62494 100644 --- a/xpp/xproto.c +++ b/xpp/xproto.c @@ -31,7 +31,6 @@ static const char rcsid[] = "$Id$"; extern int print_dbg; -static int packet_process(xbus_t *xbus, int xpd_num, xpacket_t *pack); static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE]; @@ -56,6 +55,16 @@ void xpd_set_addr(xpd_addr_t *addr, int xpd_num) addr->subunit = (xpd_num >> UNIT_BITS) & BITMASK(SUBUNIT_BITS); } +xpd_t *xpd_by_addr(const xbus_t *xbus, int unit, int subunit) +{ + xpd_addr_t addr; + int xpd_num; + + addr.unit = unit; + addr.subunit = subunit; + xpd_num = xpd_addr2num(&addr); + return xpd_of(xbus, xpd_num); +} /*---------------- General Protocol Management ----------------------------*/ @@ -154,32 +163,7 @@ static const xproto_entry_t *find_xproto_entry(xpd_t *xpd, byte opcode) return xe; } -int packet_receive(xbus_t *xbus, xpacket_t *pack) -{ - int xpd_num; - - if(!valid_xpd_addr(&pack->content.addr)) { - static int rate_limit = 0; - - if((rate_limit++ % 5003) < 3) - dump_packet("bad address", pack, print_dbg); - xbus->ops->packet_free(xbus, pack); - return -EPROTO; - } - xpd_num = XPD_NUM(pack->content.addr); -#ifdef SOFT_SIMULATOR - if(xbus->sim[xpd_num].simulated) { - //dump_packet("packet_receive -> simulate", pack, print_dbg); - return simulate_xpd(xbus, xpd_num, pack); - } else -#endif - { - //dump_packet("packet_receive -> process", pack, print_dbg); - return packet_process(xbus, xpd_num, pack); - } -} - -static int packet_process(xbus_t *xbus, int xpd_num, xpacket_t *pack) +int packet_process(xbus_t *xbus, xpacket_t *pack) { byte op; const xproto_entry_t *xe; @@ -189,24 +173,35 @@ static int packet_process(xbus_t *xbus, int xpd_num, xpacket_t *pack) int ret = 0; BUG_ON(!pack); - op = pack->content.opcode; - xpd_num = XPD_NUM(pack->content.addr); - xpd = xpd_of(xbus, xpd_num); + if(!valid_xpd_addr(&pack->addr)) { + if(printk_ratelimit()) + dump_packet("packet_process -- bad address", pack, print_dbg); + ret = -EPROTO; + goto out; + } + op = pack->opcode; + xpd = xpd_by_addr(xbus, pack->addr.unit, pack->addr.subunit); + /* XPD may be NULL (e.g: during bus polling */ xe = find_xproto_entry(xpd, op); /*-------- Validations -----------*/ if(!xe) { - ERR("xpp: %s: %s unit #%d: bad command op=0x%02X\n", - __FUNCTION__, xbus->busname, xpd_num, op); - dump_packet("packet_process -- bad command", pack, print_dbg); + if(printk_ratelimit()) { + ERR("xpp: %s: %s/%d-%d: bad command op=0x%02X\n", + __FUNCTION__, xbus->busname, + pack->addr.unit, pack->addr.subunit, op); + dump_packet("packet_process -- bad command", pack, print_dbg); + } ret = -EPROTO; goto out; } table = xe->table; BUG_ON(!table); if(!table->packet_is_valid(pack)) { - ERR("xpp: %s: wrong size %d for op=0x%02X\n", + if(printk_ratelimit()) { + ERR("xpp: %s: wrong size %d for op=0x%02X\n", __FUNCTION__, pack->datalen, op); - dump_packet("packet_process -- wrong size", pack, print_dbg); + dump_packet("packet_process -- wrong size", pack, print_dbg); + } ret = -EPROTO; goto out; } @@ -215,7 +210,35 @@ static int packet_process(xbus_t *xbus, int xpd_num, xpacket_t *pack) XBUS_COUNTER(xbus, RX_BYTES) += pack->datalen; handler(xbus, xpd, xe, pack); out: - xbus->ops->packet_free(xbus, pack); + return ret; +} + +int xframe_receive(xbus_t *xbus, xframe_t *xframe) +{ + byte *p; + byte *xpacket_start; + byte *xframe_end; + int ret = 0; + static int rate_limit; + + if(print_dbg == 2 && ((rate_limit++ % 1003) == 0)) + dump_xframe("RCV_PCM", xbus, xframe); + p = xpacket_start = xframe->packets; + xframe_end = xpacket_start + XFRAME_LEN(xframe); + do { + xpacket_t *pack = (xpacket_t *)p; + int len = pack->datalen; + + p += len; + if(p > xframe_end) { + ERR("%s: Invalid packet length %d\n", __FUNCTION__, len); + ret = -EPROTO; + goto out; + } + packet_process(xbus, pack); + } while(p < xframe_end); +out: + xbus->ops->xframe_free(xbus, xframe); return ret; } @@ -224,41 +247,45 @@ out: void dump_packet(const char *msg, xpacket_t *packet, bool print_dbg) { - byte op = packet->content.opcode; - byte *addr = (byte *)&packet->content.addr; + byte op = packet->opcode; + byte *addr = (byte *)&packet->addr; if(!print_dbg) return; - DBG("%s: XPD=%1X-%1X (0x%X) OP=0x%02X LEN=%d\n", + DBG("%s: XPD=%1X-%1X (0x%X) OP=0x%02X LEN=%d", msg, - packet->content.addr.unit, - packet->content.addr.subunit, + packet->addr.unit, + packet->addr.subunit, *addr, op, (byte)packet->datalen); #if VERBOSE_DEBUG { int i; - byte *p = packet->content.data; + byte *p = (byte *)packet; + if (print_dbg) + printk(" BYTES: "); for(i = 0; i < packet->datalen; i++) { static int limiter = 0; - if(i >= sizeof(xpacket_raw_t)) { + if(i >= sizeof(xpacket_t)) { if(limiter < ERR_REPORT_LIMIT) { - ERR("%s: length overflow i=%d > sizeof(xpacket_raw_t)=%d\n", - __FUNCTION__, i+1, sizeof(xpacket_raw_t)); + ERR("%s: length overflow i=%d > sizeof(xpacket_t)=%d\n", + __FUNCTION__, i+1, sizeof(xpacket_t)); } else if(limiter == ERR_REPORT_LIMIT) { ERR("%s: error packet #%d... squelsh reports.\n", - __FUNCTION__, limiter); + __FUNCTION__, limiter); } limiter++; break; } - DBG(" %2d> %02X\n", i+1, p[i]); + if (print_dbg) + printk("%02X ", p[i]); } } #endif + printk("\n"); } void dump_reg_cmd(const char msg[], reg_cmd_t *regcmd) @@ -334,9 +361,7 @@ int xproto_register(const xproto_table_t *proto_table) CHECK_XOP(card_hooksig); // CHECK_XOP(card_ioctl); // optional method -- call after testing CHECK_XOP(SYNC_SOURCE); - CHECK_XOP(PCM_WRITE); CHECK_XOP(XPD_STATE); - CHECK_XOP(CHAN_CID); CHECK_XOP(RING); CHECK_XOP(RELAY_OUT); @@ -364,7 +389,7 @@ void xproto_unregister(const xproto_table_t *proto_table) EXPORT_SYMBOL(dump_packet); EXPORT_SYMBOL(dump_reg_cmd); -EXPORT_SYMBOL(packet_receive); +EXPORT_SYMBOL(xframe_receive); EXPORT_SYMBOL(valid_xpd_addr); EXPORT_SYMBOL(xpd_addr2num); EXPORT_SYMBOL(xpd_set_addr); |