xpp: support for RAM type register commands
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
This commit is contained in:
parent
2dd077cc53
commit
14d9a53162
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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" : "");
|
||||
|
@ -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;
|
||||
|
@ -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__
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user