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

📄 isicom.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (!arg)				isicom_send_break(port, HZ/4);			return 0;					case TCSBRKP:				retval = tty_check_change(tty);			if (retval)				return retval;			tty_wait_until_sent(tty, 0);			isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);			return 0;					case TIOCGSOFTCAR:			return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);					case TIOCSSOFTCAR:			if(get_user(arg, (unsigned long *) arg))				return -EFAULT;			tty->termios->c_cflag =				((tty->termios->c_cflag & ~CLOCAL) |				(arg ? CLOCAL : 0));			return 0;						case TIOCMGET:			return isicom_get_modem_info(port, (unsigned int*) arg);					case TIOCMBIS:		case TIOCMBIC:		case TIOCMSET: 				return isicom_set_modem_info(port, cmd, 					(unsigned int *) arg);				case TIOCGSERIAL:			return isicom_get_serial_info(port, 					(struct serial_struct *) arg);				case TIOCSSERIAL:			return isicom_set_serial_info(port,					(struct serial_struct *) arg);							default:			return -ENOIOCTLCMD;							}	return 0;}/* set_termios et all */static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios){	struct isi_port * port = (struct isi_port *) tty->driver_data;	unsigned long flags;		if (isicom_paranoia_check(port, tty->device, "isicom_set_termios"))		return;		if (tty->termios->c_cflag == old_termios->c_cflag &&	    tty->termios->c_iflag == old_termios->c_iflag)		return;			save_flags(flags); cli();	isicom_config_port(port);	restore_flags(flags);		if ((old_termios->c_cflag & CRTSCTS) &&	    !(tty->termios->c_cflag & CRTSCTS)) {			tty->hw_stopped = 0;		isicom_start(tty);   	}    }/* throttle et all */static void isicom_throttle(struct tty_struct * tty){	struct isi_port * port = (struct isi_port *) tty->driver_data;	struct isi_board * card = port->card;	unsigned long flags;		if (isicom_paranoia_check(port, tty->device, "isicom_throttle"))		return;		/* tell the card that this port cannot handle any more data for now */	save_flags(flags); cli();	card->port_status &= ~(1 << port->channel);	outw(card->port_status, card->base + 0x02);	restore_flags(flags);}/* unthrottle et all */static void isicom_unthrottle(struct tty_struct * tty){	struct isi_port * port = (struct isi_port *) tty->driver_data;	struct isi_board * card = port->card;	unsigned long flags;		if (isicom_paranoia_check(port, tty->device, "isicom_unthrottle"))		return;		/* tell the card that this port is ready to accept more data */	save_flags(flags); cli();	card->port_status |= (1 << port->channel);	outw(card->port_status, card->base + 0x02);	restore_flags(flags);}/* stop et all */static void isicom_stop(struct tty_struct * tty){	struct isi_port * port = (struct isi_port *) tty->driver_data;	if (isicom_paranoia_check(port, tty->device, "isicom_stop"))		return;		/* this tells the transmitter not to consider this port for	   data output to the card. */	port->status &= ~ISI_TXOK;}/* start et all */static void isicom_start(struct tty_struct * tty){	struct isi_port * port = (struct isi_port *) tty->driver_data;		if (isicom_paranoia_check(port, tty->device, "isicom_start"))		return;		/* this tells the transmitter to consider this port for	   data output to the card. */	port->status |= ISI_TXOK;}/* hangup et all */static void do_isicom_hangup(void * data){	struct isi_port * port = (struct isi_port *) data;	struct tty_struct * tty;		tty = port->tty;	if (!tty)		return;			tty_hangup(tty);	}static void isicom_hangup(struct tty_struct * tty){	struct isi_port * port = (struct isi_port *) tty->driver_data;		if (isicom_paranoia_check(port, tty->device, "isicom_hangup"))		return;		isicom_shutdown_port(port);	port->count = 0;	port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);	port->tty = 0;	wake_up_interruptible(&port->open_wait);}/* flush_buffer et all */static void isicom_flush_buffer(struct tty_struct * tty){	struct isi_port * port = (struct isi_port *) tty->driver_data;	unsigned long flags;		if (isicom_paranoia_check(port, tty->device, "isicom_flush_buffer"))		return;		save_flags(flags); cli();	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;	restore_flags(flags);		wake_up_interruptible(&tty->write_wait);	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup)		(tty->ldisc.write_wakeup)(tty);}static int register_ioregion(void){	int count, done=0;	for (count=0; count < BOARD_COUNT; count++ ) {		if (isi_card[count].base) {			if (check_region(isi_card[count].base,16)) {				printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",					isi_card[count].base,isi_card[count].base+15,count+1);				isi_card[count].base=0;			}			else {				request_region(isi_card[count].base,16,ISICOM_NAME);#ifdef ISICOM_DEBUG								printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x requested for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);#endif								done++;			}		}		}	return done;}static void unregister_ioregion(void){	int count;	for (count=0; count < BOARD_COUNT; count++ ) 		if (isi_card[count].base) {			release_region(isi_card[count].base,16);#ifdef ISICOM_DEBUG						printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);#endif					}}static int register_drivers(void){	int error;	/* tty driver structure initialization */	memset(&isicom_normal, 0, sizeof(struct tty_driver));	isicom_normal.magic	= TTY_DRIVER_MAGIC;	isicom_normal.name 	= "ttyM";	isicom_normal.major	= ISICOM_NMAJOR;	isicom_normal.minor_start	= 0;	isicom_normal.num	= PORT_COUNT;	isicom_normal.type	= TTY_DRIVER_TYPE_SERIAL;	isicom_normal.subtype	= SERIAL_TYPE_NORMAL;	isicom_normal.init_termios	= tty_std_termios;	isicom_normal.init_termios.c_cflag	= 				B9600 | CS8 | CREAD | HUPCL |CLOCAL;	isicom_normal.flags	= TTY_DRIVER_REAL_RAW;	isicom_normal.refcount	= &isicom_refcount;		isicom_normal.table	= isicom_table;	isicom_normal.termios	= isicom_termios;	isicom_normal.termios_locked	= isicom_termios_locked;		isicom_normal.open	= isicom_open;	isicom_normal.close	= isicom_close;	isicom_normal.write	= isicom_write;	isicom_normal.put_char	= isicom_put_char;	isicom_normal.flush_chars	= isicom_flush_chars;	isicom_normal.write_room	= isicom_write_room;	isicom_normal.chars_in_buffer	= isicom_chars_in_buffer;	isicom_normal.ioctl	= isicom_ioctl;	isicom_normal.set_termios	= isicom_set_termios;	isicom_normal.throttle	= isicom_throttle;	isicom_normal.unthrottle	= isicom_unthrottle;	isicom_normal.stop	= isicom_stop;	isicom_normal.start	= isicom_start;	isicom_normal.hangup	= isicom_hangup;	isicom_normal.flush_buffer	= isicom_flush_buffer;		/*	callout device	*/		isicom_callout	= isicom_normal;	isicom_callout.name	= "cum"; 	isicom_callout.major	= ISICOM_CMAJOR;	isicom_callout.subtype	= SERIAL_TYPE_CALLOUT;		if ((error=tty_register_driver(&isicom_normal))!=0) {		printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",			error);		return error;	}	if ((error=tty_register_driver(&isicom_callout))!=0) {		tty_unregister_driver(&isicom_normal);		printk(KERN_DEBUG "ISICOM: Couldn't register the callout driver, error=%d\n",			error);		return error;		}	return 0;}static void unregister_drivers(void){	int error;	if ((error=tty_unregister_driver(&isicom_callout))!=0)		printk(KERN_DEBUG "ISICOM: couldn't unregister callout driver error=%d.\n",error);	if (tty_unregister_driver(&isicom_normal))		printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);}static int register_isr(void){	int count, done=0;	for (count=0; count < BOARD_COUNT; count++ ) {		if (isi_card[count].base) {			if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT, ISICOM_NAME, NULL)) {				printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n",					isi_card[count].irq, count+1);				release_region(isi_card[count].base,16);				isi_card[count].base=0;			}			else {				printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n", 				count+1, isi_card[count].base, isi_card[count].irq); 								irq_to_board[isi_card[count].irq]=&isi_card[count];				done++;			}		}		}	return done;}static void unregister_isr(void){	int count;	for (count=0; count < BOARD_COUNT; count++ ) 		if (isi_card[count].base) {			free_irq(isi_card[count].irq, NULL);#ifdef ISICOM_DEBUG						printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1);#endif					}}static int isicom_init(void){	int card, channel, base;	struct isi_port * port;	unsigned long page;		if (!tmp_buf) { 		page = get_free_page(GFP_KERNEL);	      	if (!page) {#ifdef ISICOM_DEBUG	      		      		printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");#else			printk(KERN_ERR "ISICOM: Not enough memory...\n");#endif	      	      		return 0;	      	}		      	tmp_buf = (unsigned char *) page;	}		if (!register_ioregion()) 	{		printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");		free_page((unsigned long)tmp_buf);		return 0;	}	if (register_drivers()) 	{		unregister_ioregion();		free_page((unsigned long)tmp_buf);		return 0;	}	if (!register_isr()) 	{		unregister_drivers();		/*  ioports already uregistered in register_isr */		free_page((unsigned long)tmp_buf);		return 0;			}		/* initialize bottom half  */	init_bh(ISICOM_BH, do_isicom_bh);	memset(isi_ports, 0, sizeof(isi_ports));	for (card = 0; card < BOARD_COUNT; card++) {		port = &isi_ports[card * 16];		isi_card[card].ports = port;		base = isi_card[card].base;		for (channel = 0; channel < 16; channel++, port++) {			port->magic = ISICOM_MAGIC;			port->card = &isi_card[card];			port->channel = channel;					port->normal_termios = isicom_normal.init_termios;			port->callout_termios = isicom_callout.init_termios;		 	port->close_delay = 50 * HZ/100;		 	port->closing_wait = 3000 * HZ/100;			port->hangup_tq.routine = do_isicom_hangup;		 	port->hangup_tq.data = port;		 	port->bh_tqueue.routine = isicom_bottomhalf;		 	port->bh_tqueue.data = port;		 	port->status = 0;		 							/*  . . .  */ 		}	} 		return 1;	}/* *	Insmod can set static symbols so keep these static */ static int io[4];static int irq[4];MODULE_AUTHOR("MultiTech");MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");MODULE_PARM(io, "1-4i");MODULE_PARM_DESC(io, "I/O ports for the cards");MODULE_PARM(irq, "1-4i");MODULE_PARM_DESC(irq, "Interrupts for the cards");int init_module(void){	int retval, card;	for(card=0; card < BOARD_COUNT; card++)	{			isi_card[card].base=io[card];		isi_card[card].irq=irq[card];	}		for (card=0 ;card < BOARD_COUNT; card++) {		if (!((isi_card[card].irq==2)||(isi_card[card].irq==3)||		    (isi_card[card].irq==4)||(isi_card[card].irq==5)||		    (isi_card[card].irq==7)||(isi_card[card].irq==10)||		    (isi_card[card].irq==11)||(isi_card[card].irq==12)||		    (isi_card[card].irq==15))) {						if (isi_card[card].base) {				printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",					isi_card[card].irq, card+1);				isi_card[card].base=0;			}			}	}			if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {		printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); 		return -EIO;	}			retval=misc_register(&isiloader_device);	if (retval<0) {		printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");		return -EIO;	}		if (!isicom_init()) {		if (misc_deregister(&isiloader_device)) 			printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");		return -EIO;	}		init_timer(&tx);	tx.expires = jiffies + 1;	tx.data = 0;	tx.function = isicom_tx;	re_schedule = 1;	add_timer(&tx);		return 0;}void cleanup_module(void){	re_schedule = 0;	current->state = TASK_INTERRUPTIBLE;	schedule_timeout(HZ);	disable_bh(ISICOM_BH);	#ifdef ISICOM_DEBUG		printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);#endif	#ifdef ISICOM_DEBUG	printk("ISICOM: uregistering isr ...\n");#endif		unregister_isr();#ifdef ISICOM_DEBUG		printk("ISICOM: unregistering drivers ...\n");#endif	unregister_drivers();	#ifdef ISICOM_DEBUG		printk("ISICOM: unregistering ioregion ...\n");#endif		unregister_ioregion();		#ifdef ISICOM_DEBUG		printk("ISICOM: freeing tmp_buf ...\n");#endif		free_page((unsigned long)tmp_buf);	#ifdef ISICOM_DEBUG			printk("ISICOM: unregistering firmware loader ...\n");	#endif	if (misc_deregister(&isiloader_device))		printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");}

⌨️ 快捷键说明

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