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

📄 pcxx.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		if(tty->ldisc.num != ldiscs[N_TTY].num) {			if(tty->ldisc.close)				(tty->ldisc.close)(tty);			tty->ldisc = ldiscs[N_TTY];			tty->termios->c_line = N_TTY;			if(tty->ldisc.open)				(tty->ldisc.open)(tty);		}#endif		if(info->blocked_open) {			if(info->close_delay) {				current->state = TASK_INTERRUPTIBLE;				schedule_timeout(info->close_delay);			}			wake_up_interruptible(&info->open_wait);		}		info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|							  ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING);		wake_up_interruptible(&info->close_wait);		MOD_DEC_USE_COUNT;		restore_flags(flags);	}}void pcxe_hangup(struct tty_struct *tty){	struct channel *ch;	if ((ch=chan(tty))!=NULL) {		unsigned long flags;		save_flags(flags);		cli();		shutdown(ch);		ch->event = 0;		ch->count = 0;		ch->tty = NULL;		ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);		wake_up_interruptible(&ch->open_wait);		restore_flags(flags);	}}static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){	struct channel *ch;	volatile struct board_chan *bc;	int total, remain, size, stlen;	unsigned int head, tail;	unsigned long flags;	/* printk("Entering pcxe_write()\n"); */	if ((ch=chan(tty))==NULL)		return 0;	bc = ch->brdchan;	size = ch->txbufsize;	if (from_user) {		save_flags(flags);		cli();		globalwinon(ch);		head = bc->tin & (size - 1);		/* It seems to be necessary to make sure that the value is stable here somehow		   This is a rather odd pice of code here. */		do		{ tail = bc->tout;		} while (tail != bc->tout);				tail &= (size - 1);		stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);		count = MIN(stlen, count);		if (count) {			if (verify_area(VERIFY_READ, (char*)buf, count))				count=0;			else copy_from_user(ch->tmp_buf, buf, count);		}		buf = ch->tmp_buf;		memoff(ch);		restore_flags(flags);	}	/*	 * All data is now local	 */	total = 0;	save_flags(flags);	cli();	globalwinon(ch);	head = bc->tin & (size - 1);	tail = bc->tout;	if (tail != bc->tout)		tail = bc->tout;	tail &= (size - 1);	if (head >= tail) {		remain = size - (head - tail) - 1;		stlen = size - head;	}	else {		remain = tail - head - 1;		stlen = remain;	}	count = MIN(remain, count);	txwinon(ch);	while (count > 0) {		stlen = MIN(count, stlen);		memcpy(ch->txptr + head, buf, stlen);		buf += stlen;		count -= stlen;		total += stlen;		head += stlen;		if (head >= size) {			head = 0;			stlen = tail;		}	}	ch->statusflags |= TXBUSY;	globalwinon(ch);	bc->tin = head;	if ((ch->statusflags & LOWWAIT) == 0) {		ch->statusflags |= LOWWAIT;		bc->ilow = 1;	}	memoff(ch);	restore_flags(flags);	return(total);}static void pcxe_put_char(struct tty_struct *tty, unsigned char c){	pcxe_write(tty, 0, &c, 1);	return;}static int pcxe_write_room(struct tty_struct *tty){	struct channel *ch;	int remain;	remain = 0;	if ((ch=chan(tty))!=NULL) {		volatile struct board_chan *bc;		unsigned int head, tail;		unsigned long flags;		save_flags(flags);		cli();		globalwinon(ch);		bc = ch->brdchan;		head = bc->tin & (ch->txbufsize - 1);		tail = bc->tout;		if (tail != bc->tout)			tail = bc->tout;		tail &= (ch->txbufsize - 1);		if((remain = tail - head - 1) < 0 )			remain += ch->txbufsize;		if (remain && (ch->statusflags & LOWWAIT) == 0) {			ch->statusflags |= LOWWAIT;			bc->ilow = 1;		}		memoff(ch);		restore_flags(flags);	}	return remain;}static int pcxe_chars_in_buffer(struct tty_struct *tty){	int chars;	unsigned int ctail, head, tail;	int remain;	unsigned long flags;	struct channel *ch;	volatile struct board_chan *bc;	if ((ch=chan(tty))==NULL)		return(0);	save_flags(flags);	cli();	globalwinon(ch);	bc = ch->brdchan;	tail = bc->tout;	head = bc->tin;	ctail = ch->mailbox->cout;	if(tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)		chars = 0;	else {		head = bc->tin & (ch->txbufsize - 1);		tail &= (ch->txbufsize - 1);		if((remain = tail - head - 1) < 0 )			remain += ch->txbufsize;		chars = (int)(ch->txbufsize - remain);		/* 		 * Make it possible to wakeup anything waiting for output		 * in tty_ioctl.c, etc.		 */		if(!(ch->statusflags & EMPTYWAIT))			setup_empty_event(tty,ch);	}	memoff(ch);	restore_flags(flags);	return(chars);}static void pcxe_flush_buffer(struct tty_struct *tty){	unsigned int tail;	volatile struct board_chan *bc;	struct channel *ch;	unsigned long flags;	if ((ch=chan(tty))==NULL)		return;	save_flags(flags);	cli();	globalwinon(ch);	bc = ch->brdchan;	tail = bc->tout;	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);	memoff(ch);	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 void pcxe_flush_chars(struct tty_struct *tty){	struct channel * ch;	if ((ch=chan(tty))!=NULL) {		unsigned long flags;		save_flags(flags);		cli();		if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))			setup_empty_event(tty,ch);		restore_flags(flags);	}}#ifndef MODULE/* * Driver setup function when linked into the kernel to optionally parse multible * "digi="-lines and initialize the driver at boot time. No probing. */__initfunc(void pcxx_setup(char *str, int *ints)){	struct board_info board;	int               i, j, last;	char              *temp, *t2;	unsigned          len;	numcards=0;	memset(&board, 0, sizeof(board));	for(last=0,i=1;i<=ints[0];i++)		switch(i)		{			case 1:				board.status = ints[i];				last = i;				break;			case 2:				board.type = ints[i];				last = i;				break;			case 3:				board.altpin = ints[i];				last = i;				break;			case 4:				board.numports = ints[i];				last = i;				break;			case 5:				board.port = ints[i];				last = i;				break;			case 6:				board.membase = ints[i];				last = i;				break;			default:				printk("PC/Xx: Too many integer parms\n");				return;		}	while (str && *str) 	{		/* find the next comma or terminator */		temp = str;		while (*temp && (*temp != ','))			temp++;		if (!*temp)			temp = NULL;		else			*temp++ = 0;		i = last + 1;		switch(i)		{			case 1:				len = strlen(str);				if (strncmp("Disable", str, len) == 0) 					board.status = 0;				else					if (strncmp("Enable", str, len) == 0)						board.status = 1;					else					{						printk("PC/Xx: Invalid status %s\n", str);						return;					}				last = i;				break;			case 2:				for(j=0;j<PCXX_NUM_TYPES;j++)					if (strcmp(board_desc[j], str) == 0)						break;				if (i<PCXX_NUM_TYPES) 					board.type = j;				else				{					printk("PC/Xx: Invalid board name: %s\n", str);					return;				}				last = i;				break;			case 3:				len = strlen(str);				if (strncmp("Disable", str, len) == 0) 					board.altpin = 0;				else					if (strncmp("Enable", str, len) == 0)						board.altpin = 1;					else					{						printk("PC/Xx: Invalid altpin %s\n", str);						return;					}				last = i;				break;			case 4:				t2 = str;				while (isdigit(*t2))					t2++;				if (*t2)				{					printk("PC/Xx: Invalid port count %s\n", str);					return;				}				board.numports = simple_strtoul(str, NULL, 0);				last = i;				break;			case 5:				t2 = str;				while (isxdigit(*t2))					t2++;				if (*t2)				{					printk("PC/Xx: Invalid io port address %s\n", str);					return;				}				board.port = simple_strtoul(str, NULL, 16);				last = i;				break;			case 6:				t2 = str;				while (isxdigit(*t2))					t2++;				if (*t2)				{					printk("PC/Xx: Invalid memory base %s\n", str);					return;				}				board.membase = simple_strtoul(str, NULL, 16);				last = i;				break;			default:				printk("PC/Xx: Too many string parms\n");				return;		}		str = temp;	}	if (last < 6)  	{		printk("PC/Xx: Insufficient parms specified\n");		return;	}         /* I should REALLY validate the stuff here */	memcpy(&boards[numcards],&board, sizeof(board));	printk("PC/Xx: Added board %i, %s %s %i ports at 0x%4.4X base 0x%6.6X\n", 		numcards, board_desc[board.type], board_mem[board.type], 		board.numports, board.port, (unsigned int) board.membase);	/* keep track of my initial minor number */        if (numcards)		boards[numcards].first_minor = boards[numcards-1].first_minor + boards[numcards-1].numports;	else		boards[numcards].first_minor = 0;	/* yeha!  string parameter was successful! */	numcards++;}#endif/* * function to initialize the driver with the given parameters, which are either * the default values from this file or the parameters given at boot. */__initfunc(int pcxe_init(void)){	ulong memory_seg=0, memory_size=0;	int lowwater, enabled_cards=0, i, crd, shrinkmem=0, topwin = 0xff00L, botwin=0x100L;	unchar *fepos, *memaddr, *bios, v;	volatile struct global_data *gd;	volatile struct board_chan *bc;	struct board_info *bd;	struct channel *ch;	printk(KERN_NOTICE "Digiboard PC/X{i,e,eve} driver v%s\n", VERSION);#ifdef MODULE	for (i = 0; i < 4; i++) {		if (io[i]) {			numcards = 0;			break;		}	}	if (numcards == 0) {		int first_minor = 0;		for (i = 0; i < 4; i++) {			if (io[i] == 0) {				boards[i].port    = 0;				boards[i].status  = DISABLED;			}			else {				boards[i].port         = (ushort)io[i];				boards[i].status       = ENABLED;				boards[i].first_minor  = first_minor;				numcards=i+1;			}			if (membase[i])				boards[i].membase = (ulong)membase[i];			else				boards[i].membase = 0xD0000;			if (memsize[i])				boards[i].memsize = (ulong)(memsize[i] * 1024);			else				boards[i].memsize = 0;			if (altpin[i])				boards[i].altpin  = ON;			else				boards[i].altpin  = OFF;			if (numports[i])				boards[i].numports  = (ushort)numports[i];			else				boards[i].numports  = 16;			first_minor += boards[i].numports;		}	}#endif	if (numcards <= 0)	{		printk("PC/Xx: No cards configured, driver not active.\n");		return -EIO;	}#if 1	if (debug)	    for (i = 0; i < numcards; i++) {		    printk("Card %d:status=%d, port=0x%x, membase=0x%lx, memsize=0x%lx, altpin=%d, numports=%d, first_minor=%d\n",			    i+1,			    boards[i].status,			    boards[i].port,			    boards[i].membase,			    boards[i].memsize,			    boards[i].altpin,			    boards[i].numports,			    boards[i].first_minor);	    }#endif	for (i=0;i<numcards;i++)		nbdevs += boards[i].numports;	if (nbdevs <= 0)	{		printk("PC/Xx: No devices activated, driver not active.\n");		return -EIO;	}	/*	 * this turns out to be more memory efficient, as there are no 	 * unused spaces.	 */	digi_channels = kmalloc(sizeof(struct channel) * nbdevs, GFP_KERNEL);	if (!digi_channels)		panic("Unable to allocate digi_channel struct");	memset(digi_channels, 0, sizeof(struct channel) * nbdevs);	pcxe_table =  kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL);	if (!pcxe_table)		panic("Unable to allocate pcxe_table struct");	memset(pcxe_table, 0, sizeof(struct tty_struct *) * nbdevs);	pcxe_termios = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);	if (!pcxe_termios)		panic("Unable to allocate pcxe_termios struct");	memset(pcxe_termios,0,sizeof(struct termios *)*nbdevs);	pcxe_termios_locked = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);	if (!pcxe_termios_locked)		panic("Unable to allocate pcxe_termios_locked struct");	memset(pcxe_termios_locked,0,sizeof(struct termios *)*nbdevs);	init_bh(DIGI_BH,do_pcxe_bh);	enable_bh(DIGI_BH);	timer_table[DIGI_TIMER].fn = pcxxpoll;	timer_table[DIGI_TIMER].expires = 0;	memset(&pcxe_driver, 0, sizeof(struct tty_driver));	pcxe_driver.magic = TTY_DRIVER_MAGIC;	pcxe_driver.name = "ttyD";	pcxe_driver.major = DIGI_MAJOR; 	pcxe_driver.minor_start = 0;	pcxe_driver.num = nbdevs;	pcxe_driver.type = TTY_DRIVER_TYPE_SERIAL;	pcxe_driver.subtype = SERIAL_TYPE_NORMAL;	pcxe_driver.init_termios = tty_std_termios;	pcxe_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;	pcxe_driver.flags = TTY_DRIVER_REAL_RAW;	pcxe_driver.refcount = &pcxe_refcount;	pcxe_driver.table = pcxe_table;	pcxe_driver.termios = pcxe_termios;	pcxe_driver.termios_locked = pcxe_termios_locked;	pcxe_driver.open = pcxe_open;	pcxe_driver.close = pcxe_close;	pcxe_driver.write = pcxe_write;	pcxe_driver.put_char = pcxe_put_char;	pcxe_driver.flush_chars = pcxe_flush_chars;	pcxe_driver.write_room = pcxe_write_room;	pcxe_driver.chars_in_buffer = pcxe_chars_in_buffer;	pcxe_driver.flush_buffer = pcxe_flush_buffer;	pcxe_driver.ioctl = pcxe_ioctl;	pcxe_driver.throttle = pcxe_throttle;	pcxe_driver.unthrottle = pcxe_unthrottle;	pcxe_driver.set_termios = pcxe_set_termios;	pcxe_driver.stop = pcxe_stop;	pcxe_driver.start = pcxe_start;	pcxe_driver.hangup = pcxe_hangup;	pcxe_callout = pcxe_driver;	pcxe_callout.name = "cud";	pcxe_callout.major = DIGICU_MAJOR;	pcxe_callout.subtype = SERIAL_TYPE_CALLOUT;	pcxe_callout.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	for(crd=0; crd < numcards; crd++) {

⌨️ 快捷键说明

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