xpp: support for RAM type register commands

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 2dd077cc53
commit 14d9a53162
6 changed files with 176 additions and 3 deletions

View File

@ -81,6 +81,9 @@ enum fxs_leds {
#define SLIC_INDIRECT_REQUEST(xbus, xpd, port, writing, reg, dL, dH) \
xpp_register_request((xbus), (xpd), (port), \
(writing), 0x1E, 1, (reg), (dL), 1, (dH), 0)
#define RAM_REQUEST(xbus, xpd, port, writing, addr, data) \
xpp_ram_request((xbus), (xpd), (port), \
(writing), (__u8)(addr), (__u8)((addr) >> 8), (__u8)(data), (__u8)((data) >> 8), (__u8)((data) >> 16), (__u8)((data) >> 24), 0)
#define VALID_PORT(port) \
(((port) >= 0 && (port) <= 7) || (port) == PORT_BROADCAST)
@ -1595,7 +1598,24 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
(indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low),
REG_FIELD(info, data_high));
}
if (!indirect && regnum == REG_TYPE1_DTMF_DECODE) {
if (info->h.bytes == REG_CMD_SIZE(RAM)) {
uint addr;
unsigned long val;
XPD_INFO(xpd, "RAM reply is not fully implemented(%s)\n", __func__);
XPD_DBG(REGS, xpd, "port=%d, addr_low=0x%X, addr_high=0x%X, data_0=0x%X data_1=0x%X data_2=0x%X data_3=0x%X\n",
info->h.portnum,
REG_FIELD_RAM(info, addr_low),
REG_FIELD_RAM(info, addr_high),
REG_FIELD_RAM(info, data_0),
REG_FIELD_RAM(info, data_1),
REG_FIELD_RAM(info, data_2),
REG_FIELD_RAM(info, data_3));
addr = (REG_FIELD_RAM(info, addr_high) << 8) | REG_FIELD_RAM(info, addr_low);
val = (REG_FIELD_RAM(info, data_3) << 24) |
(REG_FIELD_RAM(info, data_2) << 16) |
(REG_FIELD_RAM(info, data_1) << 8) |
REG_FIELD_RAM(info, data_0);
} else if (!indirect && regnum == REG_TYPE1_DTMF_DECODE) {
__u8 val = REG_FIELD(info, data_low);
process_dtmf(xpd, info->h.portnum, val);

View File

@ -90,7 +90,7 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
int portno;
bool writing;
int op; /* [W]rite, [R]ead */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti, [R]AM */
bool do_subreg = 0;
int regnum;
int subreg;
@ -169,6 +169,16 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
num_args--; /* No data low */
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
break;
case 'R':
switch (op) {
case 'W':
num_args += 5; /* add: addr_high, data_[0-3] */
break;
case 'R':
num_args += 2; /* add: addr_low, addr_high */
break;
}
break;
default:
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
goto out;
@ -197,6 +207,31 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
addr_mode == 'm');
goto out;
}
if (addr_mode == 'R') {
__u8 input[6];
int i;
if (num_args - 2 > 6) {
XPD_ERR(xpd, "Too many args (%d) -- should be less than 6\n", num_args - 2);
goto out;
}
for (i = 0; i < num_args - 2; i++, argno++) {
input[i] = parse_hexbyte(argv[argno]);
if (input[i] < 0) {
XPD_ERR(xpd, "Illegal input[%d] number '%s'\n", i, argv[argno]);
goto out;
}
}
ret = xpp_ram_request(xpd->xbus, xpd, portno, writing,
input[0],
input[1],
input[2],
input[3],
input[4],
input[5],
1);
goto out;
}
/* Normal (non-Magic) register commands */
do_datah = 0;
if (argno >= argc) {
@ -415,6 +450,67 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
}
EXPORT_SYMBOL(xpp_register_request);
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing,
__u8 addr_low,
__u8 addr_high,
__u8 data_0,
__u8 data_1,
__u8 data_2,
__u8 data_3,
bool should_reply)
{
int ret = 0;
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
if (!xbus) {
DBG(REGS, "NO XBUS\n");
return -EINVAL;
}
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, RAM, xpd->xbus_idx);
LINE_DBG(REGS, xpd, portno, "%cR %02X %02X %02X %02X %02X %02X\n",
(writing) ? 'W' : 'R',
addr_low, addr_high,
data_0, data_1, data_2, data_3);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
/* do not count the 'bytes' field */
reg_cmd->h.bytes = REG_CMD_SIZE(RAM);
reg_cmd->h.is_multibyte = 0;
if (portno == PORT_BROADCAST) {
reg_cmd->h.portnum = 0;
REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 1;
} else {
reg_cmd->h.portnum = portno;
REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 0;
}
reg_cmd->h.eoframe = 0;
REG_FIELD_RAM(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
REG_FIELD_RAM(reg_cmd, read_request) = (writing) ? 0 : 1;
REG_FIELD_RAM(reg_cmd, do_datah) = 1;
REG_FIELD_RAM(reg_cmd, do_subreg) = 1;
REG_FIELD_RAM(reg_cmd, addr_low) = addr_low;
REG_FIELD_RAM(reg_cmd, addr_high) = addr_high;
REG_FIELD_RAM(reg_cmd, data_0) = data_0;
REG_FIELD_RAM(reg_cmd, data_1) = data_1;
REG_FIELD_RAM(reg_cmd, data_2) = data_2;
REG_FIELD_RAM(reg_cmd, data_3) = data_3;
if (should_reply)
xpd->requested_reply = *reg_cmd;
if (debug & DBG_REGS) {
dump_reg_cmd("REG_RAM", 1, xbus, xpd->addr.unit,
reg_cmd->h.portnum, reg_cmd);
dump_packet("REG_RAM", pack, 1);
}
if (!xframe->usec_towait) { /* default processing time of SPI */
xframe->usec_towait = 1000;
}
ret = send_cmd_frame(xbus, xframe);
return ret;
}
EXPORT_SYMBOL(xpp_ram_request);
/*
* The XPD parameter is totaly ignored by the driver and firmware as well.
*/
@ -594,6 +690,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
}
switch (reg->h.bytes) {
case REG_CMD_SIZE(REG):
case REG_CMD_SIZE(RAM):
return CALL_XMETHOD(card_register_reply, xpd, reg);
}
XPD_ERR(xpd, "REGISTER_REPLY: bad packet_len=%d\n", pack->head.packet_len);

View File

@ -77,6 +77,15 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool should_reply);
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
bool eoftx, __u8 *buf, unsigned len);
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing,
__u8 addr_low,
__u8 addr_high,
__u8 data_0,
__u8 data_1,
__u8 data_2,
__u8 data_3,
bool should_reply);
extern xproto_table_t PROTO_TABLE(GLOBAL);
int run_initialize_registers(xpd_t *xpd);
int parse_chip_command(xpd_t *xpd, char *cmdline);

View File

@ -518,7 +518,19 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
REG_FIELD(regs, data_high));
} else
datah_str[0] = '\0';
if (REG_FIELD(regs, do_subreg)) {
if (regs->h.bytes == REG_CMD_SIZE(RAM)) {
len +=
sprintf(buf + len, "#CH\tOP\tAL\tAH\tD0\tD1\tD2\tD3\n");
len +=
sprintf(buf + len, "%2d\tRR\t%02X\t%02X\t%02X\t%02X\t%02X\t%02X\n",
regs->h.portnum,
REG_FIELD_RAM(regs, addr_low),
REG_FIELD_RAM(regs, addr_high),
REG_FIELD_RAM(regs, data_0),
REG_FIELD_RAM(regs, data_1),
REG_FIELD_RAM(regs, data_2),
REG_FIELD_RAM(regs, data_3));
} else if (REG_FIELD(regs, do_subreg)) {
len +=
sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
(do_datah) ? "\tDH" : "");

View File

@ -387,6 +387,25 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
msg, regcmd->h.bytes);
return;
}
if (regcmd->h.bytes == REG_CMD_SIZE(RAM)) {
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum,
(REG_FIELD_RAM(regcmd, all_ports_broadcast)) ? "*" : "");
if (REG_FIELD_RAM(regcmd, read_request)) {
action = 'R';
} else {
action = 'W';
}
PORT_DBG(REGS, xbus, unit, port,
"%s: %s %cR %02X %02X %02X %02X %02X %02X\n",
msg, port_buf, action,
REG_FIELD_RAM(regcmd, addr_low),
REG_FIELD_RAM(regcmd, addr_high),
REG_FIELD_RAM(regcmd, data_0),
REG_FIELD_RAM(regcmd, data_1),
REG_FIELD_RAM(regcmd, data_2),
REG_FIELD_RAM(regcmd, data_3));
return;
}
if (regcmd->h.is_multibyte) {
char buf[MAX_PROC_WRITE + 1];
int i;

View File

@ -188,6 +188,20 @@ struct reg_cmd_REG {
__u8 data_high;
} PACKED;
struct reg_cmd_RAM {
__u8 reserved:4;
__u8 do_datah:1;
__u8 do_subreg:1;
__u8 read_request:1;
__u8 all_ports_broadcast:1;
__u8 addr_low;
__u8 addr_high;
__u8 data_0;
__u8 data_1;
__u8 data_2;
__u8 data_3;
} PACKED;
typedef struct reg_cmd {
struct reg_cmd_header h;
union {
@ -196,6 +210,7 @@ typedef struct reg_cmd {
struct {
__u8 xdata[MULTIBYTE_MAX_LEN];
} PACKED d;
struct reg_cmd_RAM m;
} PACKED alt;
} PACKED reg_cmd_t;
@ -203,6 +218,7 @@ typedef struct reg_cmd {
#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)
#define REG_FIELD_RAM(regptr, member) ((regptr)->alt.m.member)
#ifdef __KERNEL__