int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 
static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 
int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	hdlc_device *hdlc = dev_to_hdlc(dev);	pc300dev_t *d = (pc300dev_t *) dev->priv;	pc300ch_t *chan = (pc300ch_t *) d->chan;	pc300_t *card = (pc300_t *) chan->card;	pc300conf_t conf_aux;	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;	int ch = chan->channel;	void __user *arg = ifr->ifr_data;	struct if_settings *settings = &ifr->ifr_settings;	void __iomem *scabase = card->hw.scabase;	if (!capable(CAP_NET_ADMIN))		return -EPERM;	switch (cmd) {		case SIOCGPC300CONF:#ifdef CONFIG_PC300_MLPPP			if (conf->proto != PC300_PROTO_MLPPP) {				conf->proto = hdlc->proto.id;			}#else			conf->proto = hdlc->proto.id;#endif			memcpy(&conf_aux.conf, conf, sizeof(pc300chconf_t));			memcpy(&conf_aux.hw, &card->hw, sizeof(pc300hw_t));			if (!arg || 				copy_to_user(arg, &conf_aux, sizeof(pc300conf_t))) 				return -EINVAL;			return 0;		case SIOCSPC300CONF:			if (!capable(CAP_NET_ADMIN))				return -EPERM;			if (!arg || 				copy_from_user(&conf_aux.conf, arg, sizeof(pc300chconf_t)))				return -EINVAL;			if (card->hw.cpld_id < 0x02 &&			    conf_aux.conf.fr_mode == PC300_FR_UNFRAMED) {				/* CPLD_ID < 0x02 doesn't support Unframed E1 */				return -EINVAL;			}#ifdef CONFIG_PC300_MLPPP			if (conf_aux.conf.proto == PC300_PROTO_MLPPP) {				if (conf->proto != PC300_PROTO_MLPPP) {					memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));					cpc_tty_init(d);	/* init TTY driver */				}			} else {				if (conf_aux.conf.proto == 0xffff) {					if (conf->proto == PC300_PROTO_MLPPP){ 						/* ifdown interface */						cpc_close(dev);					}				} else {					memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));					hdlc->proto.id = conf->proto;				}			}#else			memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));			hdlc->proto.id = conf->proto;#endif			return 0;		case SIOCGPC300STATUS:			cpc_sca_status(card, ch);			return 0;		case SIOCGPC300FALCSTATUS:			cpc_falc_status(card, ch);			return 0;		case SIOCGPC300UTILSTATS:			{				if (!arg) {	/* clear statistics */					memset(&hdlc->stats, 0, sizeof(struct net_device_stats));					if (card->hw.type == PC300_TE) {						memset(&chan->falc, 0, sizeof(falc_t));					}				} else {					pc300stats_t pc300stats;					memset(&pc300stats, 0, sizeof(pc300stats_t));					pc300stats.hw_type = card->hw.type;					pc300stats.line_on = card->chan[ch].d.line_on;					pc300stats.line_off = card->chan[ch].d.line_off;					memcpy(&pc300stats.gen_stats, &hdlc->stats,					       sizeof(struct net_device_stats));					if (card->hw.type == PC300_TE)						memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t));				    	if (copy_to_user(arg, &pc300stats, sizeof(pc300stats_t)))						return -EFAULT;				}				return 0;			}		case SIOCGPC300UTILSTATUS:			{				struct pc300status pc300status;				pc300status.hw_type = card->hw.type;				if (card->hw.type == PC300_TE) {					pc300status.te_status.sync = chan->falc.sync;					pc300status.te_status.red_alarm = chan->falc.red_alarm;					pc300status.te_status.blue_alarm = chan->falc.blue_alarm;					pc300status.te_status.loss_fa = chan->falc.loss_fa;					pc300status.te_status.yellow_alarm =chan->falc.yellow_alarm;					pc300status.te_status.loss_mfa = chan->falc.loss_mfa;					pc300status.te_status.prbs = chan->falc.prbs;				} else {					pc300status.gen_status.dcd =						!(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_DCD);					pc300status.gen_status.cts =						!(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_CTS);					pc300status.gen_status.rts =						!(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_RTS);					pc300status.gen_status.dtr =						!(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_DTR);					/* There is no DSR in HD64572 */				}				if (!arg				    || copy_to_user(arg, &pc300status, sizeof(pc300status_t)))						return -EINVAL;				return 0;			}		case SIOCSPC300TRACE:			/* Sets/resets a trace_flag for the respective device */			if (!arg || copy_from_user(&d->trace_on, arg,sizeof(unsigned char)))					return -EINVAL;			return 0;		case SIOCSPC300LOOPBACK:			{				struct pc300loopback pc300loop;				/* TE boards only */				if (card->hw.type != PC300_TE)					return -EINVAL;				if (!arg || 					copy_from_user(&pc300loop, arg, sizeof(pc300loopback_t)))						return -EINVAL;				switch (pc300loop.loop_type) {					case PC300LOCLOOP:	/* Turn the local loop on/off */						falc_local_loop(card, ch, pc300loop.loop_on);						return 0;					case PC300REMLOOP:	/* Turn the remote loop on/off */						falc_remote_loop(card, ch, pc300loop.loop_on);						return 0;					case PC300PAYLOADLOOP:	/* Turn the payload loop on/off */						falc_payload_loop(card, ch, pc300loop.loop_on);						return 0;					case PC300GENLOOPUP:	/* Generate loop UP */						if (pc300loop.loop_on) {							falc_generate_loop_up_code (card, ch);						} else {							turn_off_xlu(card, ch);						}						return 0;					case PC300GENLOOPDOWN:	/* Generate loop DOWN */						if (pc300loop.loop_on) {							falc_generate_loop_down_code (card, ch);						} else {							turn_off_xld(card, ch);						}						return 0;					default:						return -EINVAL;				}			}		case SIOCSPC300PATTERNTEST:			/* Turn the pattern test on/off and show the errors counter */			{				struct pc300patterntst pc300patrntst;				/* TE boards only */				if (card->hw.type != PC300_TE)					return -EINVAL;				if (card->hw.cpld_id < 0x02) {					/* CPLD_ID < 0x02 doesn't support pattern test */					return -EINVAL;				}				if (!arg || 					copy_from_user(&pc300patrntst,arg,sizeof(pc300patterntst_t)))						return -EINVAL;				if (pc300patrntst.patrntst_on == 2) {					if (chan->falc.prbs == 0) {						falc_pattern_test(card, ch, 1);					}					pc300patrntst.num_errors =						falc_pattern_test_error(card, ch);					if (!arg					    || copy_to_user(arg, &pc300patrntst,							    sizeof (pc300patterntst_t)))							return -EINVAL;				} else {					falc_pattern_test(card, ch, pc300patrntst.patrntst_on);				}				return 0;			}		case SIOCWANDEV:			switch (ifr->ifr_settings.type) {				case IF_GET_IFACE:				{					const size_t size = sizeof(sync_serial_settings);					ifr->ifr_settings.type = conf->media;					if (ifr->ifr_settings.size < size) {						/* data size wanted */						ifr->ifr_settings.size = size;						return -ENOBUFS;					}						if (copy_to_user(settings->ifs_ifsu.sync,							 &conf->phys_settings, size)) {						return -EFAULT;					}					return 0;				}				case IF_IFACE_V35:				case IF_IFACE_V24:				case IF_IFACE_X21:				{					const size_t size = sizeof(sync_serial_settings);					if (!capable(CAP_NET_ADMIN)) {						return -EPERM;					}					/* incorrect data len? */					if (ifr->ifr_settings.size != size) {						return -ENOBUFS;					}					if (copy_from_user(&conf->phys_settings, 							   settings->ifs_ifsu.sync, size)) {						return -EFAULT;					}					if (conf->phys_settings.loopback) {						cpc_writeb(card->hw.scabase + M_REG(MD2, ch),							cpc_readb(card->hw.scabase + M_REG(MD2, ch)) | 							MD2_LOOP_MIR);					}					conf->media = ifr->ifr_settings.type;					return 0;				}				case IF_IFACE_T1:				case IF_IFACE_E1:				{					const size_t te_size = sizeof(te1_settings);					const size_t size = sizeof(sync_serial_settings);					if (!capable(CAP_NET_ADMIN)) {						return -EPERM;					}					/* incorrect data len? */					if (ifr->ifr_settings.size != te_size) {						return -ENOBUFS;					}					if (copy_from_user(&conf->phys_settings, 							   settings->ifs_ifsu.te1, size)) {						return -EFAULT;					}/* Ignoring HDLC slot_map for a while */										if (conf->phys_settings.loopback) {						cpc_writeb(card->hw.scabase + M_REG(MD2, ch),							cpc_readb(card->hw.scabase + M_REG(MD2, ch)) | 							MD2_LOOP_MIR);					}					conf->media = ifr->ifr_settings.type;					return 0;				}				default:					return hdlc_ioctl(dev, ifr, cmd);			}		default:			return hdlc_ioctl(dev, ifr, cmd);	}}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/7665a08928f241247afe8c76865cdbe4ef5489bf/pc300_drv.c/buggy/drivers/net/wan/pc300_drv.c