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

📄 sab82532.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	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;		}	}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.54 $";	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) {			snode = prom_getchild(enode);			snode = prom_searchsiblings(snode, "se");			if (snode)				goto found;			enode = prom_getsibling(enode);			enode = prom_searchsiblings(enode, "ebus");		}		node = prom_getsibling(node);		node = prom_searchsiblings(node, "pci");	}	return -ENODEV;found:#ifdef CONFIG_SERIAL_CONSOLE	sunserial_setinitfunc(sab82532_console_init);#endif#ifndef MODULE	sunserial_setinitfunc(sab82532_init);	rs_ops.rs_kgdb_hook = sab82532_kgdb_hook;#endif	return 0;}#ifdef MODULEint init_module(void){	if (get_sab82532(0))		return -ENODEV;	return sab82532_init();}void cleanup_module(void) {	struct sab82532 *sab;	unsigned long flags;	int e1, e2;	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */	save_flags(flags);	cli();        remove_bh(SERIAL_BH);	if ((e1 = tty_unregister_driver(&serial_driver)))		printk("SERIAL: failed to unregister serial driver (%d)\n",		       e1);	if ((e2 = tty_unregister_driver(&callout_driver)))		printk("SERIAL: failed to unregister callout driver (%d)\n", 		       e2);	restore_flags(flags);	if (tmp_buf) {		free_page((unsigned long) tmp_buf);		tmp_buf = NULL;	}	for (sab = sab82532_chain; sab; sab = sab->next) {		if (!(sab->line & 0x01))			free_irq(sab->irq, sab);		iounmap(sab->regs);	}}#endif /* MODULE */#ifdef CONFIG_SERIAL_CONSOLEstatic voidbatten_down_hatches(struct sab82532 *info){	unsigned char saved_rfc, tmp;	if (!stop_a_enabled)		return;	/* If we are doing kadb, we call the debugger	 * else we just drop into the boot monitor.	 * Note that we must flush the user windows	 * first before giving up control.	 */	printk("\n");	flush_user_windows();	/*	 * Set FIFO to single character mode.	 */	saved_rfc = readb(&info->regs->r.rfc);	tmp = readb(&info->regs->rw.rfc);	tmp &= ~(SAB82532_RFC_RFDF);	writeb(tmp, &info->regs->rw.rfc);	sab82532_cec_wait(info);	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);#ifndef __sparc_v9__	if ((((unsigned long)linux_dbvec) >= DEBUG_FIRSTVADDR) &&	    (((unsigned long)linux_dbvec) <= DEBUG_LASTVADDR))		sp_enter_debugger();	else#endif		prom_cmdline();	/*	 * Reset FIFO to character + status mode.	 */	writeb(saved_rfc, &info->regs->w.rfc);	sab82532_cec_wait(info);	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);}static __inline__ voidsab82532_console_putchar(struct sab82532 *info, char c){	unsigned long flags;	save_flags(flags); cli();	sab82532_tec_wait(info);	writeb(c, &info->regs->w.tic);	restore_flags(flags);}static voidsab82532_console_write(struct console *con, const char *s, unsigned n){	struct sab82532 *info;	int i;	info = sab82532_chain;	for (i = con->index; i; i--) {		info = info->next;		if (!info)			return;	}	for (i = 0; i < n; i++) {		if (*s == '\n')			sab82532_console_putchar(info, '\r');		sab82532_console_putchar(info, *s++);	}	sab82532_tec_wait(info);}static intsab82532_console_wait_key(struct console *con)

⌨️ 快捷键说明

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