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:
parent
d9aa82b025
commit
1c68f2ec73
@ -467,8 +467,8 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
|
||||
int ret = 0;
|
||||
|
||||
src = REG_XDATA(regcmd);
|
||||
len = regcmd->bytes;
|
||||
eoframe = regcmd->eoframe;
|
||||
len = regcmd->h.bytes;
|
||||
eoframe = regcmd->h.eoframe;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
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_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->bytes = len;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = xpd->addr.subunit;
|
||||
reg_cmd->eoframe = eoframe;
|
||||
reg_cmd->h.bytes = len;
|
||||
reg_cmd->h.is_multibyte = 1;
|
||||
reg_cmd->h.portnum = xpd->addr.subunit;
|
||||
reg_cmd->h.eoframe = eoframe;
|
||||
p = REG_XDATA(reg_cmd);
|
||||
memcpy(p, buf, len);
|
||||
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 */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->portnum;
|
||||
addr.subunit = info->h.portnum;
|
||||
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
|
||||
if (!xpd) {
|
||||
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",
|
||||
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",
|
||||
info->bytes, info->eoframe);
|
||||
info->h.bytes, info->h.eoframe);
|
||||
ret = rx_dchan(xpd, info);
|
||||
if (ret < 0) {
|
||||
priv->dchan_rx_drops++;
|
||||
|
@ -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 */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->portnum;
|
||||
addr.subunit = info->h.portnum;
|
||||
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
|
||||
if (!xpd) {
|
||||
static int rate_limit;
|
||||
|
@ -1246,7 +1246,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
portno = info->portnum;
|
||||
portno = info->h.portnum;
|
||||
switch (REG_FIELD(info, regnum)) {
|
||||
case REG_INTERRUPT_SRC:
|
||||
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
|
||||
}
|
||||
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));
|
||||
/* Update /proc info only if reply relate to the last slic read request */
|
||||
if (REG_FIELD(&xpd->requested_reply, regnum) ==
|
||||
|
@ -1484,7 +1484,7 @@ static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
|
||||
{
|
||||
int i;
|
||||
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 */
|
||||
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) {
|
||||
__u8 val = REG_FIELD(info, data_low);
|
||||
|
||||
process_dtmf(xpd, info->portnum, val);
|
||||
process_dtmf(xpd, info->h.portnum, val);
|
||||
}
|
||||
#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
|
||||
else if (!indirect && regnum == REG_LOOPCLOSURE) { /* OFFHOOK ? */
|
||||
__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;
|
||||
|
||||
/*
|
||||
@ -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) {
|
||||
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 "
|
||||
"(offhook=0x%X mask=0x%X)\n",
|
||||
val, offhook, mask);
|
||||
|
@ -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);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->bytes = 0;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = portno;
|
||||
reg_cmd->eoframe = eoftx;
|
||||
reg_cmd->h.bytes = 0;
|
||||
reg_cmd->h.is_multibyte = 1;
|
||||
reg_cmd->h.portnum = portno;
|
||||
reg_cmd->h.eoframe = eoftx;
|
||||
PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
|
||||
if (debug & DBG_REGS)
|
||||
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);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
/* do not count the 'bytes' field */
|
||||
reg_cmd->bytes = sizeof(*reg_cmd) - 1;
|
||||
reg_cmd->is_multibyte = 0;
|
||||
reg_cmd->h.bytes = REG_CMD_SIZE(REG);
|
||||
reg_cmd->h.is_multibyte = 0;
|
||||
if (portno == PORT_BROADCAST) {
|
||||
reg_cmd->portnum = 0;
|
||||
reg_cmd->h.portnum = 0;
|
||||
REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
|
||||
} else {
|
||||
reg_cmd->portnum = portno;
|
||||
reg_cmd->h.portnum = portno;
|
||||
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, read_request) = (writing) ? 0 : 1;
|
||||
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;
|
||||
if (debug & DBG_REGS) {
|
||||
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);
|
||||
}
|
||||
if (!xframe->usec_towait) { /* default processing time of SPI */
|
||||
@ -591,7 +591,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
||||
return -EPROTO;
|
||||
}
|
||||
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);
|
||||
dump_packet("REG_REPLY", pack, 1);
|
||||
}
|
||||
|
@ -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 */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->portnum;
|
||||
addr.subunit = info->h.portnum;
|
||||
regnum = REG_FIELD(info, regnum);
|
||||
data_low = REG_FIELD(info, data_low);
|
||||
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);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
if (info->is_multibyte) {
|
||||
if (info->h.is_multibyte) {
|
||||
XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
|
||||
info->bytes, info->eoframe);
|
||||
info->h.bytes, info->h.eoframe);
|
||||
goto end;
|
||||
}
|
||||
if (regnum == REG_FRS0 && !REG_FIELD(info, do_subreg))
|
||||
|
@ -524,7 +524,7 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
||||
(do_datah) ? "\tDH" : "");
|
||||
len +=
|
||||
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),
|
||||
datah_str);
|
||||
} else {
|
||||
@ -532,7 +532,7 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
||||
sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
|
||||
(do_datah) ? "\tDH" : "");
|
||||
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),
|
||||
datah_str);
|
||||
}
|
||||
|
@ -381,17 +381,17 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
||||
char data_buf[MAX_PROC_WRITE];
|
||||
|
||||
/* The size byte is not included */
|
||||
if (regcmd->bytes > sizeof(*regcmd) - 1) {
|
||||
if (regcmd->h.bytes > sizeof(*regcmd) - 1) {
|
||||
PORT_NOTICE(xbus, unit, port,
|
||||
"%s: %s: Too long: regcmd->bytes = %d\n", __func__,
|
||||
msg, regcmd->bytes);
|
||||
msg, regcmd->h.bytes);
|
||||
return;
|
||||
}
|
||||
if (regcmd->is_multibyte) {
|
||||
if (regcmd->h.is_multibyte) {
|
||||
char buf[MAX_PROC_WRITE + 1];
|
||||
int i;
|
||||
int n = 0;
|
||||
size_t len = regcmd->bytes;
|
||||
size_t len = regcmd->h.bytes;
|
||||
const __u8 *p = REG_XDATA(regcmd);
|
||||
|
||||
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,
|
||||
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) "
|
||||
"%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) ? "..." : "");
|
||||
return;
|
||||
}
|
||||
/* 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,
|
||||
"%s: %s: Wrong size: regcmd->bytes = %d\n",
|
||||
__func__, msg, regcmd->bytes);
|
||||
__func__, msg, regcmd->h.bytes);
|
||||
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)) ? "*" : "");
|
||||
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
|
||||
modifier = 'D';
|
||||
|
@ -167,14 +167,16 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
|
||||
|
||||
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
|
||||
|
||||
typedef struct reg_cmd {
|
||||
struct reg_cmd_header {
|
||||
__u8 bytes:3; /* Length (for Multibyte) */
|
||||
__u8 eoframe:1; /* For BRI -- end of frame */
|
||||
__u8 portnum:3; /* For port specific registers */
|
||||
__u8 is_multibyte:1;
|
||||
union {
|
||||
struct {
|
||||
__u8 reserved:4;
|
||||
} PACKED;
|
||||
|
||||
struct reg_cmd_REG {
|
||||
__u8 reserved:3;
|
||||
__u8 do_expander:1;
|
||||
__u8 do_datah:1;
|
||||
__u8 do_subreg:1;
|
||||
__u8 read_request:1;
|
||||
@ -183,7 +185,12 @@ typedef struct reg_cmd {
|
||||
__u8 subreg;
|
||||
__u8 data_low;
|
||||
__u8 data_high;
|
||||
} PACKED r;
|
||||
} PACKED;
|
||||
|
||||
typedef struct reg_cmd {
|
||||
struct reg_cmd_header h;
|
||||
union {
|
||||
struct reg_cmd_REG r;
|
||||
/* For Write-Multibyte commands in BRI */
|
||||
struct {
|
||||
__u8 xdata[MULTIBYTE_MAX_LEN];
|
||||
@ -192,6 +199,7 @@ typedef struct reg_cmd {
|
||||
} PACKED reg_cmd_t;
|
||||
|
||||
/* Shortcut access macros */
|
||||
#define REG_CMD_SIZE(variant) (sizeof(struct reg_cmd_ ## variant))
|
||||
#define REG_FIELD(regptr, member) ((regptr)->alt.r.member)
|
||||
#define REG_XDATA(regptr) ((regptr)->alt.d.xdata)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user