diff options
author | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2008-05-13 21:08:09 +0000 |
---|---|---|
committer | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2008-05-13 21:08:09 +0000 |
commit | d7e54a785544ac40abc4a88383df3a913ca466e8 (patch) | |
tree | abf630c8372e7c81407172ad31190fa8a617a8ed /kernel/xpp/card_pri.c | |
parent | 823cf303caf13cc6e4fd2c2173804f0990b29532 (diff) |
xpp r5723: Includes, among others:
* New firmware protocol version: 3.0 .
* New numbers for the device types: (e.g. in card_init* scripts)
- FXS: 1 (was: 3)
- FXO: 2 (was: 4)
- BRI: 3 (was: 6 for TE, 7 for NT)
- PRI: 4 (was: 9)
* Init scripts of FXS and FXO modules are now written in Perl as well
(be sure to have File::Basename, e.g: perl-modules in Debian).
* calibrate_slics merged into init_card_1_30 .
* Module parameter print_dbg replaced with debug . Same meaning.
* init_fxo_modes removed: content moved into init_card_2_30, verified
at build time.
* Code tested with sparse. Most warnings were fixed.
* Set ZT_SIG_DACS for the bchans in the PRI and BRI modules to not get
ignored by ztscan.
* Handle null config_desc we get from some crazy USB controllers.
* genzaptelconf: Fix reporting of empty slots in list mode.
* xpp_blink can now blink a single analog port.
* "slics" has been renamed "chipregs".
* Fixed a small typo in fpga_load(8).
* Fixed bashism in xpp_fxloader.
Merged revisions 4264 via svnmerge from
http://svn.digium.com/svn/zaptel/branches/1.2
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4266 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'kernel/xpp/card_pri.c')
-rw-r--r-- | kernel/xpp/card_pri.c | 464 |
1 files changed, 130 insertions, 334 deletions
diff --git a/kernel/xpp/card_pri.c b/kernel/xpp/card_pri.c index 2187bb7..335b933 100644 --- a/kernel/xpp/card_pri.c +++ b/kernel/xpp/card_pri.c @@ -36,8 +36,8 @@ static const char rcsid[] = "$Id$"; -DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ -DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); +static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ +static DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); #define PRI_LINES_BITMASK BITMASK(31) #define PRI_DCHAN_SIGCAP ( \ @@ -50,11 +50,13 @@ DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in millise ZT_SIG_FXOGS | \ ZT_SIG_FXOKS | \ ZT_SIG_CAS | \ + ZT_SIG_DACS | \ ZT_SIG_SF \ ) -#define PRI_BCHAN_SIGCAP ZT_SIG_CLEAR +#define PRI_BCHAN_SIGCAP (ZT_SIG_CLEAR | ZT_SIG_DACS) #define MAX_SLAVES 4 /* we have MUX of 4 clocks */ +#define PRI_PORT(xpd) ((xpd)->addr.subunit) /*---------------- PRI Protocol Commands ----------------------------------*/ @@ -62,8 +64,6 @@ static bool pri_packet_is_valid(xpacket_t *pack); static void pri_packet_dump(const char *msg, xpacket_t *pack); static int proc_pri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); static int proc_pri_info_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); static int pri_startup(struct zt_span *span); static int pri_shutdown(struct zt_span *span); static int pri_lineconfig(xpd_t *xpd, int lineconfig); @@ -71,8 +71,6 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig); #define PROC_REGISTER_FNAME "slics" #define PROC_PRI_INFO_FNAME "pri_info" -#define VALID_CHIPSEL(x) ((x) == 0) - enum pri_protocol { PRI_PROTO_0 = 0, PRI_PROTO_E1 = 1, @@ -246,15 +244,12 @@ struct pri_leds { struct PRI_priv_data { bool is_nt; bool clock_source; - struct proc_dir_entry *regfile; struct proc_dir_entry *pri_info; enum pri_protocol pri_protocol; int deflaw; unsigned int dchan_num; bool initialized; bool local_loopback; - reg_cmd_t requested_reply; - reg_cmd_t last_reply; uint poll_noreplies; uint layer1_replies; byte reg_frs0; @@ -286,20 +281,21 @@ static /* 0x33 */ DECLARE_CMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum static int query_subunit(xpd_t *xpd, byte regnum) { -#if 0 - XPD_DBG(GENERAL, xpd, "(%d%d): REG=0x%02X\n", + XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X\n", xpd->addr.unit, xpd->addr.subunit, regnum); -#endif return xpp_register_request( xpd->xbus, xpd, - 0, /* chipsel */ - 0, /* writing */ - 1, /* do_subreg */ + PRI_PORT(xpd), /* portno */ + 0, /* writing */ regnum, - xpd->addr.subunit, /* subreg */ - 0, /* data_L */ - 0); /* data_H */ + 0, /* do_subreg */ + 0, /* subreg */ + 0, /* data_L */ + 0, /* do_datah */ + 0, /* data_H */ + 0 /* should_reply */ + ); } @@ -310,13 +306,16 @@ static int write_subunit(xpd_t *xpd, byte regnum, byte val) regnum, val); return xpp_register_request( xpd->xbus, xpd, - 0, /* chipsel */ - 1, /* writing */ - 1, /* do_subreg */ + PRI_PORT(xpd), /* portno */ + 1, /* writing */ regnum, - xpd->addr.subunit, /* subreg */ - val, /* data_L */ - 0); /* data_H */ + 0, /* do_subreg */ + 0, /* subreg */ + val, /* data_L */ + 0, /* do_datah */ + 0, /* data_H */ + 0 /* should_reply */ + ); } static int pri_write_reg(xpd_t *xpd, int regnum, byte val) @@ -326,35 +325,34 @@ static int pri_write_reg(xpd_t *xpd, int regnum, byte val) regnum, val); return xpp_register_request( xpd->xbus, xpd, - 0, /* chipsel */ - 1, /* writing */ - 0, /* do_subreg */ + PRI_PORT(xpd), /* portno */ + 1, /* writing */ regnum, - 0, /* subreg */ - val, /* data_L */ - 0); /* data_H */ + 0, /* do_subreg */ + 0, /* subreg */ + val, /* data_L */ + 0, /* do_datah */ + 0, /* data_H */ + 0 /* should_reply */ + ); } -static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) +static void pri_proc_remove(xbus_t *xbus, xpd_t *xpd) { - xpd_t *xpd = NULL; struct PRI_priv_data *priv; - int channels = min(31, CHANNELS_PERXPD); /* worst case */ - XBUS_DBG(GENERAL, xbus, "\n"); - xpd = xpd_alloc(sizeof(struct PRI_priv_data), proto_table, channels); - if(!xpd) - return NULL; + BUG_ON(!xpd); priv = xpd->priv; - xpd->revision = revision; - priv->pri_protocol = PRI_PROTO_0; /* Default, changes in set_pri_proto() */ - priv->deflaw = ZT_LAW_DEFAULT; /* Default, changes in set_pri_proto() */ - xpd->type_name = - type_name(priv->pri_protocol, 0); /* Default, changes in set_nt() */ - return xpd; + XPD_DBG(PROC, xpd, "\n"); +#ifdef CONFIG_PROC_FS + if(priv->pri_info) { + XPD_DBG(PROC, xpd, "Removing xpd PRI_INFO file\n"); + remove_proc_entry(PROC_PRI_INFO_FNAME, xpd->proc_xpd_dir); + } +#endif } -static void clean_proc(xbus_t *xbus, xpd_t *xpd) +static int pri_proc_create(xbus_t *xbus, xpd_t *xpd) { struct PRI_priv_data *priv; @@ -362,16 +360,21 @@ static void clean_proc(xbus_t *xbus, xpd_t *xpd) priv = xpd->priv; XPD_DBG(PROC, xpd, "\n"); #ifdef CONFIG_PROC_FS - if(priv->regfile) { - XPD_DBG(PROC, xpd, "Removing registers file\n"); - priv->regfile->data = NULL; - remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); - } - if(priv->pri_info) { - XPD_DBG(PROC, xpd, "Removing xpd PRI_INFO file\n"); - remove_proc_entry(PROC_PRI_INFO_FNAME, xpd->proc_xpd_dir); + XPD_DBG(PROC, xpd, "Creating PRI_INFO file\n"); + priv->pri_info = create_proc_entry(PROC_PRI_INFO_FNAME, 0644, xpd->proc_xpd_dir); + if(!priv->pri_info) { + XPD_ERR(xpd, "Failed to create proc '%s'\n", PROC_PRI_INFO_FNAME); + goto err; } + priv->pri_info->owner = THIS_MODULE; + priv->pri_info->write_proc = proc_pri_info_write; + priv->pri_info->read_proc = proc_pri_info_read; + priv->pri_info->data = xpd; #endif + return 0; +err: + pri_proc_remove(xbus, xpd); + return -EINVAL; } static bool valid_pri_modes(const xpd_t *xpd) @@ -588,10 +591,10 @@ static int set_master_mode(const char *msg, xpd_t *xpd) lim0 &= ~REG_LIM0_MAS; if(priv->pri_protocol == PRI_PROTO_E1) { - lim0 |= REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched on (100 Ohm || 300 Ohm = 75 Ohm) */ - xsp |= REG_XSP_E_EBP | REG_XSP_E_AXS | REG_XSP_E_XSIF; - } else if(priv->pri_protocol == PRI_PROTO_T1) { lim0 &= ~REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched off (100 Ohm, no internal 300 Ohm) */; + xsp |= REG_XSP_E_EBP | REG_XSP_E_AXS | REG_XSP_E_XSIF; + } else if(priv->pri_protocol == PRI_PROTO_T1) { + lim0 |= REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched on (100 Ohm || 300 Ohm = 75 Ohm) */ xsp |= REG_FMR5_T_XTM; } XPD_DBG(SIGNAL, xpd, "%s(%s): %s\n", __FUNCTION__, msg, (is_master_mode) ? "MASTER" : "SLAVE"); @@ -680,7 +683,7 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig) const char *crcstr = ""; byte fmr0 = 0; /* Dummy initilizations to */ byte fmr2 = 0; /* silense false gcc warnings */ - byte fmr4 = 0x0C; + byte fmr4 = 0; /* Dummy initilizations to */ unsigned int bad_bits; int i; @@ -716,11 +719,14 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig) } if(bad_bits) goto bad_lineconfig; - if(priv->pri_protocol == PRI_PROTO_E1) + if(priv->pri_protocol == PRI_PROTO_E1) { fmr2 = REG_FMR2_E_AXRA | REG_FMR2_E_ALMF; /* 0x03 */ - else if(priv->pri_protocol == PRI_PROTO_T1) + fmr4 = 0x9F; /* E1.XSW: All spare bits = 1*/ + } else if(priv->pri_protocol == PRI_PROTO_T1) { fmr2 = REG_FMR2_T_SSP | REG_FMR2_T_AXRA; /* 0x22 */ - else if(priv->pri_protocol == PRI_PROTO_J1) { + fmr4 = 0x0C; + } else if(priv->pri_protocol == PRI_PROTO_J1) { + fmr4 = 0x1C; XPD_ERR(xpd, "J1 unsupported yet\n"); return -ENOSYS; } @@ -819,49 +825,47 @@ static int pri_chanconfig(struct zt_chan *chan, int sigtype) return 0; } -static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) +static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, int subunits, bool to_phone) { + xpd_t *xpd = NULL; struct PRI_priv_data *priv; + int channels = min(31, CHANNELS_PERXPD); /* worst case */ int ret = 0; - xproto_table_t *proto_table; - BUG_ON(!xpd); - XPD_DBG(GENERAL, xpd, "\n"); - xpd->type = XPD_TYPE_PRI; - proto_table = &PROTO_TABLE(PRI); + XBUS_DBG(GENERAL, xbus, "\n"); + xpd = xpd_alloc(sizeof(struct PRI_priv_data), proto_table, channels); + if(!xpd) + return NULL; priv = xpd->priv; - xpd->xops = &proto_table->xops; -#ifdef CONFIG_PROC_FS - XPD_DBG(PROC, xpd, "Creating PRI_INFO file\n"); - priv->pri_info = create_proc_entry(PROC_PRI_INFO_FNAME, 0644, xpd->proc_xpd_dir); - if(!priv->pri_info) { - XPD_ERR(xpd, "Failed to create proc '%s'\n", PROC_PRI_INFO_FNAME); - ret = -ENOENT; + priv->pri_protocol = PRI_PROTO_0; /* Default, changes in set_pri_proto() */ + priv->deflaw = ZT_LAW_DEFAULT; /* Default, changes in set_pri_proto() */ + xpd->type_name = + type_name(priv->pri_protocol, 0); /* Default, changes in set_nt() */ + if(xpd_common_init(xbus, xpd, unit, subunit, subtype, subunits) < 0) goto err; - } - priv->pri_info->owner = THIS_MODULE; - priv->pri_info->write_proc = proc_pri_info_write; - priv->pri_info->read_proc = proc_pri_info_read; - priv->pri_info->data = xpd; - XPD_DBG(PROC, xpd, "Creating registers file\n"); - priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); - if(!priv->regfile) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); - ret = -ENOENT; + if(pri_proc_create(xbus, xpd) < 0) goto err; - } - priv->regfile->owner = THIS_MODULE; - priv->regfile->write_proc = proc_xpd_register_write; - priv->regfile->read_proc = proc_xpd_register_read; - priv->regfile->data = xpd; -#endif /* Assume E1, changes later from user space */ ret = set_pri_proto(xpd, PRI_PROTO_E1); if(ret < 0) goto err; - ret = run_initialize_registers(xpd); - if(ret < 0) - goto err; + return xpd; +err: + xpd_free(xpd); + return NULL; +} + +static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) +{ + struct PRI_priv_data *priv; + int ret = 0; + xproto_table_t *proto_table; + + BUG_ON(!xpd); + XPD_DBG(GENERAL, xpd, "\n"); + xpd->type = XPD_TYPE_PRI; + proto_table = &PROTO_TABLE(PRI); + priv = xpd->priv; /* * initialization script should have set correct * operating modes. @@ -870,7 +874,6 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) XPD_NOTICE(xpd, "PRI protocol not set\n"); goto err; } - XPD_DBG(GENERAL, xpd, "done\n"); for(ret = 0; ret < NUM_LEDS; ret++) { DO_LED(xpd, ret, PRI_LED_ON); msleep(20); @@ -879,7 +882,7 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) priv->initialized = 1; return 0; err: - clean_proc(xbus, xpd); + pri_proc_remove(xbus, xpd); XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); return ret; } @@ -891,7 +894,7 @@ static int PRI_card_remove(xbus_t *xbus, xpd_t *xpd) BUG_ON(!xpd); priv = xpd->priv; XPD_DBG(GENERAL, xpd, "\n"); - clean_proc(xbus, xpd); + pri_proc_remove(xbus, xpd); return 0; } @@ -1275,7 +1278,7 @@ static void PRI_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) } if(logical_chan == PRI_DCHAN_IDX(priv)) { if(priv->dchan_rx_sample != pcm[0]) { - if(print_dbg & DBG_PCM) { + if(debug & DBG_PCM) { XPD_INFO(xpd, "RX-D-Chan: prev=0x%X now=0x%X\n", priv->dchan_rx_sample, pcm[0]); dump_packet("RX-D-Chan", pack, 1); @@ -1307,19 +1310,7 @@ static /* 0x0F */ HOSTCMD(PRI, XPD_STATE, bool on) return 0; } -static /* 0x0F */ HOSTCMD(PRI, RING, lineno_t chan, bool on) -{ - XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); - return -ENOSYS; -} - -static /* 0x0F */ HOSTCMD(PRI, RELAY_OUT, byte which, bool on) -{ - XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); - return -ENOSYS; -} - -/* 0x33 */ HOSTCMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum pri_led_state to_led_state) +static /* 0x33 */ HOSTCMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum pri_led_state to_led_state) { int ret = 0; xframe_t *xframe; @@ -1336,6 +1327,7 @@ static /* 0x0F */ HOSTCMD(PRI, RELAY_OUT, byte which, bool on) pri_leds = &RPACKET_FIELD(pack, PRI, SET_LED, pri_leds); pri_leds->state = to_led_state; pri_leds->led_sel = led_sel; + pri_leds->reserved = 0; XPACKET_LEN(pack) = RPACKET_SIZE(PRI, SET_LED); ret = send_cmd_frame(xbus, xframe); priv->ledstate[led_sel] = to_led_state; @@ -1343,7 +1335,7 @@ static /* 0x0F */ HOSTCMD(PRI, RELAY_OUT, byte which, bool on) } /*---------------- PRI: Astribank Reply Handlers --------------------------*/ -static void layer1_state(xpd_t *xpd, byte subunit, byte data_low) +static void layer1_state(xpd_t *xpd, byte data_low) { struct PRI_priv_data *priv; int alarms = 0; @@ -1351,10 +1343,6 @@ static void layer1_state(xpd_t *xpd, byte subunit, byte data_low) BUG_ON(!xpd); priv = xpd->priv; BUG_ON(!priv); - if(xpd->addr.subunit != subunit) { - XPD_NOTICE(xpd, "layer1_state got wrong subunit=%d. Ignored.\n", subunit); - return; - } priv->poll_noreplies = 0; if(data_low & REG_FRS0_LOS) alarms |= ZT_ALARM_RED; @@ -1390,36 +1378,46 @@ static void layer1_state(xpd_t *xpd, byte subunit, byte data_low) } priv->reg_frs0 = data_low; priv->layer1_replies++; - XPD_DBG(REGS, xpd, "subunit=%d data_low=0x%02X\n", subunit, data_low); + XPD_DBG(REGS, xpd, "subunit=%d data_low=0x%02X\n", xpd->addr.subunit, data_low); } static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) { unsigned long flags; struct PRI_priv_data *priv; - + struct xpd_addr addr; + xpd_t *orig_xpd; + + /* Map UNIT + PORTNUM to XPD */ + orig_xpd = xpd; + addr.unit = orig_xpd->addr.unit; + addr.subunit = info->portnum; + xpd = xpd_byaddr(xbus, addr.unit, addr.subunit); + if(!xpd) { + static int rate_limit; + + if((rate_limit++ % 1003) < 5) + notify_bad_xpd(__FUNCTION__, xbus, addr , orig_xpd->xpdname); + return -EPROTO; + } spin_lock_irqsave(&xpd->lock, flags); priv = xpd->priv; BUG_ON(!priv); -#if 1 - if(print_dbg) - dump_reg_cmd("PRI", info, 0); -#endif - if(info->multibyte) { + if(info->is_multibyte) { XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n", info->bytes, info->eoframe); goto end; } - if(REG_FIELD(info, regnum) == REG_FRS0 && REG_FIELD(info, do_subreg)) - layer1_state(xpd, REG_FIELD(info, subreg), REG_FIELD(info, data_low)); - if(REG_FIELD(info, regnum) == REG_FRS1 && REG_FIELD(info, do_subreg)) + if(REG_FIELD(info, regnum) == REG_FRS0 && !REG_FIELD(info, do_subreg)) + layer1_state(xpd, REG_FIELD(info, data_low)); + if(REG_FIELD(info, regnum) == REG_FRS1 && !REG_FIELD(info, do_subreg)) priv->reg_frs1 = REG_FIELD(info, data_low); /* Update /proc info only if reply relate to the last slic read request */ if( - REG_FIELD(&priv->requested_reply, regnum) == REG_FIELD(info, regnum) && - REG_FIELD(&priv->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && - REG_FIELD(&priv->requested_reply, subreg) == REG_FIELD(info, subreg)) { - priv->last_reply = *info; + REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) && + REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && + REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) { + xpd->last_reply = *info; } end: @@ -1432,7 +1430,8 @@ static xproto_table_t PROTO_TABLE(PRI) = { .entries = { /* Table Card Opcode */ }, - .name = "PRI_xx", /* xpd->type_name is set in set_nt() */ + .name = "PRI", /* protocol name */ + .ports_per_subunit = 1, .type = XPD_TYPE_PRI, .xops = { .card_new = PRI_card_new, @@ -1448,8 +1447,6 @@ static xproto_table_t PROTO_TABLE(PRI) = { .card_close = PRI_card_close, .card_register_reply = PRI_card_register_reply, - .RING = XPROTO_CALLER(PRI, RING), - .RELAY_OUT = XPROTO_CALLER(PRI, RELAY_OUT), .XPD_STATE = XPROTO_CALLER(PRI, XPD_STATE), }, .packet_is_valid = pri_packet_is_valid, @@ -1610,208 +1607,7 @@ static int proc_pri_info_read(char *page, char **start, off_t off, int count, in return len; } -/* - * - * Direct/Indirect - * | - * | Reg# - * | | - * | | Data (only in Write) - * | | | - * | | +-+-+ - * v v v v - * FF WD 06 01 05 - * ^ ^ - * | | - * | Write/Read - * | - * Chan# - * - */ -static int handle_register_command(xpd_t *xpd, char *cmdline) -{ - unsigned chipsel; - unsigned data = 0; - unsigned xdata1 = 0; - unsigned xdata2 = 0; - char op; /* [W]rite, [R]ead */ - char reg_type; /* [D]irect, [S]ubregister */ - int reg_num; - int subreg; - int elements; - bool writing; - char *p; - reg_cmd_t regcmd; - xbus_t *xbus; - int ret = -EINVAL; - struct PRI_priv_data *priv; - byte buf[MAX_PROC_WRITE]; - - BUG_ON(!xpd); - xbus = xpd->xbus; - priv = xpd->priv; - BUG_ON(!priv); - if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ - *p = '\0'; - if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ - *p = '\0'; - for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ - ; - if(*p == '\0') - return 0; - if(!XBUS_GET(xbus)) { - XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); - return -EBUSY; - } - memset(buf, 0, MAX_PROC_WRITE); - elements = sscanf(cmdline, "%d %c%c %x %x %x %x %x", - &chipsel, - &op, ®_type, ®_num, - &subreg, - &data, &xdata1, &xdata2); - XPD_DBG(PROC, xpd, "'%s': %d %c%c %02X %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, subreg, data); - if(elements < 3) { // At least: chipsel, op, reg_type, reg_num - ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); - goto out; - } - if(!VALID_CHIPSEL(chipsel)) { - ERR("Bad chip select number: %d\n", chipsel); - goto out; - } - REG_FIELD(®cmd, chipsel) = chipsel; - switch(op) { - case 'W': - writing = 1; - break; - case 'R': - writing = 0; - break; - default: - ERR("Unkown operation type '%c'\n", op); - goto out; - } - if( - (op == 'W' && reg_type == 'D' && elements != 5) || - (op == 'W' && reg_type == 'S' && elements != 6) || - (op == 'R' && reg_type == 'D' && elements != 4) || - (op == 'R' && reg_type == 'S' && elements != 5) - ) { - ERR("Bad number of elements: '%s' (%d elements): %d %c%c %02X %02X %02X\n", - cmdline, elements, - chipsel, op, reg_type, reg_num, subreg, data); - goto out; - } - switch(reg_type) { - case 'S': - REG_FIELD(®cmd, do_subreg) = 1; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = subreg; - REG_FIELD(®cmd, data_low) = data; - XPD_DBG(PROC, xpd, "SUBREG\n"); - break; - case 'D': - REG_FIELD(®cmd, do_subreg) = 0; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = 0; - REG_FIELD(®cmd, data_low) = subreg; - XPD_DBG(PROC, xpd, "DIRECT\n"); - break; - default: - ERR("Unkown register type '%c'\n", reg_type); - goto out; - } - regcmd.bytes = sizeof(regcmd) - 1; - REG_FIELD(®cmd, read_request) = writing; - REG_FIELD(®cmd, data_high) = 0; - priv->requested_reply = regcmd; - if(print_dbg) - dump_reg_cmd("PRI", ®cmd, 1); - ret = xpp_register_request(xpd->xbus, xpd, - REG_FIELD(®cmd, chipsel), - writing, - REG_FIELD(®cmd, do_subreg), - REG_FIELD(®cmd, regnum), - REG_FIELD(®cmd, subreg), - REG_FIELD(®cmd, data_low), - REG_FIELD(®cmd, data_high)); -out: - XBUS_PUT(xbus); - return ret; -} - -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - char *p; - int i; - int ret; - - if(!xpd) - return -ENODEV; - for(i = 0; i < count; /* noop */) { - for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ - if(i >= count) - break; - if(get_user(*p, buffer + i)) - return -EFAULT; - i++; - if(*p == '\n' || *p == '\r') /* whatever */ - break; - } - if(p >= buf + MAX_PROC_WRITE) - return -E2BIG; - *p = '\0'; - ret = handle_register_command(xpd, buf); - if(ret < 0) - return ret; - msleep(1); - } - return count; -} - - -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - reg_cmd_t *info; - struct PRI_priv_data *priv; - - if(!xpd) - return -ENODEV; - priv = xpd->priv; - BUG_ON(!priv); - spin_lock_irqsave(&xpd->lock, flags); - info = &priv->last_reply; - len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); - len += sprintf(page + len, "# Consult firmware docs first\n"); - len += sprintf(page + len, "#\n"); - if(REG_FIELD(info, do_subreg)) { - len += sprintf(page + len, "#CH\tOP\tReg.\tSub\tDL\n"); - len += sprintf(page + len, "%2d\tRS\t%02X\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); - } else { - len += sprintf(page + len, "#CH\tOP\tReg.\tDL\n"); - len += sprintf(page + len, "%2d\tRD\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - REG_FIELD(info, regnum), REG_FIELD(info, data_low)); - } - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -int __init card_pri_startup(void) +static int __init card_pri_startup(void) { DBG(GENERAL, "\n"); @@ -1820,7 +1616,7 @@ int __init card_pri_startup(void) return 0; } -void __exit card_pri_cleanup(void) +static void __exit card_pri_cleanup(void) { DBG(GENERAL, "\n"); xproto_unregister(&PROTO_TABLE(PRI)); |