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

📄 baycom_epp.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
                goto stuff##j;                                                \  enditer##j:                                                                 \})#define DECODEITERB(j)                                                                 \({                                                                                     \  flgabrt##j:                                                                          \        if (!(notbitstream & (0x1fc << j))) {              /* abort received */        \                state = 0;                                                             \                goto enditer##j;                                                       \        }                                                                              \        if ((bitstream & (0x1fe << j)) != (0x0fc << j))   /* flag received */          \                goto enditer##j;                                                       \        if (state)                                                                     \                do_rxpacket(dev);                                                      \        bc->hdlcrx.bufcnt = 0;                                                         \        bc->hdlcrx.bufptr = bc->hdlcrx.buf;                                            \        state = 1;                                                                     \        numbits = 7-j;                                                                 \        goto enditer##j;                                                               \  stuff##j:                                                                            \        numbits--;                                                                     \        bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1);        \        goto enditer##j;                                                               \})        static void receive(struct device *dev, int cnt){	struct baycom_state *bc = (struct baycom_state *)dev->priv;	struct parport *pp = bc->pdev->port;        unsigned int bitbuf, notbitstream, bitstream, numbits, state;        unsigned char ch;                numbits = bc->hdlcrx.numbits;	state = bc->hdlcrx.state;	bitstream = bc->hdlcrx.bitstream;	bitbuf = bc->hdlcrx.bitbuf;	for (; cnt > 0; cnt--) {		ch = parport_epp_read_data(pp);		bitstream >>= 8;                bitstream |= ch << 8;                bitbuf >>= 8;                bitbuf |= ch << 8;                numbits += 8;                notbitstream = ~bitstream;                DECODEITERA(0);                DECODEITERA(1);                DECODEITERA(2);                DECODEITERA(3);                DECODEITERA(4);                DECODEITERA(5);                DECODEITERA(6);                DECODEITERA(7);                goto enddec;                DECODEITERB(0);                DECODEITERB(1);                DECODEITERB(2);                DECODEITERB(3);                DECODEITERB(4);                DECODEITERB(5);                DECODEITERB(6);                DECODEITERB(7);          enddec:                while (state && numbits >= 8) {                        if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) {                                state = 0;                        } else {				*(bc->hdlcrx.bufptr)++ = bitbuf >> (16-numbits);				bc->hdlcrx.bufcnt++;				numbits -= 8;			}		}        }        bc->hdlcrx.numbits = numbits;	bc->hdlcrx.state = state;	bc->hdlcrx.bitstream = bitstream;	bc->hdlcrx.bitbuf = bitbuf;}/* --------------------------------------------------------------------- */#ifdef __i386__#define GETTICK(x)                                                \({                                                                \	if (current_cpu_data.x86_capability & X86_FEATURE_TSC)    \		__asm__ __volatile__("rdtsc" : "=a" (x) : : "dx");\})#else /* __i386__ */#define GETTICK(x)#endif /* __i386__ */static void epp_bh(struct device *dev){	struct baycom_state *bc;	struct parport *pp;	unsigned char stat;	unsigned int time1 = 0, time2 = 0, time3 = 0;	int cnt, cnt2;		baycom_paranoia_check_void(dev, "epp_bh");	bc = (struct baycom_state *)dev->priv;	if (!bc->bh_running)		return;	baycom_int_freq(bc);	pp = bc->pdev->port;	/* update status */	bc->stat = stat = parport_epp_read_addr(pp);	bc->debug_vals.last_pllcorr = stat;	GETTICK(time1);	if (bc->modem == EPP_FPGAEXTSTATUS) {		/* get input count */		parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1);		cnt = parport_epp_read_addr(pp);		cnt |= parport_epp_read_addr(pp) << 8;		cnt &= 0x7fff;		/* get output count */		parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|2);		cnt2 = parport_epp_read_addr(pp);		cnt2 |= parport_epp_read_addr(pp) << 8;		cnt2 = 16384 - (cnt2 & 0x7fff);		/* return to normal */		parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE);		transmit(bc, cnt2, stat);		GETTICK(time2);		receive(dev, cnt);		bc->stat = stat = parport_epp_read_addr(pp);	} else {		/* try to tx */		switch (stat & (EPP_NTAEF|EPP_NTHF)) {		case EPP_NTHF:			cnt = 2048 - 256;			break;				case EPP_NTAEF:			cnt = 2048 - 1793;			break;				case 0:			cnt = 0;			break;				default:			cnt = 2048 - 1025;			break;		}		transmit(bc, cnt, stat);		GETTICK(time2);		/* do receiver */		while ((stat & (EPP_NRAEF|EPP_NRHF)) != EPP_NRHF) {			switch (stat & (EPP_NRAEF|EPP_NRHF)) {			case EPP_NRAEF:				cnt = 1025;				break;			case 0:				cnt = 1793;				break;			default:				cnt = 256;				break;			}			receive(dev, cnt);			stat = parport_epp_read_addr(pp);			if (parport_epp_check_timeout(pp))				goto epptimeout;		}		cnt = 0;		if (bc->bitrate < 50000)			cnt = 256;		else if (bc->bitrate < 100000)			cnt = 128;		while (cnt > 0 && stat & EPP_NREF) {			receive(dev, 1);			cnt--;			stat = parport_epp_read_addr(pp);		}	}	GETTICK(time3);#ifdef BAYCOM_DEBUG	bc->debug_vals.mod_cycles = time2 - time1;	bc->debug_vals.demod_cycles = time3 - time2;#endif /* BAYCOM_DEBUG */	if (parport_epp_check_timeout(pp)) 		goto epptimeout;	queue_task(&bc->run_bh, &tq_timer);	return; epptimeout:	printk(KERN_ERR "%s: EPP timeout!\n", bc_drvname);}/* ---------------------------------------------------------------------- *//* * ===================== network driver interface ========================= */static int baycom_send_packet(struct sk_buff *skb, struct device *dev){	struct baycom_state *bc;	baycom_paranoia_check(dev, "baycom_send_packet", 0);	bc = (struct baycom_state *)dev->priv;	skb_queue_tail(&bc->send_queue, skb);	dev->trans_start = jiffies;		return 0;}/* --------------------------------------------------------------------- */static int baycom_set_mac_address(struct device *dev, void *addr){	struct sockaddr *sa = (struct sockaddr *)addr;	/* addr is an AX.25 shifted ASCII mac address */	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); 	return 0;                                         }/* --------------------------------------------------------------------- */static struct net_device_stats *baycom_get_stats(struct device *dev){	struct baycom_state *bc;	baycom_paranoia_check(dev, "baycom_get_stats", NULL);	bc = (struct baycom_state *)dev->priv;	/* 	 * Get the current statistics.  This may be called with the	 * card open or closed. 	 */	return &bc->stats;}/* --------------------------------------------------------------------- */static void epp_wakeup(void *handle){        struct device *dev = (struct device *)handle;        struct baycom_state *bc;	baycom_paranoia_check_void(dev, "epp_wakeup");        bc = (struct baycom_state *)dev->priv;        printk(KERN_DEBUG "baycom_epp: %s: why am I being woken up?\n", dev->name);        if (!parport_claim(bc->pdev))                printk(KERN_DEBUG "baycom_epp: %s: I'm broken.\n", dev->name);}/* --------------------------------------------------------------------- *//* * Open/initialize the board. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. */static int epp_open(struct device *dev){	struct baycom_state *bc;        struct parport *pp;	const struct tq_struct run_bh = {		0, 0, (void *)(void *)epp_bh, dev	};	unsigned int i, j;	unsigned char stat;	unsigned long tstart;		baycom_paranoia_check(dev, "epp_open", -ENXIO);	bc = (struct baycom_state *)dev->priv;	if (dev->start)		return 0;        pp = parport_enumerate();        while (pp && pp->base != dev->base_addr)                 pp = pp->next;        if (!pp) {                printk(KERN_ERR "%s: parport at 0x%lx unknown\n", bc_drvname, dev->base_addr);                return -ENXIO;        }#if 0        if (pp->irq < 0) {                printk(KERN_ERR "%s: parport at 0x%lx has no irq\n", bc_drvname, pp->base);                return -ENXIO;        }#endif	memset(&bc->modem, 0, sizeof(bc->modem));        if (!(bc->pdev = parport_register_device(pp, dev->name, NULL, epp_wakeup,                                                  epp_interrupt, PARPORT_DEV_EXCL, dev))) {                printk(KERN_ERR "%s: cannot register parport at 0x%lx\n", bc_drvname, pp->base);                return -ENXIO;        }        if (parport_claim(bc->pdev)) {                printk(KERN_ERR "%s: parport at 0x%lx busy\n", bc_drvname, pp->base);                parport_unregister_device(bc->pdev);                return -EBUSY;        }	if (!(pp->modes & (PARPORT_MODE_PCECPEPP|PARPORT_MODE_PCEPP))) {                printk(KERN_ERR "%s: parport at 0x%lx does not support any EPP mode\n",		       bc_drvname, pp->base);		parport_release(bc->pdev);                parport_unregister_device(bc->pdev);                return -EIO;			}        dev->irq = /*pp->irq*/ 0;	bc->run_bh = run_bh;	bc->bh_running = 1;	if (pp->modes & PARPORT_MODE_PCECPEPP) {		printk(KERN_INFO "%s: trying to enable EPP mode\n", bc_drvname);		parport_frob_econtrol(pp, 0xe0, 0x80);	}        /* bc->pdev->port->ops->change_mode(bc->pdev->port, PARPORT_MODE_PCEPP);  not yet implemented */	bc->modem = EPP_CONVENTIONAL;	if (eppconfig(bc))		printk(KERN_INFO "%s: no FPGA detected, assuming conventional EPP modem\n", bc_drvname);	else		bc->modem = /*EPP_FPGA*/ EPP_FPGAEXTSTATUS;	parport_write_control(pp, LPTCTRL_PROGRAM); /* prepare EPP mode; we aren't using interrupts */	/* reset the modem */	parport_epp_write_addr(pp, 0);	parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE);	/* autoprobe baud rate */	tstart = jiffies;	i = 0;	while ((signed)(jiffies-tstart-HZ/3) < 0) {		stat = parport_epp_read_addr(pp);		if ((stat & (EPP_NRAEF|EPP_NRHF)) == EPP_NRHF) {			schedule();			continue;		}		for (j = 0; j < 256; j++)			parport_epp_read_data(pp);		i += 256;	}	for (j = 0; j < 256; j++) {		stat = parport_epp_read_addr(pp);		if (!(stat & EPP_NREF))			break;		parport_epp_read_data(pp);		i++;	}	tstart = jiffies - tstart;	bc->bitrate = i * (8 * HZ) / tstart;	j = 1;	i = bc->bitrate >> 3;	while (j < 7 && i > 150) {		j++;		i >>= 1;	}	printk(KERN_INFO "%s: autoprobed bitrate: %d  int divider: %d  int rate: %d\n", 	       bc_drvname, bc->bitrate, j, bc->bitrate >> (j+2));	parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE/*|j*/);	/*	 * initialise hdlc variables	 */	bc->hdlcrx.state = 0;	bc->hdlcrx.numbits = 0;	bc->hdlctx.state = tx_idle;	bc->hdlctx.bufcnt = 0;	bc->hdlctx.slotcnt = bc->ch_params.slottime;	bc->hdlctx.calibrate = 0;        dev->start = 1;       	dev->tbusy = 0;	dev->interrupt = 0;	/* start the bottom half stuff */	queue_task(&bc->run_bh, &tq_timer);	MOD_INC_USE_COUNT;	return 0;#if 0  errreturn:        parport_release(bc->pdev);        parport_unregister_device(bc->pdev);	return -EIO;#endif}/* --------------------------------------------------------------------- */static int epp_close(struct device *dev){	struct baycom_state *bc;	struct parport *pp;	struct sk_buff *skb;	baycom_paranoia_check(dev, "epp_close", -EINVAL);	if (!dev->start)		return 0;

⌨️ 快捷键说明

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