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

📄 epca.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* We dec count so that pc_close will know when to free things */	if (!tty_hung_up_p(filp))		ch->count--;	restore_flags(flags);	ch->blocked_open++;	while(1) 	{ /* Begin forever while  */		set_current_state(TASK_INTERRUPTIBLE);		if (tty_hung_up_p(filp) ||		    !(ch->asyncflags & ASYNC_INITIALIZED)) 		{			if (ch->asyncflags & ASYNC_HUP_NOTIFY)				retval = -EAGAIN;			else				retval = -ERESTARTSYS;				break;		}		if (!(ch->asyncflags & ASYNC_CLOSING) && 		    !(ch->asyncflags & ASYNC_CALLOUT_ACTIVE) &&			  (do_clocal || (ch->imodem & ch->dcd)))			break;		if (signal_pending(current)) 		{			retval = -ERESTARTSYS;			break;		}		/* ---------------------------------------------------------------			Allow someone else to be scheduled.  We will occasionally go			through this loop until one of the above conditions change.			The below schedule call will allow other processes to enter and			prevent this loop from hogging the cpu.		------------------------------------------------------------------ */		schedule();	} /* End forever while  */	current->state = TASK_RUNNING;	remove_wait_queue(&ch->open_wait, &wait);	cli();	if (!tty_hung_up_p(filp))		ch->count++;	restore_flags(flags);	ch->blocked_open--;	if (retval)		return retval;	ch->asyncflags |= ASYNC_NORMAL_ACTIVE;	return 0;} /* End block_til_ready */	/* ------------------ Begin pc_open  ---------------------- */static int pc_open(struct tty_struct *tty, struct file * filp){ /* Begin pc_open */	struct channel *ch;	unsigned long flags;	int line, retval, boardnum;	volatile struct board_chan *bc;	volatile unsigned int head;	/* Nothing "real" happens in open of control device */	if (tty->driver.subtype == SERIAL_TYPE_INFO) 	{		return (0) ;	}	line = MINOR(tty->device) - tty->driver.minor_start;	if (line < 0 || line >= nbdevs) 	{		printk(KERN_ERR "<Error> - pc_open : line out of range in pc_open\n");		tty->driver_data = NULL;		return(-ENODEV);	}	MOD_INC_USE_COUNT;	ch = &digi_channels[line];	boardnum = ch->boardnum;	/* Check status of board configured in system.  */	/* -----------------------------------------------------------------		I check to see if the epca_setup routine detected an user error.  		It might be better to put this in pc_init, but for the moment it		goes here.	---------------------------------------------------------------------- */	if (invalid_lilo_config)	{		if (setup_error_code & INVALID_BOARD_TYPE)			printk(KERN_ERR "<Error> - pc_open: Invalid board type specified in LILO command\n");		if (setup_error_code & INVALID_NUM_PORTS)			printk(KERN_ERR "<Error> - pc_open: Invalid number of ports specified in LILO command\n");		if (setup_error_code & INVALID_MEM_BASE)			printk(KERN_ERR "<Error> - pc_open: Invalid board memory address specified in LILO command\n");		if (setup_error_code & INVALID_PORT_BASE)			printk(KERN_ERR "<Error> - pc_open: Invalid board port address specified in LILO command\n");		if (setup_error_code & INVALID_BOARD_STATUS)			printk(KERN_ERR "<Error> - pc_open: Invalid board status specified in LILO command\n");		if (setup_error_code & INVALID_ALTPIN)			printk(KERN_ERR "<Error> - pc_open: Invalid board altpin specified in LILO command\n");		tty->driver_data = NULL;   /* Mark this device as 'down' */		return(-ENODEV);	}	if ((boardnum >= num_cards) || (boards[boardnum].status == DISABLED)) 	{		tty->driver_data = NULL;   /* Mark this device as 'down' */		return(-ENODEV);	}		if (( bc = ch->brdchan) == 0) 	{		tty->driver_data = NULL;		return(-ENODEV);	}	/* ------------------------------------------------------------------		Every time a channel is opened, increment a counter.  This is 		necessary because we do not wish to flush and shutdown the channel		until the last app holding the channel open, closes it.	 		--------------------------------------------------------------------- */	ch->count++;	/* ----------------------------------------------------------------		Set a kernel structures pointer to our local channel 		structure.  This way we can get to it when passed only		a tty struct.	------------------------------------------------------------------ */	tty->driver_data = ch;		/* ----------------------------------------------------------------		If this is the first time the channel has been opened, initialize		the tty->termios struct otherwise let pc_close handle it.	-------------------------------------------------------------------- */	/* Should this be here except for SPLIT termios ? */	if (ch->count == 1) 	{		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = ch->normal_termios;		else 			*tty->termios = ch->callout_termios;	}	ch->session = current->session;	ch->pgrp = current->pgrp;	save_flags(flags);	cli();	globalwinon(ch);	ch->statusflags = 0;	/* Save boards current modem status */	ch->imodem = bc->mstat;	/* ----------------------------------------------------------------	   Set receive head and tail ptrs to each other.  This indicates	   no data available to read.	----------------------------------------------------------------- */	head = bc->rin;	bc->rout = head;	/* Set the channels associated tty structure */	ch->tty = tty;	/* -----------------------------------------------------------------		The below routine generally sets up parity, baud, flow control 		issues, etc.... It effect both control flags and input flags.	-------------------------------------------------------------------- */	epcaparam(tty,ch);	ch->asyncflags |= ASYNC_INITIALIZED;	memoff(ch);	restore_flags(flags);	retval = block_til_ready(tty, filp, ch);	if (retval)	{		return retval;	}	/* -------------------------------------------------------------		Set this again in case a hangup set it to zero while this 		open() was waiting for the line...	--------------------------------------------------------------- */	ch->tty = tty;	save_flags(flags);	cli();	globalwinon(ch);	/* Enable Digi Data events */	bc->idata = 1;	memoff(ch);	restore_flags(flags);	return 0;} /* End pc_open */#ifdef MODULE/* -------------------- Begin init_module ---------------------- */int __init init_module(){ /* Begin init_module */	unsigned long	flags;	save_flags(flags);	cli();	pc_init();	restore_flags(flags);	return(0);} /* End init_module */#endif#ifdef ENABLE_PCIstatic struct pci_driver epca_driver;#endif#ifdef MODULE/* -------------------- Begin cleanup_module  ---------------------- */void cleanup_module(){ /* Begin cleanup_module */	int               count, crd;	struct board_info *bd;	struct channel    *ch;	unsigned long     flags;	del_timer_sync(&epca_timer);	save_flags(flags);	cli();	if ((tty_unregister_driver(&pc_driver)) ||  	    (tty_unregister_driver(&pc_callout)) ||	    (tty_unregister_driver(&pc_info)))	{		printk(KERN_WARNING "<Error> - DIGI : cleanup_module failed to un-register tty driver\n");		restore_flags(flags);		return;	}	for (crd = 0; crd < num_cards; crd++) 	{ /* Begin for each card */		bd = &boards[crd];		if (!bd)		{ /* Begin sanity check */			printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");			return;		} /* End sanity check */		ch = card_ptr[crd]; 		for (count = 0; count < bd->numports; count++, ch++) 		{ /* Begin for each port */			if (ch) 			{				if (ch->tty)					tty_hangup(ch->tty);				kfree(ch->tmp_buf);			}		} /* End for each port */	} /* End for each card */#ifdef ENABLE_PCI	pci_unregister_driver (&epca_driver);#endif	restore_flags(flags);} /* End cleanup_module */#endif /* MODULE *//* ------------------ Begin pc_init  ---------------------- */int __init pc_init(void){ /* Begin pc_init */	/* ----------------------------------------------------------------		pc_init is called by the operating system during boot up prior to		any open calls being made.  In the older versions of Linux (Prior		to 2.0.0) an entry is made into tty_io.c.  A pointer to the last		memory location (from kernel space) used (kmem_start) is passed		to pc_init.  It is pc_inits responsibility to modify this value 		for any memory that the Digi driver might need and then return		this value to the operating system.  For example if the driver		wishes to allocate 1K of kernel memory, pc_init would return 		(kmem_start + 1024).  This memory (Between kmem_start and kmem_start		+ 1024) would then be available for use exclusively by the driver.  		In this case our driver does not allocate any of this kernel 		memory.	------------------------------------------------------------------*/	ulong flags;	int crd;	struct board_info *bd;	unsigned char board_id = 0;	#ifdef ENABLE_PCI	int pci_boards_found, pci_count;	pci_count = 0;#endif /* ENABLE_PCI */	/* -----------------------------------------------------------------------		If epca_setup has not been ran by LILO set num_cards to defaults; copy		board structure defined by digiConfig into drivers board structure.		Note : If LILO has ran epca_setup then epca_setup will handle defining		num_cards as well as copying the data into the board structure.	-------------------------------------------------------------------------- */	if (!liloconfig)	{ /* Begin driver has been configured via. epcaconfig */		nbdevs = NBDEVS;		num_cards = NUMCARDS;		memcpy((void *)&boards, (void *)&static_boards,		       (sizeof(struct board_info) * NUMCARDS));	} /* End driver has been configured via. epcaconfig */	/* -----------------------------------------------------------------		Note : If lilo was used to configure the driver and the 		ignore epcaconfig option was choosen (digiepca=2) then 		nbdevs and num_cards will equal 0 at this point.  This is		okay; PCI cards will still be picked up if detected.	--------------------------------------------------------------------- */	/*  -----------------------------------------------------------		Set up interrupt, we will worry about memory allocation in		post_fep_init. 	--------------------------------------------------------------- */	printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION);#ifdef ENABLE_PCI	/* ------------------------------------------------------------------		NOTE : This code assumes that the number of ports found in 		       the boards array is correct.  This could be wrong if		       the card in question is PCI (And therefore has no ports 		       entry in the boards structure.)  The rest of the 		       information will be valid for PCI because the beginning		       of pc_init scans for PCI and determines i/o and base		       memory addresses.  I am not sure if it is possible to 		       read the number of ports supported by the card prior to		       it being booted (Since that is the state it is in when 		       pc_init is run).  Because it is not possible to query the		       number of supported ports until after the card has booted;		       we are required to calculate the card_ptrs as the card is	 		       is initialized (Inside post_fep_init).  The negative thing		       about this approach is that digiDload's call to GET_INFO		       will have a bad port value.  (Since this is called prior		       to post_fep_init.)	--------------------------------------------------------------------- */  	pci_boards_found = 0;	if (pci_present())	{		if(num_cards < MAXBOARDS)			pci_boards_found += init_PCI();		num_cards += pci_boards_found;	}	else 	{		printk(KERN_ERR "<Error> - No PCI BIOS found\n");	}#endif /* ENABLE_PCI */	memset(&pc_driver, 0, sizeof(struct tty_driver));	memset(&pc_callout, 0, sizeof(struct tty_driver));	memset(&pc_info, 0, sizeof(struct tty_driver));	pc_driver.magic = TTY_DRIVER_MAGIC;	pc_driver.name = "ttyD"; 	pc_driver.major = DIGI_MAJOR; 	pc_driver.minor_start = 0;	pc_driver.num = MAX_ALLOC;	pc_driver.type = TTY_DRIVER_TYPE_SERIAL;	pc_driver.subtype = SERIAL_TYPE_NORMAL;	pc_driver.init_termios = tty_std_termios;	pc_driver.init_termios.c_iflag = 0;	pc_driver.init_termios.c_oflag = 0;	pc_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;	pc_driver.init_termios.c_lflag = 0;	pc_driver.flags = TTY_DRIVER_REAL_RAW;	pc_driver.refcount = &pc_refcount;	pc_driver.table = pc_table;		/* pc_termios is an array of pointers pointing at termios structs */	/* The below should get the first pointer */	pc_driver.termios = pc_termios;	pc_driver.termios_locked = pc_termios_locked;

⌨️ 快捷键说明

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