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

📄 rocket.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			return get_config(info, (struct rocket_config *) arg);		case RCKP_SET_CONFIG:			return set_config(info, (struct rocket_config *) arg);					case RCKP_GET_PORTS:			return get_ports(info, (struct rocket_ports *) arg);		default:			return -ENOIOCTLCMD;		}	return 0;}#if (defined(ROCKET_DEBUG_FLOW) || defined(ROCKET_DEBUG_THROTTLE))static char *rp_tty_name(struct tty_struct *tty, char *buf){	if (tty)		sprintf(buf, "%s%d", tty->driver.name,			MINOR(tty->device) - tty->driver.minor_start +			tty->driver.name_base);	else		strcpy(buf, "NULL tty");	return buf;}#endifstatic void rp_send_xchar(struct tty_struct *tty, char ch){	struct r_port *info = (struct r_port *)tty->driver_data;	CHANNEL_t *cp;	if (rocket_paranoia_check(info, tty->device, "rp_send_xchar"))		return;	cp = &info->channel;	if (sGetTxCnt(cp)) 		sWriteTxPrioByte(cp, ch);	else		sWriteTxByte(sGetTxRxDataIO(cp), ch);}static void rp_throttle(struct tty_struct * tty){	struct r_port *info = (struct r_port *)tty->driver_data;	CHANNEL_t *cp;#ifdef ROCKET_DEBUG_THROTTLE	char	buf[64];		printk("throttle %s: %d....\n", rp_tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif	if (rocket_paranoia_check(info, tty->device, "rp_throttle"))		return;	cp = &info->channel;	if (I_IXOFF(tty))		rp_send_xchar(tty, STOP_CHAR(tty));		sClrRTS(&info->channel);}static void rp_unthrottle(struct tty_struct * tty){	struct r_port *info = (struct r_port *)tty->driver_data;	CHANNEL_t *cp;#ifdef ROCKET_DEBUG_THROTTLE	char	buf[64];		printk("unthrottle %s: %d....\n", rp_tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif	if (rocket_paranoia_check(info, tty->device, "rp_throttle"))		return;	cp = &info->channel;	if (I_IXOFF(tty))		rp_send_xchar(tty, START_CHAR(tty));	sSetRTS(&info->channel);}/* * ------------------------------------------------------------ * rp_stop() and rp_start() * * This routines are called before setting or resetting tty->stopped. * They enable or disable transmitter interrupts, as necessary. * ------------------------------------------------------------ */static void rp_stop(struct tty_struct *tty){	struct r_port * info = (struct r_port *)tty->driver_data;#ifdef ROCKET_DEBUG_FLOW	char	buf[64];		printk("stop %s: %d %d....\n", rp_tty_name(tty, buf),	       info->xmit_cnt, info->xmit_fifo_room);#endif	if (rocket_paranoia_check(info, tty->device, "rp_stop"))		return;	if (sGetTxCnt(&info->channel))		sDisTransmit(&info->channel);}static void rp_start(struct tty_struct *tty){	struct r_port * info = (struct r_port *)tty->driver_data;#ifdef ROCKET_DEBUG_FLOW	char	buf[64];		printk("start %s: %d %d....\n", rp_tty_name(tty, buf),	       info->xmit_cnt, info->xmit_fifo_room);#endif	if (rocket_paranoia_check(info, tty->device, "rp_stop"))		return;	sEnTransmit(&info->channel);	xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));}/* * rp_wait_until_sent() --- wait until the transmitter is empty */static void rp_wait_until_sent(struct tty_struct *tty, int timeout){	struct r_port *info = (struct r_port *)tty->driver_data;	CHANNEL_t *cp;	unsigned long orig_jiffies;	int check_time, exit_time;	int txcnt;		if (rocket_paranoia_check(info, tty->device, "rp_wait_until_sent"))		return;	cp = &info->channel;	orig_jiffies = jiffies;#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT	printk("In RP_wait_until_sent(%d) (jiff=%lu)...", timeout, jiffies);	printk("cps=%d...", info->cps);#endif	while (1) {		txcnt = sGetTxCnt(cp);		if (!txcnt) {			if (sGetChanStatusLo(cp) & TXSHRMT)				break;			check_time = (HZ / info->cps) / 5;		} else			check_time = HZ * txcnt / info->cps;		if (timeout) {			exit_time = orig_jiffies + timeout - jiffies;			if (exit_time <= 0)				break;			if (exit_time < check_time)				check_time = exit_time;		}		if (check_time == 0)			check_time = 1;#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT		printk("txcnt = %d (jiff=%lu,check=%d)...", txcnt,		       jiffies, check_time);#endif		current->state = TASK_INTERRUPTIBLE;		current->counter = 0;	/* make us low-priority */		schedule_timeout(check_time);		if (signal_pending(current))			break;	}	current->state = TASK_RUNNING;#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT	printk("txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);#endif}/* * rp_hangup() --- called by tty_hangup() when a hangup is signaled. */static void rp_hangup(struct tty_struct *tty){	CHANNEL_t	*cp;	struct r_port * info = (struct r_port *)tty->driver_data;		if (rocket_paranoia_check(info, tty->device, "rp_hangup"))		return;#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))	printk("rp_hangup of ttyR%d...", info->line);#endif	/*	 * If the port is in the process of being closed, just force	 * the transmit buffer to be empty, and let rp_close handle	 * the clean up.	 */	if (info->flags & ROCKET_CLOSING) {		cli();		info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;		sti();		wake_up_interruptible(&tty->write_wait);		return;	}	if (info->count) {#ifdef MODULE		MOD_DEC_USE_COUNT;#endif		rp_num_ports_open--;	}		xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));	info->count = 0;	info->flags &= ~(ROCKET_NORMAL_ACTIVE|ROCKET_CALLOUT_ACTIVE);	info->tty = 0;	cp = &info->channel;	sDisRxFIFO(cp);	sDisTransmit(cp);	sDisInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));	sDisCTSFlowCtl(cp);	sDisTxSoftFlowCtl(cp);	sClrTxXOFF(cp);	info->flags &= ~ROCKET_INITIALIZED;		wake_up_interruptible(&info->open_wait);}/* * The Rocketport write routines.  The Rocketport driver uses a * double-buffering strategy, with the twist that if the in-memory CPU * buffer is empty, and there's space in the transmit FIFO, the * writing routines will write directly to transmit FIFO. * * This gets a little tricky, but I'm pretty sure I got it all right. */static void rp_put_char(struct tty_struct *tty, unsigned char ch){	struct r_port * info = (struct r_port *)tty->driver_data;	CHANNEL_t	*cp;	if (rocket_paranoia_check(info, tty->device, "rp_put_char"))		return;#ifdef ROCKET_DEBUG_WRITE	printk("rp_put_char %c...", ch);#endif		cp = &info->channel;	if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)		info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);	if (tty->stopped || tty->hw_stopped ||	    info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {		info->xmit_buf[info->xmit_head++] = ch;		info->xmit_head &= XMIT_BUF_SIZE-1;		info->xmit_cnt++;		xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));	} else {		sOutB(sGetTxRxDataIO(cp), ch);		info->xmit_fifo_room--;	}}#if (LINUX_VERSION_CODE > 66304)static int rp_write(struct tty_struct * tty, int from_user,		    const unsigned char *buf, int count)#elsestatic int rp_write(struct tty_struct * tty, int from_user,		    unsigned char *buf, int count)#endif	{	struct r_port * info = (struct r_port *)tty->driver_data;	CHANNEL_t	*cp;	const unsigned char	*b;	int		c, retval = 0;	unsigned long	flags;	if (count <= 0 || rocket_paranoia_check(info, tty->device, "rp_write"))		return 0;#ifdef ROCKET_DEBUG_WRITE	printk("rp_write %d chars...", count);#endif	cp = &info->channel;	if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)		info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);	if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0	    && info->xmit_fifo_room >= 0) {		c = MIN(count, info->xmit_fifo_room);		b = buf;		if (from_user) {			down(&tmp_buf_sem);			c -= copy_from_user(tmp_buf, buf, c);			b = tmp_buf;			up(&tmp_buf_sem);			/* In case we got pre-empted */			if (!c) {				retval = -EFAULT;				goto end;			}			if (info->tty == 0)				goto end;			c = MIN(c, info->xmit_fifo_room);		}		sOutStrW(sGetTxRxDataIO(cp), b, c/2);		if (c & 1)			sOutB(sGetTxRxDataIO(cp), b[c-1]);		retval += c;		buf += c;		count -= c;		info->xmit_fifo_room -= c;	}	if (!count)		goto end;		save_flags(flags);	while (1) {		if (info->tty == 0) {			restore_flags(flags);			goto end;		}		c = MIN(count, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1,				   XMIT_BUF_SIZE - info->xmit_head));		if (c <= 0)			break;		b = buf;		if (from_user) {			down(&tmp_buf_sem);			c -= copy_from_user(tmp_buf, buf, c);			b = tmp_buf;			up(&tmp_buf_sem);			if (!c) {				if (retval == 0)					retval = -EFAULT;				goto end_intr;			}			/* In case we got pre-empted */			if (info->tty == 0)				goto end_intr;		}		cli();		c = MIN(c, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1,			       XMIT_BUF_SIZE - info->xmit_head));		memcpy(info->xmit_buf + info->xmit_head, b, c);		info->xmit_head = (info->xmit_head + c) & (XMIT_BUF_SIZE-1);		info->xmit_cnt += c;		restore_flags(flags);		buf += c;		count -= c;		retval += c;	}end_intr:	if ((retval > 0) && !tty->stopped && !tty->hw_stopped)		xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));	restore_flags(flags);end:	if (info->xmit_cnt < WAKEUP_CHARS) {		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&		    tty->ldisc.write_wakeup)			(tty->ldisc.write_wakeup)(tty);		wake_up_interruptible(&tty->write_wait);	}	return retval;}/* * Return the number of characters that can be sent.  We estimate * only using the in-memory transmit buffer only, and ignore the * potential space in the transmit FIFO. */static int rp_write_room(struct tty_struct *tty){	struct r_port * info = (struct r_port *)tty->driver_data;	int	ret;	if (rocket_paranoia_check(info, tty->device, "rp_write_room"))		return 0;	ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;	if (ret < 0)		ret = 0;#ifdef ROCKET_DEBUG_WRITE	printk("rp_write_room returns %d...", ret);#endif	return ret;}/* * Return the number of characters in the buffer.  Again, this only * counts those characters in the in-memory transmit buffer. */static int rp_chars_in_buffer(struct tty_struct *tty){	struct r_port * info = (struct r_port *)tty->driver_data;	CHANNEL_t	*cp;	if (rocket_paranoia_check(info, tty->device, "rp_chars_in_buffer"))		return 0;	cp = &info->channel;#ifdef ROCKET_DEBUG_WRITE	printk("rp_chars_in_buffer returns %d...", info->xmit_cnt);#endif	return info->xmit_cnt;}static void rp_flush_buffer(struct tty_struct *tty){	struct r_port * info = (struct r_port *)tty->driver_data;	CHANNEL_t	*cp;	if (rocket_paranoia_check(info, tty->device, "rp_flush_buffer"))		return;	cli();	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;	sti();	wake_up_interruptible(&tty->write_wait);	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup)		(tty->ldisc.write_wakeup)(tty);		cp = &info->channel;		sFlushTxFIFO(cp);}#ifdef ENABLE_PCI#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 *//* For compatibility */static struct pci_dev *pci_find_slot(unsigned char bus,				     unsigned char device_fn){	unsigned short		vendor_id, device_id;	int			ret, error;	static struct pci_dev	ret_struct;		error = pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID,		&vendor_id);	ret = pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID,		&device_id);	if (error == 0)		error = ret;	if (error) {		printk("PCI RocketPort error: %s not initializing due to error"		       "reading configuration space\n",		       pcibios_strerror(error));		return(0);	}	memset(&ret_struct, 0, sizeof(ret_struct));	ret_struct.device = device_id;	return &ret_struct;}#endif     __initfunc(int register_PCI(int i, unsigned int bus, unsigned int device_fn)){	int	num_aiops, aiop, max_num_aiops, num_chan, chan;	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];	char *str;	CONTROLLER_t	*ctlp;	struct pci_dev *dev = pci_find_slot(bus, device_fn);#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */	int	ret;	unsigned int port;#endif	if (!dev)		return 0;#if (LINUX_VERSION_CODE >= 0x020163) /* 2.1.99 */	rcktpt_io_addr[i] = dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;#else	ret = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0,		&port);	if (ret)		return 0;	rcktpt_io_addr[i] = port & PCI_BASE_ADDRESS_IO_MASK;#endif		switch(dev->device) {	case PCI_DEVICE_ID_RP4QUAD:		str = "Quadcable";		max_num_aiops = 1;		break;	case PCI_DEVICE_ID_RP8OCTA:		str = "Octacable";		max_num_aiops = 1;		break;	case PCI_DEVICE_ID_RP8INTF:		str = "8";

⌨️ 快捷键说明

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