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

📄 sab82532.c

📁 移植到2410开发板上的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef SERIAL_DEBUG_OPEN	printk("sab82532_open %s%d, count = %d\n", tty->driver.name, info->line,	       info->count);#endif	if (!tmp_buf) {		page = get_free_page(GFP_KERNEL);		if (!page)			return -ENOMEM;		if (tmp_buf)			free_page(page);		else			tmp_buf = (unsigned char *) page;	}	info->count++;	tty->driver_data = info;	info->tty = tty;	/*	 * If the port is in the middle of closing, bail out now.	 */	if (tty_hung_up_p(filp) ||	    (info->flags & ASYNC_CLOSING)) {		if (info->flags & ASYNC_CLOSING)			interruptible_sleep_on(&info->close_wait);#ifdef SERIAL_DO_RESTART		return ((info->flags & ASYNC_HUP_NOTIFY) ?			-EAGAIN : -ERESTARTSYS);#else		return -EAGAIN;#endif	}	/*	 * Start up serial port	 */	retval = startup(info);	if (retval)		return retval;	MOD_INC_USE_COUNT;	retval = block_til_ready(tty, filp, info);	if (retval) {#ifdef SERIAL_DEBUG_OPEN		printk("sab82532_open returning after block_til_ready with %d\n",		       retval);#endif		return retval;	}	if ((info->count == 1) &&	    (info->flags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = info->normal_termios;		else 			*tty->termios = info->callout_termios;		change_speed(info);	}#ifdef CONFIG_SERIAL_CONSOLE	if (sab82532_console.cflag && sab82532_console.index == line) {		tty->termios->c_cflag = sab82532_console.cflag;		sab82532_console.cflag = 0;		change_speed(info);	}#endif	info->session = current->session;	info->pgrp = current->pgrp;#ifdef SERIAL_DEBUG_OPEN	printk("sab82532_open ttys%d successful... count %d", info->line, info->count);#endif	return 0;}/* * /proc fs routines.... */static __inline__ intline_info(char *buf, struct sab82532 *info){	unsigned long flags;	char stat_buf[30];	int ret;	ret = sprintf(buf, "%u: uart:SAB82532 ", info->line);	switch (info->type) {		case 0:			ret += sprintf(buf+ret, "V1.0 ");			break;		case 1:			ret += sprintf(buf+ret, "V2.0 ");			break;		case 2:			ret += sprintf(buf+ret, "V3.2 ");			break;		default:			ret += sprintf(buf+ret, "V?.? ");			break;	}	ret += sprintf(buf+ret, "port:%lX irq:%s",		       (unsigned long)info->regs, __irq_itoa(info->irq));	if (!info->regs) {		ret += sprintf(buf+ret, "\n");		return ret;	}	/*	 * Figure out the current RS-232 lines	 */	stat_buf[0] = 0;	stat_buf[1] = 0;	save_flags(flags); cli();	if (readb(&info->regs->r.mode) & SAB82532_MODE_RTS) {		if (!(readb(&info->regs->r.mode) & SAB82532_MODE_FRTS))			strcat(stat_buf, "|RTS");	} else {		strcat(stat_buf, "|RTS");	}	if (readb(&info->regs->r.star) & SAB82532_STAR_CTS)		strcat(stat_buf, "|CTS");	if (!(readb(&info->regs->r.pvr) & info->pvr_dtr_bit))		strcat(stat_buf, "|DTR");	if (!(readb(&info->regs->r.pvr) & info->pvr_dsr_bit))		strcat(stat_buf, "|DSR");	if (!(readb(&info->regs->r.vstr) & SAB82532_VSTR_CD))		strcat(stat_buf, "|CD");	restore_flags(flags);	if (info->baud)		ret += sprintf(buf+ret, " baud:%u", info->baud);	ret += sprintf(buf+ret, " tx:%u rx:%u",		       info->icount.tx, info->icount.rx);	if (info->icount.frame)		ret += sprintf(buf+ret, " fe:%u", info->icount.frame);	if (info->icount.parity)		ret += sprintf(buf+ret, " pe:%u", info->icount.parity);	if (info->icount.brk)		ret += sprintf(buf+ret, " brk:%u", info->icount.brk);	if (info->icount.overrun)		ret += sprintf(buf+ret, " oe:%u", info->icount.overrun);	/*	 * Last thing is the RS-232 status lines.	 */	ret += sprintf(buf+ret, " %s\n", stat_buf + 1);	return ret;}int sab82532_read_proc(char *page, char **start, off_t off, int count,		       int *eof, void *data){	struct sab82532 *info = sab82532_chain;	off_t begin = 0;	int len = 0;	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);	for (info = sab82532_chain; info && len < 4000; info = info->next) {		len += line_info(page + len, info);		if (len+begin > off+count)			goto done;		if (len+begin < off) {			begin += len;			len = 0;		}	}	*eof = 1;done:	if (off >= len+begin)		return 0;	*start = page + (off-begin);	return ((count < begin+len-off) ? count : begin+len-off);}/* * --------------------------------------------------------------------- * sab82532_init() and friends * * sab82532_init() is called at boot-time to initialize the serial driver. * --------------------------------------------------------------------- */static int __init get_sab82532(unsigned long *memory_start){	struct linux_ebus *ebus;	struct linux_ebus_device *edev = 0;	struct sab82532 *sab;	unsigned long regs, offset;	int i;	for_each_ebus(ebus) {		for_each_ebusdev(edev, ebus) {			if (!strcmp(edev->prom_name, "se"))				goto ebus_done;			if (!strcmp(edev->prom_name, "serial")) {				char compat[32];				int clen;				/* On RIO this can be an SE, check it.  We could				 * just check ebus->is_rio, but this is more portable.				 */				clen = prom_getproperty(edev->prom_node, "compatible",							compat, sizeof(compat));				if (clen > 0) {					if (strncmp(compat, "sab82532", 8) == 0) {						/* Yep. */						goto ebus_done;					}				}			}		}	}ebus_done:	if (!edev)		return -ENODEV;	regs = edev->resource[0].start;	offset = sizeof(union sab82532_async_regs);	for (i = 0; i < 2; i++) {		if (memory_start) {			*memory_start = (*memory_start + 7) & ~(7);			sab = (struct sab82532 *)*memory_start;			*memory_start += sizeof(struct sab82532);		} else {			sab = (struct sab82532 *)kmalloc(sizeof(struct sab82532),							 GFP_KERNEL);			if (!sab) {				printk("sab82532: can't alloc sab struct\n");				break;			}		}		memset(sab, 0, sizeof(struct sab82532));		sab->regs = ioremap(regs + offset, sizeof(union sab82532_async_regs));		sab->irq = edev->irqs[0];		sab->line = 1 - i;		sab->xmit_fifo_size = 32;		sab->recv_fifo_size = 32;		writeb(SAB82532_IPC_IC_ACT_LOW, &sab->regs->w.ipc);		sab->next = sab82532_chain;		sab82532_chain = sab;		offset -= sizeof(union sab82532_async_regs);	}	return 0;}#ifndef MODULEstatic void __init sab82532_kgdb_hook(int line){	prom_printf("sab82532: kgdb support is not implemented, yet\n");	prom_halt();}#endifstatic inline void __init show_serial_version(void){	char *revision = "$Revision: 1.65 $";	char *version, *p;	version = strchr(revision, ' ');	strcpy(serial_version, ++version);	p = strchr(serial_version, ' ');	*p = '\0';	printk("SAB82532 serial driver version %s\n", serial_version);}extern int su_num_ports;/* * The serial driver boot-time initialization code! */int __init sab82532_init(void){	struct sab82532 *info;	int i;	if (!sab82532_chain)		get_sab82532(0);	if (!sab82532_chain)		return -ENODEV;	init_bh(SERIAL_BH, do_serial_bh);	show_serial_version();	/* Initialize the tty_driver structure */	memset(&serial_driver, 0, sizeof(struct tty_driver));	serial_driver.magic = TTY_DRIVER_MAGIC;	serial_driver.driver_name = "serial";#ifdef CONFIG_DEVFS_FS	serial_driver.name = "tts/%d";#else	serial_driver.name = "ttyS";#endif	serial_driver.major = TTY_MAJOR;	serial_driver.minor_start = 64 + su_num_ports;	serial_driver.num = NR_PORTS;	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;	serial_driver.subtype = SERIAL_TYPE_NORMAL;	serial_driver.init_termios = tty_std_termios;	serial_driver.init_termios.c_cflag =		B9600 | CS8 | CREAD | HUPCL | CLOCAL;	serial_driver.flags = TTY_DRIVER_REAL_RAW;	serial_driver.refcount = &sab82532_refcount;	serial_driver.table = sab82532_table;	serial_driver.termios = sab82532_termios;	serial_driver.termios_locked = sab82532_termios_locked;	serial_driver.open = sab82532_open;	serial_driver.close = sab82532_close;	serial_driver.write = sab82532_write;	serial_driver.put_char = sab82532_put_char;	serial_driver.flush_chars = sab82532_flush_chars;	serial_driver.write_room = sab82532_write_room;	serial_driver.chars_in_buffer = sab82532_chars_in_buffer;	serial_driver.flush_buffer = sab82532_flush_buffer;	serial_driver.ioctl = sab82532_ioctl;	serial_driver.throttle = sab82532_throttle;	serial_driver.unthrottle = sab82532_unthrottle;	serial_driver.send_xchar = sab82532_send_xchar;	serial_driver.set_termios = sab82532_set_termios;	serial_driver.stop = sab82532_stop;	serial_driver.start = sab82532_start;	serial_driver.hangup = sab82532_hangup;	serial_driver.break_ctl = sab82532_break;	serial_driver.wait_until_sent = sab82532_wait_until_sent;	serial_driver.read_proc = sab82532_read_proc;	/*	 * The callout device is just like normal device except for	 * major number and the subtype code.	 */	callout_driver = serial_driver;#ifdef CONFIG_DEVFS_FS	callout_driver.name = "cua/%d";#else	callout_driver.name = "cua";#endif	callout_driver.major = TTYAUX_MAJOR;	callout_driver.subtype = SERIAL_TYPE_CALLOUT;	callout_driver.read_proc = 0;	callout_driver.proc_entry = 0;	if (tty_register_driver(&serial_driver))		panic("Couldn't register serial driver\n");	if (tty_register_driver(&callout_driver))		panic("Couldn't register callout driver\n");	for (info = sab82532_chain, i = 0; info; info = info->next, i++) {		info->magic = SERIAL_MAGIC;		info->type = readb(&info->regs->r.vstr) & 0x0f;		writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &info->regs->w.pcr);		writeb(0xff, &info->regs->w.pim);		if (info->line == 0) {			info->pvr_dsr_bit = (1 << 0);			info->pvr_dtr_bit = (1 << 1);		} else {			info->pvr_dsr_bit = (1 << 3);			info->pvr_dtr_bit = (1 << 2);		}		writeb((1 << 1) | (1 << 2) | (1 << 4), &info->regs->w.pvr);		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);		info->custom_divisor = 16;		info->close_delay = 5*HZ/10;		info->closing_wait = 30*HZ;		info->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;		info->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;		info->x_char = 0;		info->event = 0;			info->blocked_open = 0;		info->tqueue.routine = do_softint;		info->tqueue.data = info;		info->tqueue_hangup.routine = do_serial_hangup;		info->tqueue_hangup.data = info;		info->callout_termios = callout_driver.init_termios;		info->normal_termios = serial_driver.init_termios;		init_waitqueue_head(&info->open_wait);		init_waitqueue_head(&info->close_wait);		init_waitqueue_head(&info->delta_msr_wait);		info->icount.cts = info->icount.dsr = 			info->icount.rng = info->icount.dcd = 0;		info->icount.rx = info->icount.tx = 0;		info->icount.frame = info->icount.parity = 0;		info->icount.overrun = info->icount.brk = 0;		if (!(info->line & 0x01)) {			if (request_irq(info->irq, sab82532_interrupt, SA_SHIRQ,					"serial(sab82532)", info)) {				printk("sab82532: can't get IRQ %x\n",				       info->irq);				panic("sab82532 initialization failed");			}		}			printk(KERN_INFO		       "ttyS%02d at 0x%lx (irq = %s) is a SAB82532 %s\n",		       info->line + su_num_ports, (unsigned long)info->regs,		       __irq_itoa(info->irq), sab82532_version[info->type]);	}#ifdef SERIAL_LOG_DEVICE	dprint_init(SERIAL_LOG_DEVICE);#endif	return 0;}int __init sab82532_probe(void){	int node, enode, snode;	char model[32];	int len;        node = prom_getchild(prom_root_node);	node = prom_searchsiblings(node, "pci");	/*	 * Check for SUNW,sabre on Ultra 5/10/AXi.	 */	len = prom_getproperty(node, "model", model, sizeof(model));	if ((len > 0) && !strncmp(model, "SUNW,sabre", len)) {        	node = prom_getchild(node);		node = prom_searchsiblings(node, "pci");	}	/*	 * For each PCI bus...	 */	while (node) {		enode = prom_getchild(node);		enode = prom_searchsiblings(enode, "ebus");		/*		 * For each EBus on this PCI...		 */		while (enode) {			int child;			child = prom_getchild(enode);			snode = prom_searchsiblings(child, "se");			if (snode)				goto found;			snode = prom_searchsiblings(child, "serial");			if (snode) {				char compat[32];				int clen;				clen = prom_getproperty(snode, "compatible",							compat, sizeof(compat));				if (clen > 0) {					if (strncmp(compat, "sab82532", 8) == 0)						goto found;				}			}			enode = prom_getsibling(enode);			enode = prom_searchsiblings(enode, "ebus");		}		node = prom_getsibling(node);		node = prom_searchsiblings(node, "pci");	}	return -ENODEV;found:#i

⌨️ 快捷键说明

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