⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 baycom_par.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* --------------------------------------------------------------------- */static void par96_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct device *dev = (struct device *)dev_id;	struct baycom_state *bc = (struct baycom_state *)dev->priv;	if (!dev || !bc || bc->hdrv.magic != HDLCDRV_MAGIC)		return;	baycom_int_freq(bc);	/*	 * check if transmitter active	 */	if (hdlcdrv_ptt(&bc->hdrv))		par96_tx(dev, bc);	else {		par96_rx(dev, bc);		if (--bc->modem.arb_divider <= 0) {			bc->modem.arb_divider = 6;			__sti();			hdlcdrv_arbitrate(dev, &bc->hdrv);		}	}	__sti();	hdlcdrv_transmitter(dev, &bc->hdrv);	hdlcdrv_receiver(dev, &bc->hdrv);        __cli();}/* --------------------------------------------------------------------- */static void par96_wakeup(void *handle){        struct device *dev = (struct device *)handle;	struct baycom_state *bc = (struct baycom_state *)dev->priv;	printk(KERN_DEBUG "baycom_par: %s: why am I being woken up?\n", dev->name);	if (!parport_claim(bc->pdev))		printk(KERN_DEBUG "baycom_par: %s: I'm broken.\n", dev->name);}/* --------------------------------------------------------------------- */static int par96_open(struct device *dev){	struct baycom_state *bc = (struct baycom_state *)dev->priv;	struct parport *pp = parport_enumerate();	if (!dev || !bc)		return -ENXIO;	while (pp && pp->base != dev->base_addr) 		pp = pp->next;	if (!pp) {		printk(KERN_ERR "baycom_par: parport at 0x%lx unknown\n", dev->base_addr);		return -ENXIO;	}	if (pp->irq < 0) {		printk(KERN_ERR "baycom_par: parport at 0x%lx has no irq\n", pp->base);		return -ENXIO;	}	memset(&bc->modem, 0, sizeof(bc->modem));	bc->hdrv.par.bitrate = 9600;	if (!(bc->pdev = parport_register_device(pp, dev->name, NULL, par96_wakeup, 						 par96_interrupt, PARPORT_DEV_EXCL, dev))) {		printk(KERN_ERR "baycom_par: cannot register parport at 0x%lx\n", pp->base);		return -ENXIO;	}	if (parport_claim(bc->pdev)) {		printk(KERN_ERR "baycom_par: parport at 0x%lx busy\n", pp->base);		parport_unregister_device(bc->pdev);		return -EBUSY;	}	dev->irq = pp->irq;	/* bc->pdev->port->ops->change_mode(bc->pdev->port, PARPORT_MODE_PCSPP);  not yet implemented */        bc->hdrv.par.bitrate = 9600;	/* switch off PTT */	outb(PAR96_PTT | PAR97_POWER, LPT_DATA(dev));	/*bc->pdev->port->ops->enable_irq(bc->pdev->port);  not yet implemented */        outb(LPT_IRQ_ENABLE, LPT_CONTROL(dev));		printk(KERN_INFO "%s: par96 at iobase 0x%lx irq %u options 0x%x\n",	       bc_drvname, dev->base_addr, dev->irq, bc->options);	MOD_INC_USE_COUNT;	return 0;}/* --------------------------------------------------------------------- */static int par96_close(struct device *dev){	struct baycom_state *bc = (struct baycom_state *)dev->priv;	if (!dev || !bc)		return -EINVAL;	/* disable interrupt */        outb(0, LPT_CONTROL(dev));	/*bc->pdev->port->ops->disable_irq(bc->pdev->port);  not yet implemented */	/* switch off PTT */	outb(PAR96_PTT | PAR97_POWER, LPT_DATA(dev));	parport_release(bc->pdev);	parport_unregister_device(bc->pdev);	printk(KERN_INFO "%s: close par96 at iobase 0x%lx irq %u\n",	       bc_drvname, dev->base_addr, dev->irq);	MOD_DEC_USE_COUNT;	return 0;}/* --------------------------------------------------------------------- *//* * ===================== hdlcdrv driver interface ========================= */static int baycom_ioctl(struct device *dev, struct ifreq *ifr,			struct hdlcdrv_ioctl *hi, int cmd);/* --------------------------------------------------------------------- */static struct hdlcdrv_ops par96_ops = {	bc_drvname,	bc_drvinfo,	par96_open,	par96_close,	baycom_ioctl};/* --------------------------------------------------------------------- */static int baycom_setmode(struct baycom_state *bc, const char *modestr){	if (!strncmp(modestr, "picpar", 6))		bc->options = 0;	else if (!strncmp(modestr, "par96", 5))		bc->options = BAYCOM_OPTIONS_SOFTDCD;	else		bc->options = !!strchr(modestr, '*');	return 0;}/* --------------------------------------------------------------------- */static int baycom_ioctl(struct device *dev, struct ifreq *ifr,			struct hdlcdrv_ioctl *hi, int cmd){	struct baycom_state *bc;	struct baycom_ioctl bi;	int cmd2;	if (!dev || !dev->priv ||	    ((struct baycom_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {		printk(KERN_ERR "bc_ioctl: invalid device struct\n");		return -EINVAL;	}	bc = (struct baycom_state *)dev->priv;	if (cmd != SIOCDEVPRIVATE)		return -ENOIOCTLCMD;	if (get_user(cmd2, (int *)ifr->ifr_data))		return -EFAULT;	switch (hi->cmd) {	default:		break;	case HDLCDRVCTL_GETMODE:		strcpy(hi->data.modename, bc->options ? "par96" : "picpar");		if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))			return -EFAULT;		return 0;	case HDLCDRVCTL_SETMODE:		if (dev->start || !suser())			return -EACCES;		hi->data.modename[sizeof(hi->data.modename)-1] = '\0';		return baycom_setmode(bc, hi->data.modename);	case HDLCDRVCTL_MODELIST:		strcpy(hi->data.modename, "par96,picpar");		if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))			return -EFAULT;		return 0;	case HDLCDRVCTL_MODEMPARMASK:		return HDLCDRV_PARMASK_IOBASE;	}	if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))		return -EFAULT;	switch (bi.cmd) {	default:		return -ENOIOCTLCMD;#ifdef BAYCOM_DEBUG	case BAYCOMCTL_GETDEBUG:		bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;		bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;		bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;		break;#endif /* BAYCOM_DEBUG */	}	if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))		return -EFAULT;	return 0;}/* --------------------------------------------------------------------- */__initfunc(int baycom_par_init(void)){	int i, j, found = 0;	char set_hw = 1;	struct baycom_state *bc;	char ifname[HDLCDRV_IFNAMELEN];	printk(bc_drvinfo);	/*	 * register net devices	 */	for (i = 0; i < NR_PORTS; i++) {		struct device *dev = baycom_device+i;		sprintf(ifname, "bcp%d", i);		if (!baycom_ports[i].mode)			set_hw = 0;		if (!set_hw)			baycom_ports[i].iobase = 0;		j = hdlcdrv_register_hdlcdrv(dev, &par96_ops,					     sizeof(struct baycom_state),					     ifname, baycom_ports[i].iobase, 0, 0);		if (!j) {			bc = (struct baycom_state *)dev->priv;			if (set_hw && baycom_setmode(bc, baycom_ports[i].mode))				set_hw = 0;			found++;		} else {			printk(KERN_WARNING "%s: cannot register net device\n",			       bc_drvname);		}	}	if (!found)		return -ENXIO;	return 0;}/* --------------------------------------------------------------------- */#ifdef MODULE/* * command line settable parameters */static const char *mode[NR_PORTS] = { "picpar", };static int iobase[NR_PORTS] = { 0x378, };#if LINUX_VERSION_CODE >= 0x20115MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s");MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar");MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i");MODULE_PARM_DESC(iobase, "baycom io base address");MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver");#endif__initfunc(int init_module(void)){	int i;	for (i = 0; (i < NR_PORTS) && (mode[i]); i++) {		baycom_ports[i].mode = mode[i];		baycom_ports[i].iobase = iobase[i];	}	if (i < NR_PORTS-1)		baycom_ports[i+1].mode = NULL;	return baycom_par_init();}/* --------------------------------------------------------------------- */void cleanup_module(void){	int i;	for(i = 0; i < NR_PORTS; i++) {		struct device *dev = baycom_device+i;		struct baycom_state *bc = (struct baycom_state *)dev->priv;		if (bc) {			if (bc->hdrv.magic != HDLCDRV_MAGIC)				printk(KERN_ERR "baycom: invalid magic in "				       "cleanup_module\n");			else				hdlcdrv_unregister_hdlcdrv(dev);		}	}}#else /* MODULE *//* --------------------------------------------------------------------- *//* * format: baycom_par=io,mode * mode: par96,picpar */__initfunc(void baycom_par_setup(char *str, int *ints)){	int i;	for (i = 0; (i < NR_PORTS) && (baycom_ports[i].mode); i++);	if ((i >= NR_PORTS) || (ints[0] < 1)) {		printk(KERN_INFO "%s: too many or invalid interface "		       "specifications\n", bc_drvname);		return;	}	baycom_ports[i].mode = str;	baycom_ports[i].iobase = ints[1];	if (i < NR_PORTS-1)		baycom_ports[i+1].mode = NULL;}#endif /* MODULE *//* --------------------------------------------------------------------- */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -