xpp: refactor struct reg_cmd

Currently we only have REG (register) commands. Refactor it to allow
MEM (memory) commands.

* A common header
* Don't assume a constant size.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
This commit is contained in:
Oron Peled 2015-11-16 15:42:21 -05:00 committed by Tzafrir Cohen
parent d9aa82b025
commit 1c68f2ec73
9 changed files with 60 additions and 52 deletions

View File

@ -467,8 +467,8 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
int ret = 0; int ret = 0;
src = REG_XDATA(regcmd); src = REG_XDATA(regcmd);
len = regcmd->bytes; len = regcmd->h.bytes;
eoframe = regcmd->eoframe; eoframe = regcmd->h.eoframe;
if (len <= 0) if (len <= 0)
return 0; return 0;
if (!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */ if (!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */
@ -566,10 +566,10 @@ static void fill_multibyte(xpd_t *xpd, xpacket_t *pack,
XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0); XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0);
XPACKET_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST); XPACKET_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
reg_cmd->bytes = len; reg_cmd->h.bytes = len;
reg_cmd->is_multibyte = 1; reg_cmd->h.is_multibyte = 1;
reg_cmd->portnum = xpd->addr.subunit; reg_cmd->h.portnum = xpd->addr.subunit;
reg_cmd->eoframe = eoframe; reg_cmd->h.eoframe = eoframe;
p = REG_XDATA(reg_cmd); p = REG_XDATA(reg_cmd);
memcpy(p, buf, len); memcpy(p, buf, len);
if (debug) if (debug)
@ -1537,7 +1537,7 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
/* Map UNIT + PORTNUM to XPD */ /* Map UNIT + PORTNUM to XPD */
orig_xpd = xpd; orig_xpd = xpd;
addr.unit = orig_xpd->addr.unit; addr.unit = orig_xpd->addr.unit;
addr.subunit = info->portnum; addr.subunit = info->h.portnum;
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit); xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
if (!xpd) { if (!xpd) {
static int rate_limit; static int rate_limit;
@ -1562,9 +1562,9 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n", XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n",
REG_FIELD(info, data_low)); REG_FIELD(info, data_low));
} }
if (info->is_multibyte) { if (info->h.is_multibyte) {
XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n", XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
info->bytes, info->eoframe); info->h.bytes, info->h.eoframe);
ret = rx_dchan(xpd, info); ret = rx_dchan(xpd, info);
if (ret < 0) { if (ret < 0) {
priv->dchan_rx_drops++; priv->dchan_rx_drops++;

View File

@ -112,7 +112,7 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
/* Map UNIT + PORTNUM to XPD */ /* Map UNIT + PORTNUM to XPD */
orig_xpd = xpd; orig_xpd = xpd;
addr.unit = orig_xpd->addr.unit; addr.unit = orig_xpd->addr.unit;
addr.subunit = info->portnum; addr.subunit = info->h.portnum;
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit); xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
if (!xpd) { if (!xpd) {
static int rate_limit; static int rate_limit;

View File

@ -1246,7 +1246,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
priv = xpd->priv; priv = xpd->priv;
BUG_ON(!priv); BUG_ON(!priv);
portno = info->portnum; portno = info->h.portnum;
switch (REG_FIELD(info, regnum)) { switch (REG_FIELD(info, regnum)) {
case REG_INTERRUPT_SRC: case REG_INTERRUPT_SRC:
got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno); got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno);
@ -1264,7 +1264,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
#endif #endif
} }
LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n", LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
((info->bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum), ((info->h.bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
REG_FIELD(info, data_low), REG_FIELD(info, data_high)); REG_FIELD(info, data_low), REG_FIELD(info, data_high));
/* Update /proc info only if reply relate to the last slic read request */ /* Update /proc info only if reply relate to the last slic read request */
if (REG_FIELD(&xpd->requested_reply, regnum) == if (REG_FIELD(&xpd->requested_reply, regnum) ==

View File

@ -1484,7 +1484,7 @@ static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
{ {
int i; int i;
bool offhook = (REG_FIELD(info, data_low) & 0x1) == 0; bool offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
xpp_line_t lines = BIT(info->portnum); xpp_line_t lines = BIT(info->h.portnum);
/* Sanity check */ /* Sanity check */
if (!PHONEDEV(xpd).digital_inputs) { if (!PHONEDEV(xpd).digital_inputs) {
@ -1593,7 +1593,7 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
if (!indirect && regnum == REG_DTMF_DECODE) { if (!indirect && regnum == REG_DTMF_DECODE) {
__u8 val = REG_FIELD(info, data_low); __u8 val = REG_FIELD(info, data_low);
process_dtmf(xpd, info->portnum, val); process_dtmf(xpd, info->h.portnum, val);
} }
#ifdef POLL_DIGITAL_INPUTS #ifdef POLL_DIGITAL_INPUTS
/* /*
@ -1604,7 +1604,7 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
#endif #endif
else if (!indirect && regnum == REG_LOOPCLOSURE) { /* OFFHOOK ? */ else if (!indirect && regnum == REG_LOOPCLOSURE) { /* OFFHOOK ? */
__u8 val = REG_FIELD(info, data_low); __u8 val = REG_FIELD(info, data_low);
xpp_line_t mask = BIT(info->portnum); xpp_line_t mask = BIT(info->h.portnum);
xpp_line_t offhook; xpp_line_t offhook;
/* /*
@ -1613,7 +1613,7 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
*/ */
if ((val & REG_LOOPCLOSURE_ZERO) == 0) { if ((val & REG_LOOPCLOSURE_ZERO) == 0) {
offhook = (val & REG_LOOPCLOSURE_LCR) ? mask : 0; offhook = (val & REG_LOOPCLOSURE_LCR) ? mask : 0;
LINE_DBG(SIGNAL, xpd, info->portnum, LINE_DBG(SIGNAL, xpd, info->h.portnum,
"REG_LOOPCLOSURE: dataL=0x%X " "REG_LOOPCLOSURE: dataL=0x%X "
"(offhook=0x%X mask=0x%X)\n", "(offhook=0x%X mask=0x%X)\n",
val, offhook, mask); val, offhook, mask);

View File

@ -58,10 +58,10 @@ static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
*/ */
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit); XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
reg_cmd->bytes = 0; reg_cmd->h.bytes = 0;
reg_cmd->is_multibyte = 1; reg_cmd->h.is_multibyte = 1;
reg_cmd->portnum = portno; reg_cmd->h.portnum = portno;
reg_cmd->eoframe = eoftx; reg_cmd->h.eoframe = eoftx;
PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx); PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
if (debug & DBG_REGS) if (debug & DBG_REGS)
dump_xframe(__func__, xbus, xframe, debug); dump_xframe(__func__, xbus, xframe, debug);
@ -380,16 +380,16 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
data_low, data_high); data_low, data_high);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
/* do not count the 'bytes' field */ /* do not count the 'bytes' field */
reg_cmd->bytes = sizeof(*reg_cmd) - 1; reg_cmd->h.bytes = REG_CMD_SIZE(REG);
reg_cmd->is_multibyte = 0; reg_cmd->h.is_multibyte = 0;
if (portno == PORT_BROADCAST) { if (portno == PORT_BROADCAST) {
reg_cmd->portnum = 0; reg_cmd->h.portnum = 0;
REG_FIELD(reg_cmd, all_ports_broadcast) = 1; REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
} else { } else {
reg_cmd->portnum = portno; reg_cmd->h.portnum = portno;
REG_FIELD(reg_cmd, all_ports_broadcast) = 0; REG_FIELD(reg_cmd, all_ports_broadcast) = 0;
} }
reg_cmd->eoframe = 0; reg_cmd->h.eoframe = 0;
REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */ REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1; REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1;
REG_FIELD(reg_cmd, do_subreg) = do_subreg; REG_FIELD(reg_cmd, do_subreg) = do_subreg;
@ -402,7 +402,7 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
xpd->requested_reply = *reg_cmd; xpd->requested_reply = *reg_cmd;
if (debug & DBG_REGS) { if (debug & DBG_REGS) {
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit, dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
reg_cmd->portnum, reg_cmd); reg_cmd->h.portnum, reg_cmd);
dump_packet("REG_REQ", pack, 1); dump_packet("REG_REQ", pack, 1);
} }
if (!xframe->usec_towait) { /* default processing time of SPI */ if (!xframe->usec_towait) { /* default processing time of SPI */
@ -591,7 +591,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
return -EPROTO; return -EPROTO;
} }
if (debug & DBG_REGS) { if (debug & DBG_REGS) {
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum, dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->h.portnum,
reg); reg);
dump_packet("REG_REPLY", pack, 1); dump_packet("REG_REPLY", pack, 1);
} }

View File

@ -2253,7 +2253,7 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
/* Map UNIT + PORTNUM to XPD */ /* Map UNIT + PORTNUM to XPD */
orig_xpd = xpd; orig_xpd = xpd;
addr.unit = orig_xpd->addr.unit; addr.unit = orig_xpd->addr.unit;
addr.subunit = info->portnum; addr.subunit = info->h.portnum;
regnum = REG_FIELD(info, regnum); regnum = REG_FIELD(info, regnum);
data_low = REG_FIELD(info, data_low); data_low = REG_FIELD(info, data_low);
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit); xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
@ -2267,9 +2267,9 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
spin_lock_irqsave(&xpd->lock, flags); spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv; priv = xpd->priv;
BUG_ON(!priv); BUG_ON(!priv);
if (info->is_multibyte) { if (info->h.is_multibyte) {
XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n", XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
info->bytes, info->eoframe); info->h.bytes, info->h.eoframe);
goto end; goto end;
} }
if (regnum == REG_FRS0 && !REG_FIELD(info, do_subreg)) if (regnum == REG_FRS0 && !REG_FIELD(info, do_subreg))

View File

@ -524,7 +524,7 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
(do_datah) ? "\tDH" : ""); (do_datah) ? "\tDH" : "");
len += len +=
sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n", sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
regs->portnum, REG_FIELD(regs, regnum), regs->h.portnum, REG_FIELD(regs, regnum),
REG_FIELD(regs, subreg), REG_FIELD(regs, data_low), REG_FIELD(regs, subreg), REG_FIELD(regs, data_low),
datah_str); datah_str);
} else { } else {
@ -532,7 +532,7 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n", sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
(do_datah) ? "\tDH" : ""); (do_datah) ? "\tDH" : "");
len += len +=
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->portnum, sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->h.portnum,
REG_FIELD(regs, regnum), REG_FIELD(regs, data_low), REG_FIELD(regs, regnum), REG_FIELD(regs, data_low),
datah_str); datah_str);
} }

View File

@ -381,17 +381,17 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
char data_buf[MAX_PROC_WRITE]; char data_buf[MAX_PROC_WRITE];
/* The size byte is not included */ /* The size byte is not included */
if (regcmd->bytes > sizeof(*regcmd) - 1) { if (regcmd->h.bytes > sizeof(*regcmd) - 1) {
PORT_NOTICE(xbus, unit, port, PORT_NOTICE(xbus, unit, port,
"%s: %s: Too long: regcmd->bytes = %d\n", __func__, "%s: %s: Too long: regcmd->bytes = %d\n", __func__,
msg, regcmd->bytes); msg, regcmd->h.bytes);
return; return;
} }
if (regcmd->is_multibyte) { if (regcmd->h.is_multibyte) {
char buf[MAX_PROC_WRITE + 1]; char buf[MAX_PROC_WRITE + 1];
int i; int i;
int n = 0; int n = 0;
size_t len = regcmd->bytes; size_t len = regcmd->h.bytes;
const __u8 *p = REG_XDATA(regcmd); const __u8 *p = REG_XDATA(regcmd);
buf[0] = '\0'; buf[0] = '\0';
@ -401,18 +401,18 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
PORT_DBG(REGS, xbus, unit, port, PORT_DBG(REGS, xbus, unit, port,
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) " "UNIT-%d PORT-%d: Multibyte(eoframe=%d) "
"%s[0..%zd]: %s%s\n", "%s[0..%zd]: %s%s\n",
unit, port, regcmd->eoframe, msg, len - 1, buf, unit, port, regcmd->h.eoframe, msg, len - 1, buf,
(n >= MAX_PROC_WRITE) ? "..." : ""); (n >= MAX_PROC_WRITE) ? "..." : "");
return; return;
} }
/* The size byte is not included */ /* The size byte is not included */
if (regcmd->bytes != sizeof(*regcmd) - 1) { if (regcmd->h.bytes != REG_CMD_SIZE(REG)) {
PORT_NOTICE(xbus, unit, port, PORT_NOTICE(xbus, unit, port,
"%s: %s: Wrong size: regcmd->bytes = %d\n", "%s: %s: Wrong size: regcmd->bytes = %d\n",
__func__, msg, regcmd->bytes); __func__, msg, regcmd->h.bytes);
return; return;
} }
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->portnum, snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum,
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : ""); (REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W'; action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
modifier = 'D'; modifier = 'D';

View File

@ -167,23 +167,30 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */ #define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
typedef struct reg_cmd { struct reg_cmd_header {
__u8 bytes:3; /* Length (for Multibyte) */ __u8 bytes:3; /* Length (for Multibyte) */
__u8 eoframe:1; /* For BRI -- end of frame */ __u8 eoframe:1; /* For BRI -- end of frame */
__u8 portnum:3; /* For port specific registers */ __u8 portnum:3; /* For port specific registers */
__u8 is_multibyte:1; __u8 is_multibyte:1;
} PACKED;
struct reg_cmd_REG {
__u8 reserved:3;
__u8 do_expander:1;
__u8 do_datah:1;
__u8 do_subreg:1;
__u8 read_request:1;
__u8 all_ports_broadcast:1;
__u8 regnum;
__u8 subreg;
__u8 data_low;
__u8 data_high;
} PACKED;
typedef struct reg_cmd {
struct reg_cmd_header h;
union { union {
struct { struct reg_cmd_REG r;
__u8 reserved:4;
__u8 do_datah:1;
__u8 do_subreg:1;
__u8 read_request:1;
__u8 all_ports_broadcast:1;
__u8 regnum;
__u8 subreg;
__u8 data_low;
__u8 data_high;
} PACKED r;
/* For Write-Multibyte commands in BRI */ /* For Write-Multibyte commands in BRI */
struct { struct {
__u8 xdata[MULTIBYTE_MAX_LEN]; __u8 xdata[MULTIBYTE_MAX_LEN];
@ -192,6 +199,7 @@ typedef struct reg_cmd {
} PACKED reg_cmd_t; } PACKED reg_cmd_t;
/* Shortcut access macros */ /* Shortcut access macros */
#define REG_CMD_SIZE(variant) (sizeof(struct reg_cmd_ ## variant))
#define REG_FIELD(regptr, member) ((regptr)->alt.r.member) #define REG_FIELD(regptr, member) ((regptr)->alt.r.member)
#define REG_XDATA(regptr) ((regptr)->alt.d.xdata) #define REG_XDATA(regptr) ((regptr)->alt.d.xdata)