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

📄 zs.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
	struct dec_serial **pp;	int i, n, n_chips = 0, n_channels, chip, channel;	/*	 * did we get here by accident?	 */	if(!IOASIC) {		printk("Not on JUNKIO machine, skipping probe_sccs\n");		return;	}		/*	 * When serial console is activated, tc_init has not been called yet	 * and system_base is undefined. Unfortunately we have to hardcode	 * system_base for this case :-(. HK	 */	switch(mips_machtype) {	case MACH_DS5000_2X0:		system_base = 0xbf800000;		n_chips = 2;		break;	case MACH_DS5000_1XX:		system_base = 0xbc000000;		n_chips = 2;		break;	case MACH_DS5000_XX:		system_base = 0xbc000000;		n_chips = 1;		break;	}	pp = &zs_chain;	n_channels = 0;	for (chip = 0; chip < n_chips; chip++) {		for (channel = 0; channel <= 1; channel++) {			/*			 * The sccs reside on the high byte of the 16 bit IOBUS			 */			zs_channels[n_channels].control = (volatile unsigned char *)				system_base + (0 == chip ? SCC0 : SCC1) + (0 == channel ? 1 : 9);			zs_channels[n_channels].data = zs_channels[n_channels].control + 4;			zs_soft[n_channels].zs_channel = &zs_channels[n_channels];			zs_soft[n_channels].irq = SERIAL;			if (0 == channel)				zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels+1];			else				zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels];			*pp = &zs_soft[n_channels];			pp = &zs_soft[n_channels].zs_next;			n_channels++;		}	}	*pp = 0;	zs_channels_found = n_channels;	for (n = 0; n < zs_channels_found; n++) {		for (i = 0; i < 16; i++) {			zs_soft[n].zs_channel->curregs[i] = zs_init_regs[i];		}	}/*	save_and_cli(flags);	for (n = 0; n < zs_channels_found; n++) {		if (((int)zs_channels[n].control & 0xf) == 1) {			write_zsreg(zs_soft[channel].zs_chan_a, R9, FHWRES);			udelay(10000);			write_zsreg(zs_soft[channel].zs_chan_a, R9, 0);		}		load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs);	} 	restore_flags(flags); */}/* zs_init inits the driver */int __init zs_init(void){	int channel, i;	unsigned long flags;	struct dec_serial *info;	if(!IOASIC)		return -ENODEV;	/* Setup base handler, and timer table. */	init_bh(SERIAL_BH, do_serial_bh);	/* Find out how many Z8530 SCCs we have */	if (zs_chain == 0)		probe_sccs();	show_serial_version();	/* Initialize the tty_driver structure */	/* Not all of this is exactly right for us. */	memset(&serial_driver, 0, sizeof(struct tty_driver));	serial_driver.magic = TTY_DRIVER_MAGIC;	serial_driver.name = "ttyS";	serial_driver.major = TTY_MAJOR;	serial_driver.minor_start = 64;	serial_driver.num = zs_channels_found;	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 = &serial_refcount;	serial_driver.table = serial_table;	serial_driver.termios = serial_termios;	serial_driver.termios_locked = serial_termios_locked;	serial_driver.open = rs_open;	serial_driver.close = rs_close;	serial_driver.write = rs_write;	serial_driver.flush_chars = rs_flush_chars;	serial_driver.write_room = rs_write_room;	serial_driver.chars_in_buffer = rs_chars_in_buffer;	serial_driver.flush_buffer = rs_flush_buffer;	serial_driver.ioctl = rs_ioctl;	serial_driver.throttle = rs_throttle;	serial_driver.unthrottle = rs_unthrottle;	serial_driver.set_termios = rs_set_termios;	serial_driver.stop = rs_stop;	serial_driver.start = rs_start;	serial_driver.hangup = rs_hangup;	serial_driver.break_ctl = rs_break;	serial_driver.wait_until_sent = rs_wait_until_sent;	/*	 * The callout device is just like normal device except for	 * major number and the subtype code.	 */	callout_driver = serial_driver;	callout_driver.name = "cua";	callout_driver.major = TTYAUX_MAJOR;	callout_driver.subtype = SERIAL_TYPE_CALLOUT;	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");	save_flags(flags); cli();	for (channel = 0; channel < zs_channels_found; ++channel) {#ifdef CONFIG_KGDB		if (zs_soft[channel].kgdb_channel) {			continue;		}#endif		zs_soft[channel].clk_divisor = 16;		zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);		if (request_irq(SERIAL, rs_interrupt, SA_SHIRQ,				"SCC", &zs_soft[channel]))			printk(KERN_ERR "decserial: can't get irq %d\n",			       SERIAL);		/* If console serial line, then enable interrupts. *//*		if (zs_soft[channel].is_cons) {			write_zsreg(zs_soft[channel].zs_channel, R1,				    (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB));			write_zsreg(zs_soft[channel].zs_channel, R9,				    (VIS | MIE));		}*/	}	for (info = zs_chain, i = 0; info; info = info->zs_next, i++)	{#ifdef CONFIG_KGDB		if (info->kgdb_channel) {			continue;		}#endif		info->magic = SERIAL_MAGIC;		info->port = (int) info->zs_channel->control;		info->line = i;		info->tty = 0;		info->custom_divisor = 16;		info->close_delay = 50;		info->closing_wait = 3000;		info->x_char = 0;		info->event = 0;		info->count = 0;		info->blocked_open = 0;		info->tqueue.routine = do_softint;		info->tqueue.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);		printk("tty%02d at 0x%08x (irq = %d)", info->line, 		       info->port, info->irq);		printk(" is a Z85C30 SCC\n");	}	restore_flags(flags);	return 0;}/* * register_serial and unregister_serial allows for serial ports to be * configured at run-time, to support PCMCIA modems. *//* PowerMac: Unused at this time, just here to make things link. */int register_serial(struct serial_struct *req){	return -1;}void unregister_serial(int line){	return;}/* * ------------------------------------------------------------ * Serial console driver * ------------------------------------------------------------ */#ifdef CONFIG_SERIAL_CONSOLE/* *	Print a string to the serial port trying not to disturb *	any possible real use of the port... *//* This is for console output */static voidzs_console_putchar(struct dec_serial *info, char ch){	int loops = 10000;	unsigned long flags;	if(!info->zs_channel)		return;	save_flags(flags); cli();	while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops)		RECOVERY_DELAY;	*(info->zs_channel->data) = ch;	wbflush(); RECOVERY_DELAY;	restore_flags(flags);}static void serial_console_write(struct console *co, const char *s,				 unsigned count){	struct dec_serial *info;	int i;	info = zs_soft + co->index;#if 0	/*	 * disable master interrupt if necessary	 */	nine = info->zs_channel->curregs[9];	if(nine & MIE)		write_zsreg(info->zs_channel, R9, nine & ~MIE);#endif	/*	 * do it	 */	for (i = 0; i < count; i++, s++) {		if(*s == '\n')			zs_console_putchar(info, '\r');		zs_console_putchar(info, *s);	}	/*	 * restore master interrupt enable	 */#if 0	write_zsreg(info->zs_channel, R9, nine);#endif}/* *	Receive character from the serial port */static int serial_console_wait_key(struct console *co){	return 0;}static kdev_t serial_console_device(struct console *c){	return MKDEV(TTY_MAJOR, 64 + c->index);}/* *	Setup initial baud/bits/parity. We do two things here: *	- construct a cflag setting for the first rs_open() *	- initialize the serial port *	Return non-zero if we didn't find a serial port. */static int __init serial_console_setup(struct console *co, char *options){	struct dec_serial *info;	int	baud = 9600;	int	bits = 8;	int	parity = 'n';	int	cflag = CREAD | HUPCL | CLOCAL;	char	*s;	unsigned long flags;	if(!IOASIC)		return -ENODEV;	info = zs_soft + co->index;	if (zs_chain == 0)		probe_sccs();	info->is_cons = 1;	if (options) {		baud = simple_strtoul(options, NULL, 10);		s = options;		while(*s >= '0' && *s <= '9')			s++;		if (*s)			parity = *s++;		if (*s)			bits   = *s - '0';	}	/*	 *	Now construct a cflag setting.	 */	switch(baud) {	case 1200:		cflag |= B1200;		break;	case 2400:		cflag |= B2400;		break;	case 4800:		cflag |= B4800;		break;	case 19200:		cflag |= B19200;		break;	case 38400:		cflag |= B38400;		break;	case 57600:		cflag |= B57600;		break;	case 115200:		cflag |= B115200;		break;	case 9600:	default:		cflag |= B9600;		break;	}	switch(bits) {	case 7:		cflag |= CS7;		break;	default:	case 8:		cflag |= CS8;		break;	}	switch(parity) {	case 'o': case 'O':		cflag |= PARODD;		break;	case 'e': case 'E':		cflag |= PARENB;		break;	}	co->cflag = cflag;#if 1 	save_and_cli(flags);	/*	 * Turn on RTS and DTR.	 */	zs_rtsdtr(info, 1);	/*	 * Finally, enable sequencing	 */	info->zs_channel->curregs[3] |= (RxENABLE | Rx8);	info->zs_channel->curregs[5] |= (TxENAB | Tx8);	info->zs_channel->curregs[9] |= (VIS);	write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);	write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);	write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);	/*	 * Clear the interrupt registers.	 */	write_zsreg(info->zs_channel, 0, ERR_RES);	write_zsreg(info->zs_channel, 0, RES_H_IUS);	/*	 * Set the speed of the serial port	 */	change_speed(info);	/* Save the current value of RR0 */	info->read_reg_zero = read_zsreg(info->zs_channel, 0);	zs_soft[co->index].clk_divisor = 16;	zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]);	restore_flags(flags);#endif	return 0;}static struct console sercons = {	name:		"ttyS",	write:		serial_console_write,	device:		serial_console_device,	wait_key:	serial_console_wait_key,	setup:		serial_console_setup,	flags:		CON_PRINTBUFFER,	index:		-1,};/* *	Register console. */void __init zs_serial_console_init(void){	register_console(&sercons);}#endif /* ifdef CONFIG_SERIAL_CONSOLE */#ifdef CONFIG_KGDB/* These are for receiving and sending characters under the kgdb * source level kernel debugger. */void putDebugChar(char kgdb_char){	struct dec_zschannel *chan = zs_kgdbchan;	while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0)		RECOVERY_DELAY;	write_zsdata(chan, kgdb_char);}char getDebugChar(void){	struct dec_zschannel *chan = zs_kgdbchan;	while((read_zsreg(chan, 0) & Rx_CH_AV) == 0)		eieio(); /*barrier();*/	return read_zsdata(chan);}void kgdb_interruptible(int yes){	struct dec_zschannel *chan = zs_kgdbchan;	int one, nine;	nine = read_zsreg(chan, 9);	if (yes == 1) {		one = EXT_INT_ENAB|INT_ALL_Rx;		nine |= MIE;		printk("turning serial ints on\n");	} else {		one = RxINT_DISAB;		nine &= ~MIE;		printk("turning serial ints off\n");	}	write_zsreg(chan, 1, one);	write_zsreg(chan, 9, nine);}/* This sets up the serial port we're using, and turns on * interrupts for that channel, so kgdb is usable once we're done. */static inline void kgdb_chaninit(struct dec_zschannel *ms, int intson, int bps){	int brg;	int i, x;	volatile char *sccc = ms->control;	brg = BPS_TO_BRG(bps, ZS_CLOCK/16);	printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg);	for (i = 20000; i != 0; --i) {		x = *sccc; eieio();	}	for (i = 0; i < sizeof(scc_inittab); ++i) {		write_zsreg(ms, scc_inittab[i], scc_inittab[i+1]);		i++;	}}/* This is called at boot time to prime the kgdb serial debugging * serial line.  The 'tty_num' argument is 0 for /dev/ttya and 1 * for /dev/ttyb which is determined in setup_arch() from the * boot command line flags. */void __init zs_kgdb_hook(int tty_num){	/* Find out how many Z8530 SCCs we have */	if (zs_chain == 0)		probe_sccs();	zs_soft[tty_num].zs_channel = &zs_channels[tty_num];	zs_kgdbchan = zs_soft[tty_num].zs_channel;	zs_soft[tty_num].change_needed = 0;	zs_soft[tty_num].clk_divisor = 16;	zs_soft[tty_num].zs_baud = 38400;	zs_soft[tty_num].kgdb_channel = 1;     /* This runs kgdb */	zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */	/* Turn on transmitter/receiver at 8-bits/char */        kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400);	printk("KGDB: on channel %d initialized\n", tty_num);	set_debug_traps(); /* init stub */}#endif /* ifdef CONFIG_KGDB */

⌨️ 快捷键说明

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