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

📄 fipkernel.c

📁 em86xx 完整启动程序,支持网络下载与串通下载
💻 C
📖 第 1 页 / 共 3 页
字号:
int uart_printf(const char *fmt, ...);int strlen(const char *str);#endif /* __KERNEL__ */#define FIP_DEV_NAME		"fip"static void fip_write_reg(unsigned int offset, unsigned int val);static unsigned int fip_read_reg(unsigned int offset);#ifdef __KERNEL__ #define CMDQ_SIZE	256/* Private data structure */struct cmd_request {	unsigned int cmd;	unsigned int data;};struct fip_private {	unsigned long *buffer;		/* Circular buffer */	unsigned p_idx;			/* Index of producer */	unsigned c_idx; 		/* Index of consumer */	unsigned ref_cnt;		/* Reference count */	spinlock_t lock;		/* Spin lock */	unsigned char b_mode;		/* Blocking mode or not */	unsigned long last_jiffies;	/* Timestamp for last reception */#ifdef ENABLE_WRITE_INTR	struct cmd_request cmds[CMDQ_SIZE];	unsigned cmd_pidx;	unsigned cmd_cidx;	unsigned cmdq_empty;#endif};static struct file_operations fip_fops = {	open: fip_open,	read: fip_read,	ioctl: fip_ioctl,	poll: fip_poll,	write: fip_write,	release: fip_release,	owner: THIS_MODULE,};static void fip_push_key(struct fip_private *priv, unsigned long key);#ifdef ENABLE_WRITE_INTRstatic void fip_issue_command(struct fip_private *priv);static void fip_queue_command(unsigned int cmd, unsigned int data);#endif/* Global data */static struct fip_private fip_priv;static devfs_handle_t devfs_handle = NULL;static int fip_major = FIP_DEV_MAJOR;#endif /* __KERNEL__ */static char *fip_devname = FIP_DEV_NAME;static int brightness = BRIGHTNESS;static unsigned long fip_base = (unsigned long)FIP_BASE;static char fipram[MAX_FIP_RAM] = {0};#ifdef __KERNEL__static void fip_isr(int irq, void *dev_id, struct pt_regs *regs){	struct fip_private *priv = (struct fip_private *)dev_id;	unsigned long stat;	unsigned long key;	if (irq == fip_irq) {		__raw_writel(IRQMASKOF(irq), REG_BASE_CPU + CPU_edge_rawstat);		stat = (fip_read_reg(FIP_INT) & 0x3);		fip_write_reg(FIP_INT, stat); /* Clear the interrupt */		if (!is_fip_busy_nowait()) {			if (stat & 0x2) {				key = fip_read_reg(FIP_KEY_DATA1);				fip_push_key(priv, key);			}#ifdef ENABLE_WRITE_INTR			fip_issue_command(priv);#endif		}	} else		printk("Unknown IRQ %d\n", irq);}static void fip_poll_key(unsigned long devid){	struct fip_private *priv = (struct fip_private *)devid;	/* Sending command, and later ISR will pick up the interrupt and read           the key */	if (!is_fip_busy_nowait()) {		fip_write_reg(FIP_COMMAND, FIP_CMD_DATA_SET_RW_MODE_READ_KEYS);#ifdef ENABLE_WRITE_INTR		if (priv->cmdq_empty != 0) {			fip_issue_command(priv);		}#endif	}	if (priv->ref_cnt != 0) {		mod_timer(&fip_timer, jiffies + (HZ / poll_per_sec));#if 0		queue_task(&immediate, &tq_immediate);		mark_bh(IMMEDIATE_BH);#endif	}}/* Produce data */static void fip_push_key(struct fip_private *priv, unsigned long key){	unsigned pidx;	static unsigned long oldkey = 0;	spin_lock(&priv->lock);	if ((key == 0) || (key == 0xffffffff)) {		oldkey = 0;		goto out;	} else if (((priv->last_jiffies + wait_period) > jiffies) 			&& (key == oldkey))		goto out;	else		priv->last_jiffies = jiffies;		printk(KERN_DEBUG "%s: got data 0x%08lx\n", fip_devname, key);	pidx = priv->p_idx;	/* Save the old index before proceeding */	/* Save it to buffer */	if (((priv->p_idx + 1) % buffer_size) == priv->c_idx) {		/* Adjust consumer index since buffer is full */		/* Keep the latest one and drop the oldest one */		priv->c_idx = (priv->c_idx + 1) % buffer_size;		printk(KERN_WARNING "%s: buffer full\n", fip_devname);	}	priv->buffer[priv->p_idx] = oldkey = key;	priv->p_idx = (priv->p_idx + 1) % buffer_size;	/* Buffer was empty and block mode is on, wake up the reader */	if ((priv->b_mode != 0) && (priv->c_idx == pidx))		wake_up_interruptible(&fip_wq);out:	spin_unlock(&priv->lock);}/* Reading from driver's buffer, note that it can return read size   less than specified */static int fip_consume(void *dev_id, unsigned long *buf, int count){	struct fip_private *priv = (struct fip_private *)dev_id;	int cnt;	unsigned long flags;	spin_lock_irqsave(&priv->lock, flags);	/* If block mode is on, check the emptiness of buffer */	if (priv->b_mode != 0) {		/* Sleep when buffer is empty */		while (priv->c_idx == priv->p_idx) {			spin_unlock_irqrestore(&priv->lock, flags);			interruptible_sleep_on(&fip_wq);			spin_lock_irqsave(&priv->lock, flags);		}	}	/* Get the data out and adjust consumer index */	for (cnt = 0; (priv->c_idx != priv->p_idx) && (cnt < count); cnt++) {		*buf = priv->buffer[priv->c_idx];		priv->c_idx = (priv->c_idx + 1) % buffer_size;		buf++;	}	spin_unlock_irqrestore(&priv->lock, flags);	return(cnt);}/* Poll function */static unsigned int fip_poll(struct file *fptr, struct poll_table_struct *ptable){	struct fip_private *priv = (struct fip_private *)fptr->private_data;	unsigned int mask = 0;	poll_wait(fptr, &fip_wq, ptable);	if (priv->c_idx != priv->p_idx)		mask |= (POLLIN | POLLRDNORM);	return(mask);}#ifdef ENABLE_WRITE_INTRstatic void fip_issue_command(struct fip_private *priv){	unsigned long flags;	spin_lock_irqsave(&priv->lock, flags);	if (priv->cmd_pidx == priv->cmd_cidx) {		priv->cmdq_empty = 1;		goto out;	} else if (!is_fip_busy_nowait()) {		priv->cmdq_empty = 0;		fip_wait_ready();		fip_write_reg(FIP_DISPLAY_DATA, priv->cmds[priv->cmd_cidx].data);		fip_wait_ready();		fip_write_reg(FIP_COMMAND, priv->cmds[priv->cmd_cidx].cmd);		fip_wait_ready();		priv->cmd_cidx = ((priv->cmd_cidx + 1) % CMDQ_SIZE);		if (priv->cmd_pidx == priv->cmd_cidx) 			priv->cmdq_empty = 1;	}out:	spin_unlock_irqrestore(&priv->lock, flags);}#endifstatic int fip_open(struct inode *inode_ptr, struct file *fptr){	MOD_INC_USE_COUNT;	/* This device is exclusive, that is, only one process can use it */	if (fip_priv.ref_cnt != 0) {		printk(KERN_WARNING "%s: exclusive access only\n", fip_devname);		return(-EIO);	} 	/* Set the block mode and increase reference count */	fip_priv.ref_cnt++;	fip_priv.b_mode = ((fptr->f_flags & O_NONBLOCK) ? 0 : 1);	fip_priv.last_jiffies = jiffies;	/* Flush the buffer */	fip_priv.p_idx = fip_priv.c_idx = 0;	fptr->f_op = &fip_fops;	fptr->private_data = (void *)&fip_priv;	fip_timer.function = fip_poll_key;	fip_timer.data = (unsigned long)&fip_priv;	fip_timer.expires = jiffies + (HZ / poll_per_sec);	add_timer(&fip_timer);#if 0	immediate.sync = 0;	immediate.data = (void *)&fip_priv;	immediate.routine = fip_poll_key;	queue_task(&immediate, &tq_immediate);	mark_bh(IMMEDIATE_BH);#endif	fip_clear();	return(0);}static int fip_release(struct inode *inode_ptr, struct file *fptr) {	unsigned long start = 0;	MOD_DEC_USE_COUNT;	/* Adjust reference count */	fip_priv.ref_cnt--;	/* Wait for timer expiration */	for (start = jiffies; (start + 2 * (HZ / poll_per_sec)) > jiffies;);	del_timer_sync(&fip_timer);	return(0);}static int fip_read(struct file *fptr, char *bufptr, size_t size, loff_t *fp){	unsigned long buf[buffer_size];	int count = 0;	/* Check the alignment */	if (size % sizeof(unsigned long)) {		printk(KERN_WARNING "%s: read size not aligned to %ld\n",			fip_devname, sizeof(unsigned long));		return(-EIO);	}	count = fip_consume(fptr->private_data, &buf[0], 			size / sizeof(unsigned long)) * sizeof(unsigned long);	/* Get the data to user */	if (copy_to_user(bufptr, (char *)&buf[0], count)) 		return(-EFAULT);	return(count);}static int fip_write(struct file *fptr, const char *bufptr, size_t size, loff_t *fp){	fip_wait_ready();	fip_write_text(0, bufptr, FIP_CENTER); 	fip_wait_ready();	return(size);}static int fip_ioctl(struct inode *inode, struct file *fptr, unsigned int cmd, unsigned long arg){	int on = 0;	int symbol;	int i, j, k;	switch(cmd) {		case FIP_IOCSHOWSYMBOL:			on = ((arg & 0x80000000)) == 0 ? 0 : 1;			symbol = (int)(arg & 0xff);			fip_display_symbol(symbol, on);			break;		case FIP_IOCSHOWHMS:			k = (int)(arg & 0xff);			j = (int)((arg >> 8) & 0xff);			i = (int)((arg >> 16) & 0xff);			fip_show_hms(i, j, k);			break;		case FIP_IOCDISPCHAR:			k = (int)(arg & 0xff);			j = (int)((arg >> 8) & 0xff);			fip_display_character(j, k);			break;		case FIP_IOCDISPRAW:			on = ((arg & 0x80000000)) == 0 ? 0 : 1;			k = (int)(arg & 0xff);			j = (int)((arg >> 8) & 0xff);			fip_display_raw(j, k, on);			break;		case FIP_IOCDISPTEXT:			printk("%s: ioctl FIP_IOCDISPTEXT not implemented.\n", fip_devname);			return(-EIO);		case FIP_IOCCLEAR:			fip_clear();			break;		case FIP_IOCGETFPTYPE:			{				unsigned long *ptr = (unsigned long *)arg;				unsigned long type = 0;#if defined(CONFIG_EM86XX_FIP_REF1)				type = 1;#elif defined(CONFIG_EM86XX_FIP_REF2)				type = 2;#else				return(-EIO);#endif				if (copy_to_user(ptr, (char *)&type, sizeof(unsigned long))) 					return(-EFAULT);			}			break;					case FIP_IOCSETLED:			k = (int)(arg & 0xff);			fip_setled(k);			break;		default:			return(-EIO);	}	return(0);}#endif /* __KERNEL__ *//* Micro-second sleep */static void fip_usleep(unsigned usec){#ifdef __KERNEL__	udelay(usec);#else	em86xx_usleep(usec);#endif /* __KERNEL__ */}static unsigned int fip_read_reg(unsigned int offset){	unsigned int val = *((volatile unsigned int *)(fip_base + offset));	return(val);}static void fip_write_reg(unsigned int offset, unsigned int val){	fip_wait_ready();	*((volatile unsigned int *)(fip_base + offset)) = val;	fip_wait_ready();}#ifdef __KERNEL__#ifdef ENABLE_WRITE_INTR/* To queue the write request */static void fip_queue_command(unsigned int cmd, unsigned int data){	unsigned long flags;	spin_lock_irqsave(&fip_priv.lock, flags);	if (((fip_priv.cmd_pidx + 1) % CMDQ_SIZE) == fip_priv.cmd_cidx) {		printk(KERN_ERR "Command queue full.\n");		fip_issue_command(&fip_priv);	} else {		fip_priv.cmds[fip_priv.cmd_pidx].cmd = cmd;		fip_priv.cmds[fip_priv.cmd_pidx].data = data;		fip_priv.cmd_pidx = ((fip_priv.cmd_pidx + 1) % CMDQ_SIZE);	}	spin_unlock_irqrestore(&fip_priv.lock, flags);}#endif#endif#ifdef __KERNEL__static int is_fip_busy_nowait(void){	return((fip_read_reg(FIP_CONFIG) & FIP_BUSY) != 0);}#endif#ifdef __KERNEL__static#endif /* __KERNEL__ */int is_fip_busy(void){#if defined(CONFIG_EM86XX_FIP_REF1)	fip_usleep(10);#elif defined(CONFIG_EM86XX_FIP_REF2)	fip_usleep(20);#endif	return((fip_read_reg(FIP_CONFIG) & FIP_BUSY) != 0);}#ifdef __KERNEL__static#endif /* __KERNEL__ */void fip_wait_ready(void){	while (is_fip_busy());#if defined(CONFIG_EM86XX_FIP_REF2)	fip_usleep(20);#endif}static void fip_user_display(int adr, int data){#ifdef __KERNEL__#ifdef ENABLE_WRITE_INTR	fip_wait_ready();	fip_queue_command(FIP_CMD_ADR_SETTING | (adr), data);#else	fip_wait_ready();	fip_write_reg(FIP_DISPLAY_DATA, data);	fip_write_reg(FIP_COMMAND, FIP_CMD_ADR_SETTING | (adr));#endif#else	fip_wait_ready();	fip_write_reg(FIP_DISPLAY_DATA, data);	fip_wait_ready();	fip_write_reg(FIP_COMMAND, FIP_CMD_ADR_SETTING | (adr));	fip_wait_ready();#endif}#ifdef __KERNEL__static#endif /* __KERNEL__ */int fip_display_character(const int position, const char character) {	unsigned int data1,data2;	int i, byte1, byte2;	unsigned char current_contents0, current_contents1;#if defined(CONFIG_EM86XX_FIP_REF1)	const int min_pos = 1;#elif defined(CONFIG_EM86XX_FIP_REF2)	const int min_pos = 0;#endif		if ((position < min_pos) || (position > NUM_DIGITS)) {#ifdef __KERNEL__		printk(KERN_DEBUG "%s: position %d not available/supported.\n",				fip_devname, position);#else		uart_printf("%s: position %d not available/supported.\n",				fip_devname, position);#endif /* __KERNEL__ */		return(0);	}	for (i = 0; i < NUM_CHARACTERS; i++) {

⌨️ 快捷键说明

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