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

📄 applicom.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
		spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags);		schedule();		if (signal_pending(current)) {			remove_wait_queue(&apbs[IndexCard].FlagSleepSend,					  &wait);			return -EINTR;	}		spin_lock_irqsave(&apbs[IndexCard].mutex, flags);	}	/* We may not have actually slept */	current->state = TASK_RUNNING;	remove_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait);	writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);	/* Which is best - lock down the pages with rawio and then	   copy directly, or use bounce buffers? For now we do the latter 	   because it works with 2.2 still */	{		unsigned char *from = (unsigned char *) &tmpmailbox;		unsigned long to = (unsigned long) apbs[IndexCard].RamIO + RAM_FROM_PC;		int c;		for (c = 0; c < sizeof(struct mailbox); c++)			writeb(*(from++), to++);	}	writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC);	writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC);	writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC);	writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);	writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);	writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);	Dummy = readb(apbs[IndexCard].RamIO + VERS);	spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags);	return 0;}static int do_ac_read(int IndexCard, char *buf){	struct st_ram_io st_loc;	struct mailbox tmpmailbox;	/* bounce buffer - can't copy to user space with cli() */	unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC;	unsigned char *to = (unsigned char *)&tmpmailbox;#ifdef DEBUG	int c;#endif	st_loc.tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC);	st_loc.numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);	{		int c;		for (c = 0; c < sizeof(struct mailbox); c++)			*(to++) = readb(from++);	}	writeb(1, apbs[IndexCard].RamIO + ACK_FROM_PC_READY);	writeb(1, apbs[IndexCard].RamIO + TYP_ACK_FROM_PC);	writeb(IndexCard+1, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);	writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC), 	       apbs[IndexCard].RamIO + TIC_ACK_FROM_PC);	writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY);	writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY);	writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);	Dummy = readb(apbs[IndexCard].RamIO + VERS);#ifdef DEBUG		printk("Read from applicom card #%d. struct st_ram_io follows:", NumCard);		for (c = 0; c < sizeof(struct st_ram_io);) {			printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]);			for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) {				printk(" %2.2X", ((unsigned char *) &st_loc)[c]);			}		}		printk("\nstruct mailbox follows:");		for (c = 0; c < sizeof(struct mailbox);) {			printk("\n%5.5X: %2.2X", c, ((unsigned char *) &tmpmailbox)[c]);			for (c++; c % 8 && c < sizeof(struct mailbox); c++) {				printk(" %2.2X", ((unsigned char *) &tmpmailbox)[c]);			}		}		printk("\n");#endif	/* Je suis stupide. DW. */	if (copy_to_user(buf, &st_loc, sizeof(struct st_ram_io)))		return -EFAULT;	if (copy_to_user(&buf[sizeof(struct st_ram_io)], &tmpmailbox, sizeof(struct mailbox)))		return -EFAULT;	return (sizeof(struct st_ram_io) + sizeof(struct mailbox));}static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr){	unsigned long flags;	unsigned int i;	unsigned char tmp;	int ret = 0;	DECLARE_WAITQUEUE(wait, current);#ifdef DEBUG	int loopcount=0;#endif	/* No need to ratelimit this. Only root can trigger it anyway */	if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {		printk( KERN_WARNING "Hmmm. read() of Applicom card, length %d != expected %d\n",			count,sizeof(struct st_ram_io) + sizeof(struct mailbox));		return -EINVAL;	}		while(1) {		/* Stick ourself on the wait queue */		current->state = TASK_INTERRUPTIBLE;		add_wait_queue(&FlagSleepRec, &wait);				/* Scan each board, looking for one which has a packet for us */		for (i=0; i < MAX_BOARD; i++) {			if (!apbs[i].RamIO)				continue;			spin_lock_irqsave(&apbs[i].mutex, flags);						tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY);						if (tmp == 2) {				/* Got a packet for us */				ret = do_ac_read(i, buf);				spin_unlock_irqrestore(&apbs[i].mutex, flags);				current->state = TASK_RUNNING;				remove_wait_queue(&FlagSleepRec, &wait);				return tmp;			}						if (tmp > 2) {				/* Got an error */				Dummy = readb(apbs[i].RamIO + VERS);								spin_unlock_irqrestore(&apbs[i].mutex, flags);				current->state = TASK_RUNNING;				remove_wait_queue(&FlagSleepRec, &wait);								printk(KERN_WARNING "APPLICOM driver read error board %d, DataToPcReady = %d\n",				       i,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));				DeviceErrorCount++;				return -EIO;			}						/* Nothing for us. Try the next board */			Dummy = readb(apbs[i].RamIO + VERS);			spin_unlock_irqrestore(&apbs[i].mutex, flags);					} /* per board */		/* OK - No boards had data for us. Sleep now */		schedule();		remove_wait_queue(&FlagSleepRec, &wait);		if (signal_pending(current))			return -EINTR;#ifdef DEBUG		if (loopcount++ > 2) {			printk("Looping in ac_read. loopcount %d\n", loopcount);		}#endif	} }static void ac_interrupt(int vec, void *dev_instance, struct pt_regs *regs){	unsigned int i;	unsigned int FlagInt;	unsigned int LoopCount;	//    printk("Applicom interrupt on IRQ %d occurred\n", vec);	LoopCount = 0;	do {		FlagInt = 0;		for (i = 0; i < MAX_BOARD; i++) {						/* Skip if this board doesn't exist */			if (!apbs[i].RamIO)				continue;			spin_lock(&apbs[i].mutex);			/* Skip if this board doesn't want attention */			if(readb(apbs[i].RamIO + RAM_IT_TO_PC) == 0) {				spin_unlock(&apbs[i].mutex);				continue;			}			FlagInt = 1;			writeb(0, apbs[i].RamIO + RAM_IT_TO_PC);			if (readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2) {				printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataToPcReady = %d\n",				       i+1,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));				DeviceErrorCount++;			}			if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && 			   (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6)) {								printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n",				       i+1,(int)readb(apbs[i].RamIO + DATA_FROM_PC_READY));				DeviceErrorCount++;			}			if (readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) {	/* mailbox sent by the card ?   */				if (waitqueue_active(&FlagSleepRec)) {				wake_up_interruptible(&FlagSleepRec);			}			}			if (readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0) {	/* ram i/o free for write by pc ? */				if (waitqueue_active(&apbs[i].FlagSleepSend)) {	/* process sleep during read ?    */					wake_up_interruptible(&apbs[i].FlagSleepSend);				}			}			Dummy = readb(apbs[i].RamIO + VERS);			if(readb(apbs[i].RamIO + RAM_IT_TO_PC)) {				/* There's another int waiting on this card */				spin_unlock(&apbs[i].mutex);				i--;			} else {				spin_unlock(&apbs[i].mutex);			}		}		if (FlagInt)			LoopCount = 0;		else			LoopCount++;	} while(LoopCount < 2);}static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)     {				/* @ ADG ou ATO selon le cas */	int i;	unsigned char IndexCard;	unsigned long pmem;	int ret = 0;	volatile unsigned char byte_reset_it;	struct st_ram_io *adgl;	/* In general, the device is only openable by root anyway, so we're not	   particularly concerned that bogus ioctls can flood the console. */	adgl = kmalloc(sizeof(struct st_ram_io), GFP_KERNEL);	if (!adgl)		return -ENOMEM;	if (copy_from_user(adgl, (void *)arg,sizeof(struct st_ram_io))) {		kfree(adgl);		return -EFAULT;	}		IndexCard = adgl->num_card-1;	 	if(cmd != 0 && cmd != 6 &&	   ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {		static int warncount = 10;		if (warncount) {			printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1);			warncount--;		}		kfree(adgl);		return -EINVAL;	}	switch (cmd) {			case 0:		pmem = apbs[IndexCard].RamIO;		for (i = 0; i < sizeof(struct st_ram_io); i++)			((unsigned char *)adgl)[i]=readb(pmem++);		if (copy_to_user((void *)arg, adgl, sizeof(struct st_ram_io)))			ret = -EFAULT;		break;	case 1:		pmem = apbs[IndexCard].RamIO + CONF_END_TEST;		for (i = 0; i < 4; i++)			adgl->conf_end_test[i] = readb(pmem++);		for (i = 0; i < 2; i++)			adgl->error_code[i] = readb(pmem++);		for (i = 0; i < 4; i++)			adgl->parameter_error[i] = readb(pmem++);		pmem = apbs[IndexCard].RamIO + VERS;		adgl->vers = readb(pmem);		pmem = apbs[IndexCard].RamIO + TYPE_CARD;		for (i = 0; i < 20; i++)			adgl->reserv1[i] = readb(pmem++);		*(int *)&adgl->reserv1[20] =  			(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + 			(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + 			(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) );		if (copy_to_user((void *)arg, adgl, sizeof(struct st_ram_io)))			ret = -EFAULT;		break;	case 2:		pmem = apbs[IndexCard].RamIO + CONF_END_TEST;		for (i = 0; i < 10; i++)			writeb(0xff, pmem++);		writeb(adgl->data_from_pc_ready, 		       apbs[IndexCard].RamIO + DATA_FROM_PC_READY);		writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);				for (i = 0; i < MAX_BOARD; i++) {			if (apbs[i].RamIO) {				byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC);			}		}		break;	case 3:		pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC;		writeb(adgl->tic_des_from_pc, pmem);		break;	case 4:		pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC;		adgl->tic_owner_to_pc     = readb(pmem++);		adgl->numcard_owner_to_pc = readb(pmem);		if (copy_to_user((void *)arg, adgl,sizeof(struct st_ram_io)))			ret = -EFAULT;		break;	case 5:		writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);		writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);		writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);		writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);		writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);		break;	case 6:		printk(KERN_INFO "APPLICOM driver release .... V2.8.0 ($Revision: 1.30 $)\n");		printk(KERN_INFO "Number of installed boards . %d\n", (int) numboards);		printk(KERN_INFO "Segment of board ........... %X\n", (int) mem);		printk(KERN_INFO "Interrupt IRQ number ....... %d\n", (int) irq);		for (i = 0; i < MAX_BOARD; i++) {			int serial;			char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];			if (!apbs[i].RamIO)				continue;			for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)				boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);			boardname[serial] = 0;			printk(KERN_INFO "Prom version board %d ....... V%d.%d %s",			       i+1,			       (int)(readb(apbs[IndexCard].RamIO + VERS) >> 4),			       (int)(readb(apbs[IndexCard].RamIO + VERS) & 0xF),			       boardname);			serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + 				(readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + 				(readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );			if (serial != 0)				printk(" S/N %d\n", serial);			else				printk("\n");		}		if (DeviceErrorCount != 0)			printk(KERN_INFO "DeviceErrorCount ........... %d\n", DeviceErrorCount);		if (ReadErrorCount != 0)			printk(KERN_INFO "ReadErrorCount ............. %d\n", ReadErrorCount);		if (WriteErrorCount != 0)			printk(KERN_INFO "WriteErrorCount ............ %d\n", WriteErrorCount);		if (waitqueue_active(&FlagSleepRec))			printk(KERN_INFO "Process in read pending\n");		for (i = 0; i < MAX_BOARD; i++) {			if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend))				printk(KERN_INFO "Process in write pending board %d\n",i+1);		}		break;	default:		printk(KERN_INFO "APPLICOM driver ioctl, unknown function code %d\n",cmd) ;		ret = -EINVAL;		break;	}	Dummy = readb(apbs[IndexCard].RamIO + VERS);	kfree(adgl);	return 0;}#ifndef MODULEstatic int __init applicom_setup(char *str){	int ints[4];	(void) get_options(str, 4, ints);	if (ints[0] > 2) {		printk(KERN_WARNING "Too many arguments to 'applicom=', expected mem,irq only.\n");	}	if (ints[0] < 2) {		printk(KERN_INFO"applicom numargs: %d\n", ints[0]);		return 0;	}	mem = ints[1];	irq = ints[2];	return 1;}__setup("applicom=", applicom_setup);#endif				/* MODULE */

⌨️ 快捷键说明

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