diff options
author | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-07-12 22:49:13 +0000 |
---|---|---|
committer | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-07-12 22:49:13 +0000 |
commit | 5e3f82cf4b7a4788fc9e0a78782ad05988c4502c (patch) | |
tree | db449f3f67ff0991e55df5aca04ff1c6b9419981 /xpp/xproto.c | |
parent | eeb46da049ee996c180b0bbc716bcabdf1931e7e (diff) |
xpp driver r4371:
* Update to zaptel-1.2.18 and zaptel-1.4.3 (r4308 onward)
* Fix a critical race with zaptel synchronization (r4362)
* Added a /proc/xpp/cmds for statistics about command timing (r4360)
* Fix a digit mapping bug with hardware dtmf detection (r4357)
* In xpp/utils/Makefile add perl syntax checks to our scripts (r4337)
* Better USB data error checking (r4336)
* udev rules (xpp.rules) avoid false calls from wrong nodes (r4331)
* Improve hardware detection and reporting in lszaptel,
zaptel_hardware. zapconf is basically functional.
* Leds are blinked synchronously on all Astribanks now (r4262)
* Fix a BRI bug if OPTIMIZE_CHANMUTE was compiled into zaptel (r4258)
(This feature was not yet accepted into official zaptel)
* Removed compile warning about HZ != 1000 (r4218)
* Firmware updates.
* fpga_load now supports USB pathes without zeros (r4211)
* XPD numbers have changed to '<Unit><Subunit>' (r4196)
* Proper support for ZT_VMWI ioctl, if used in zaptel (r4092)
* Fix FXO power denial detection (r4054)
* FXO could accidentally go off-hook with some compilers (r4048)
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2732 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'xpp/xproto.c')
-rw-r--r-- | xpp/xproto.c | 199 |
1 files changed, 116 insertions, 83 deletions
diff --git a/xpp/xproto.c b/xpp/xproto.c index f965c10..02741e6 100644 --- a/xpp/xproto.c +++ b/xpp/xproto.c @@ -43,27 +43,10 @@ bool valid_xpd_addr(const xpd_addr_t *addr) return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0); } -int xpd_addr2num(const xpd_addr_t *addr) -{ - BUG_ON(!valid_xpd_addr(addr)); - return addr->unit | (addr->subunit << UNIT_BITS); -} - void xpd_set_addr(xpd_addr_t *addr, int xpd_num) { - addr->unit = xpd_num & BITMASK(UNIT_BITS); - 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); + addr->unit = XBUS_UNIT(xpd_num); + addr->subunit = XBUS_SUBUNIT(xpd_num); } /*---------------- General Protocol Management ----------------------------*/ @@ -142,25 +125,10 @@ xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode) return xe->handler; } -static const xproto_entry_t *find_xproto_entry(xpd_t *xpd, byte opcode) +void notify_bad_xpd(const char *funcname, xbus_t *xbus, const xpd_addr_t addr, const char *msg) { - const xproto_entry_t *xe; - - xe = xproto_global_entry(opcode); - // DBG("opcode=0x%X xe=%p\n", opcode, xe); - if(!xe) { - const xproto_table_t *xtable; - - if(!xpd) - return NULL; - xtable = xproto_table(xpd->type); - if(!xtable) - return NULL; - xe = xproto_card_entry(xtable, opcode); - if(!xe) - return NULL; - } - return xe; + NOTICE("%s: non-existing address %s(%1d%1d): %s\n", + funcname, xbus->busname, addr.unit, addr.subunit, msg); } int packet_process(xbus_t *xbus, xpacket_t *pack) @@ -170,41 +138,63 @@ int packet_process(xbus_t *xbus, xpacket_t *pack) xproto_handler_t handler; xproto_table_t *table; xpd_t *xpd; - int ret = 0; + int ret = -EPROTO; BUG_ON(!pack); 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 = xpd_byaddr(xbus, pack->addr.unit, pack->addr.subunit); /* XPD may be NULL (e.g: during bus polling */ - xe = find_xproto_entry(xpd, op); + xe = xproto_global_entry(op); /*-------- Validations -----------*/ if(!xe) { - 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); + const xproto_table_t *xtable; + + if(!xpd) { + if(printk_ratelimit()) { + NOTICE("%s: %s from %d%d opcode=0x%02X: no such global command.\n", + __FUNCTION__, xbus->busname, + pack->addr.unit, pack->addr.subunit, op); + dump_packet("packet_process -- no such global command", pack, 1); + } + goto out; + } + xtable = xproto_table(xpd->type); + if(!xtable) { + if(printk_ratelimit()) + ERR("%s: %s/%s: no protocol table (type=%d)\n", + __FUNCTION__, + xbus->busname, xpd->xpdname, + xpd->type); + goto out; + } + xe = xproto_card_entry(xtable, op); + if(!xe) { + if(printk_ratelimit()) { + NOTICE("%s: %s/%s: bad command (type=%d,opcode=0x%x)\n", + __FUNCTION__, + xbus->busname, xpd->xpdname, + xpd->type, op); + dump_packet("packet_process -- bad command", pack, 1); + } + goto out; } - ret = -EPROTO; - goto out; } table = xe->table; BUG_ON(!table); if(!table->packet_is_valid(pack)) { if(printk_ratelimit()) { - ERR("xpp: %s: wrong size %d for op=0x%02X\n", + ERR("xpp: %s: wrong size %d for opcode=0x%02X\n", __FUNCTION__, pack->datalen, op); dump_packet("packet_process -- wrong size", pack, print_dbg); } - ret = -EPROTO; goto out; } + ret = 0; /* All well */ handler = xe->handler; BUG_ON(!handler); XBUS_COUNTER(xbus, RX_BYTES) += pack->datalen; @@ -215,33 +205,69 @@ out: 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); + byte *p; + byte *xpacket_start; + byte *xframe_end; + int ret = 0; + xpacket_t *pack; + int len; + bool is_pcm; + p = xpacket_start = xframe->packets; xframe_end = xpacket_start + XFRAME_LEN(xframe); - do { - xpacket_t *pack = (xpacket_t *)p; - int len = pack->datalen; + if(XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) { + static int rate_limit; + if((rate_limit++ % 1003) == 0) { + NOTICE("%s: short xframe\n", xbus->busname); + dump_xframe("short xframe", xbus, xframe); + } + goto bad_proto; + } + /* + * We want to check that xframes do not mix PCM and other commands + */ + is_pcm = ((xpacket_t *)p)->opcode == XPROTO_NAME(GLOBAL,PCM_READ); + if(print_dbg & DBG_PCM) { + static int rate_limit; + + if(is_pcm && ((rate_limit++ % 1003) == 0)) + dump_xframe("RX_XFRAME_PCM", xbus, xframe); + } + do { + pack = (xpacket_t *)p; + len = pack->datalen; + /* Sanity checks */ + if(unlikely(is_pcm && pack->opcode != XPROTO_NAME(GLOBAL,PCM_READ) && printk_ratelimit())) { + NOTICE("%s: Non-PCM packet within a PCM xframe\n", xbus->busname); + dump_xframe("In PCM xframe", xbus, xframe); + // goto bad_proto; + } else if(unlikely(!is_pcm && pack->opcode == XPROTO_NAME(GLOBAL,PCM_READ) && printk_ratelimit())) { + NOTICE("%s: A PCM packet within a Non-PCM xframe\n", xbus->busname); + // goto bad_proto; + } p += len; - if(p > xframe_end) { - ERR("%s: Invalid packet length %d\n", __FUNCTION__, len); - ret = -EPROTO; - goto out; + if(p > xframe_end || len < RPACKET_HEADERSIZE) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) { + NOTICE("%s: Invalid packet length %d\n", xbus->busname, len); + dump_xframe("BAD LENGTH", xbus, xframe); + } + goto bad_proto; } ret = packet_process(xbus, pack); if(unlikely(ret < 0)) goto out; } while(p < xframe_end); + if(is_pcm) + XBUS_COUNTER(xbus, RX_XFRAME_PCM)++; out: xbus->ops->xframe_free(xbus, xframe); return ret; +bad_proto: + ret = -EPROTO; + goto out; } #define VERBOSE_DEBUG 1 @@ -290,34 +316,39 @@ void dump_packet(const char *msg, xpacket_t *packet, bool print_dbg) printk("\n"); } -void dump_reg_cmd(const char msg[], reg_cmd_t *regcmd) +void dump_reg_cmd(const char msg[], const reg_cmd_t *regcmd, bool writing) { char action; - char mode; byte chipsel; - byte regnum; - byte data_low; - byte data_high; if(regcmd->bytes != sizeof(*regcmd) - 1) { /* The size byte is not included */ NOTICE("%s: Wrong size: regcmd->bytes = %d\n", __FUNCTION__, regcmd->bytes); return; } - action = (REG_FIELD(regcmd, chipsel) & 0x80) ? 'R' : 'W'; + if(writing && (REG_FIELD(regcmd, chipsel) & 0x80)) + ERR("Sending register command with reading bit ON\n"); + action = (writing) ? 'W' : 'R'; chipsel = REG_FIELD(regcmd, chipsel) & ~0x80; - if(REG_FIELD(regcmd, regnum) == 0x1E) { - mode = 'I'; - regnum = REG_FIELD(regcmd, subreg); - data_low = REG_FIELD(regcmd, data_low); - data_high = REG_FIELD(regcmd, data_high); + if(REG_FIELD(regcmd, do_subreg)) { + DBG("%s: %d %cS %02X %02X [%02X] # data_high=%X m=%d eof=%d\n", msg, chipsel, action, + REG_FIELD(regcmd, regnum), + REG_FIELD(regcmd, subreg), + REG_FIELD(regcmd, data_low), + REG_FIELD(regcmd, data_high), + regcmd->multibyte, regcmd->eoframe); + } else if(REG_FIELD(regcmd, regnum) == 0x1E) { + DBG("%s: %d %cI %02X [%02X %02X] # m=%d eof=%d\n", msg, chipsel, action, + REG_FIELD(regcmd, subreg), + REG_FIELD(regcmd, data_low), + REG_FIELD(regcmd, data_high), + regcmd->multibyte, regcmd->eoframe); } else { - mode = 'D'; - regnum = REG_FIELD(regcmd, regnum); - data_low = REG_FIELD(regcmd, data_low); - data_high = 0; + DBG("%s: %d %cD %02X [%02X] # data_high=%X m=%d eof=%d\n", msg, chipsel, action, + REG_FIELD(regcmd, regnum), + REG_FIELD(regcmd, data_low), + REG_FIELD(regcmd, data_high), + regcmd->multibyte, regcmd->eoframe); } - DBG("%d %c%c %02X %02X %02X # m=%d eof=%d\n", chipsel, action, mode, regnum, - data_low, data_high, regcmd->multibyte, regcmd->eoframe); } const char *xproto_name(xpd_type_t xpd_type) @@ -358,6 +389,8 @@ int xproto_register(const xproto_table_t *proto_table) CHECK_XOP(card_init); CHECK_XOP(card_remove); CHECK_XOP(card_tick); + CHECK_XOP(card_pcm_fromspan); + CHECK_XOP(card_pcm_tospan); CHECK_XOP(card_zaptel_preregistration); CHECK_XOP(card_zaptel_postregistration); CHECK_XOP(card_hooksig); @@ -391,8 +424,8 @@ void xproto_unregister(const xproto_table_t *proto_table) EXPORT_SYMBOL(dump_packet); EXPORT_SYMBOL(dump_reg_cmd); EXPORT_SYMBOL(xframe_receive); +EXPORT_SYMBOL(notify_bad_xpd); EXPORT_SYMBOL(valid_xpd_addr); -EXPORT_SYMBOL(xpd_addr2num); EXPORT_SYMBOL(xpd_set_addr); EXPORT_SYMBOL(xproto_global_entry); EXPORT_SYMBOL(xproto_card_entry); |