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

📄 sgiserial.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
	info->flags |= ZILOG_NORMAL_ACTIVE;	return 0;}	/* * This routine is called whenever a serial port is opened.  It * enables interrupts for a serial port, linking in its ZILOG structure into * the IRQ chain.   It also performs the serial-specific * initialization for the tty structure. */int rs_open(struct tty_struct *tty, struct file * filp){	struct sgi_serial	*info;	int 			retval, line;	line = MINOR(tty->device) - tty->driver.minor_start;	/* The zilog lines for the mouse/keyboard must be	 * opened using their respective drivers.	 */	if ((line < 0) || (line >= NUM_CHANNELS))		return -ENODEV;	info = zs_soft + line;	/* Is the kgdb running over this line? */	if (info->kgdb_channel)		return -ENODEV;	if (serial_paranoia_check(info, tty->device, "rs_open"))		return -ENODEV;#ifdef SERIAL_DEBUG_OPEN	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,	       info->count);#endif	info->count++;	tty->driver_data = info;	info->tty = tty;	/*	 * Start up serial port	 */	retval = startup(info);	if (retval)		return retval;	retval = block_til_ready(tty, filp, info);	if (retval) {#ifdef SERIAL_DEBUG_OPEN		printk("rs_open returning after block_til_ready with %d\n",		       retval);#endif		return retval;	}	if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = info->normal_termios;		else 			*tty->termios = info->callout_termios;		change_speed(info);	}	/* If this is the serial console change the speed to 	 * the right value	 */	if (info->is_cons) {		info->tty->termios->c_cflag = sgisercon->cflag;		change_speed(info);			}	info->session = current->session;	info->pgrp = current->pgrp;#ifdef SERIAL_DEBUG_OPEN	printk("rs_open ttys%d successful...\n", info->line);#endif	return 0;}/* Finally, routines used to initialize the serial driver. */static void show_serial_version(void){	printk("SGI Zilog8530 serial driver version 1.00\n");}/* Return layout for the requested zs chip number. */static inline struct sgi_zslayout *get_zs(int chip){	extern struct hpc3_miscregs *hpc3mregs;	if (chip > 0)		panic("Wheee, bogus zs chip number requested.");	return (struct sgi_zslayout *) (&hpc3mregs->ser1cmd);}static inline voidrs_cons_check(struct sgi_serial *ss, int channel){	int i, o, io;	static int msg_printed = 0;	i = o = io = 0;	/* Is this one of the serial console lines? */	if((zs_cons_chanout != channel) &&	   (zs_cons_chanin != channel))		return;	zs_conschan = ss->zs_channel;	zs_consinfo = ss;	/* If this is console input, we handle the break received	 * status interrupt on this line to mean prom_halt().	 */	if(zs_cons_chanin == channel) {		ss->break_abort = 1;		i = 1;	}	if(o && i)		io = 1;	/* Set flag variable for this port so that it cannot be	 * opened for other uses by accident.	 */	ss->is_cons = 1;	if(io) {		if (!msg_printed) {			printk("zs%d: console I/O\n", ((channel>>1)&1));			msg_printed = 1;		}	} else {		printk("zs%d: console %s\n", ((channel>>1)&1),		       (i==1 ? "input" : (o==1 ? "output" : "WEIRD")));	}}volatile int test_done;/* rs_init inits the driver */int rs_init(void){	int chip, channel, i, flags;	struct sgi_serial *info;	/* Setup base handler, and timer table. */	init_bh(SERIAL_BH, do_serial_bh);	show_serial_version();	/* Initialize the tty_driver structure */	/* SGI: 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 = NUM_CHANNELS;	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;	/*	 * 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();	/* Set up our interrupt linked list */	zs_chain = &zs_soft[0];	zs_soft[0].zs_next = &zs_soft[1];	zs_soft[1].zs_next = 0;	for(chip = 0; chip < NUM_SERIAL; chip++) {		/* If we are doing kgdb over one of the channels on		 * chip zero, kgdb_channel will be set to 1 by the		 * rs_kgdb_hook() routine below.		 */		if(!zs_chips[chip]) {			zs_chips[chip] = get_zs(chip);			/* Two channels per chip */			zs_channels[(chip*2)] = &zs_chips[chip]->channelB;			zs_channels[(chip*2)+1] = &zs_chips[chip]->channelA;			zs_soft[(chip*2)].kgdb_channel = 0;			zs_soft[(chip*2)+1].kgdb_channel = 0;		}		/* First, set up channel A on this chip. */		channel = chip * 2;		zs_soft[channel].zs_channel = zs_channels[channel];		zs_soft[channel].change_needed = 0;		zs_soft[channel].clk_divisor = 16;		zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);		zs_soft[channel].cons_mouse = 0;		/* If not keyboard/mouse and is console serial		 * line, then enable receiver interrupts.		 */		if(zs_soft[channel].is_cons) {			write_zsreg(zs_soft[channel].zs_channel, R1,				    (EXT_INT_ENAB | INT_ALL_Rx));			write_zsreg(zs_soft[channel].zs_channel, R9, (NV | MIE));			write_zsreg(zs_soft[channel].zs_channel, R10, (NRZ));			write_zsreg(zs_soft[channel].zs_channel, R3, (Rx8|RxENABLE));			write_zsreg(zs_soft[channel].zs_channel, R5, (Tx8 | TxENAB));		}		/* If this is the kgdb line, enable interrupts because we		 * now want to receive the 'control-c' character from the		 * client attached to us asynchronously.		 */		if(zs_soft[channel].kgdb_channel)			kgdb_chaninit(&zs_soft[channel], 1,				      zs_soft[channel].zs_baud);		/* Now, channel B */		channel++;		zs_soft[channel].zs_channel = zs_channels[channel];		zs_soft[channel].change_needed = 0;		zs_soft[channel].clk_divisor = 16;		zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);		zs_soft[channel].cons_keyb = 0;		/* If console serial line, then enable receiver interrupts. */		if(zs_soft[channel].is_cons) {			write_zsreg(zs_soft[channel].zs_channel, R1,				    (EXT_INT_ENAB | INT_ALL_Rx));			write_zsreg(zs_soft[channel].zs_channel, R9,				    (NV | MIE));			write_zsreg(zs_soft[channel].zs_channel, R10,				    (NRZ));			write_zsreg(zs_soft[channel].zs_channel, R3,				    (Rx8|RxENABLE));			write_zsreg(zs_soft[channel].zs_channel, R5,				    (Tx8 | TxENAB | RTS | DTR));		}	}	for(info=zs_chain, i=0; info; info = info->zs_next, i++)	{		info->magic = SERIAL_MAGIC;		info->port = (int) info->zs_channel;		info->line = i;		info->tty = 0;		info->irq = zilog_irq;		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->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);		printk("tty%02d at 0x%04x (irq = %d)", info->line, 		       info->port, info->irq);		printk(" is a Zilog8530\n");	}	if (request_irq(zilog_irq, rs_interrupt, (SA_INTERRUPT),			"Zilog8530", zs_chain))		panic("Unable to attach zs intr\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. *//* SGI: 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;}/* Hooks for running a serial console.  con_init() calls this if the * console is being run over one of the ttya/ttyb serial ports. * 'chip' should be zero, as chip 1 drives the mouse/keyboard. * 'channel' is decoded as 0=TTYA 1=TTYB, note that the channels * are addressed backwards, channel B is first, then channel A. */voidrs_cons_hook(int chip, int out, int line){	int channel;		if(chip)		panic("rs_cons_hook called with chip not zero");	if(line != 0 && line != 1)		panic("rs_cons_hook called with line not ttya or ttyb");	channel = line;	if(!zs_chips[chip]) {		zs_chips[chip] = get_zs(chip);		/* Two channels per chip */		zs_channels[(chip*2)] = &zs_chips[chip]->channelB;		zs_channels[(chip*2)+1] = &zs_chips[chip]->channelA;	}	zs_soft[channel].zs_channel = zs_channels[channel];	zs_soft[channel].change_needed = 0;	zs_soft[channel].clk_divisor = 16;	zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);	if(out) 		zs_cons_chanout = ((chip * 2) + channel);	else 		zs_cons_chanin = ((chip * 2) + channel);		rs_cons_check(&zs_soft[channel], channel);}/* This is called at boot time to prime the kgdb serial debugging * serial line.  The 'tty_num' argument is 0 for /dev/ttyd2 and 1 for * /dev/ttyd1 (yes they are backwards on purpose) which is determined * in setup_arch() from the boot command line flags. */voidrs_kgdb_hook(int tty_num){	int chip = 0;	if(!zs_chips[chip]) {		zs_chips[chip] = get_zs(chip);		/* Two channels per chip */		zs_channels[(chip*2)] = &zs_chips[chip]->channelA;		zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;	}	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 = get_zsbaud(&zs_soft[tty_num]);	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], 0, 9600);	ZS_CLEARERR(zs_kgdbchan);	udelay(5);	ZS_CLEARFIFO(zs_kgdbchan);}static void zs_console_write(struct console *co, const char *str,                             unsigned int count){	while(count--) {		if(*str == '\n')			zs_cons_put_char('\r');		zs_cons_put_char(*str++);	}	/* Comment this if you want to have a strict interrupt-driven output */	rs_fair_output();}static int zs_console_wait_key(struct console *con){	sleep_on(&keypress_wait);	return 0;}static kdev_t zs_console_device(struct console *con){	return MKDEV(TTY_MAJOR, 64 + con->index);}static int __init zs_console_setup(struct console *con, char *options){	struct sgi_serial *info;	int	baud;	int	bits = 8;	int	parity = 'n';	int	cflag = CREAD | HUPCL | CLOCAL;	char	*s, *dbaud;	int     i, brg;    	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';	}	else {		/* If the user doesn't set console=... try to read the		 * PROM variable - if this fails use 9600 baud and		 * inform the user about the problem		 */		dbaud = ArcGetEnvironmentVariable("dbaud");		if(dbaud) baud = simple_strtoul(dbaud, NULL, 10);		else {			/* Use prom_printf() to make sure that the user			 * is getting anything ...			 */			prom_printf("No dbaud set in PROM ?!? Using 9600.\n");			baud = 9600;		}	}	/*	 *	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;	}	con->cflag = cflag;        rs_cons_hook(0, 0, con->index);	info = zs_soft + con->index;	info->is_cons = 1;    	printk("Console: ttyS%d (Zilog8530), %d baud\n", 						info->line, baud);	i = con->cflag & CBAUD;	if (con->cflag & CBAUDEX) {		i &= ~CBAUDEX;		con->cflag &= ~CBAUDEX;	}	info->zs_baud = baud;	switch (con->cflag & CSIZE) {		case CS5:			zscons_regs[3] = Rx5 | RxENABLE;			zscons_regs[5] = Tx5 | TxENAB;			break;		case CS6:			zscons_regs[3] = Rx6 | RxENABLE;			zscons_regs[5] = Tx6 | TxENAB;			break;		case CS7:			zscons_regs[3] = Rx7 | RxENABLE;			zscons_regs[5] = Tx7 | TxENAB;			break;		default:		case CS8:			zscons_regs[3] = Rx8 | RxENABLE;			zscons_regs[5] = Tx8 | TxENAB;			break;	}	zscons_regs[5] |= DTR;	if (con->cflag & PARENB)		zscons_regs[4] |= PAR_ENA;	if (!(con->cflag & PARODD))		zscons_regs[4] |= PAR_EVEN;	if (con->cflag & CSTOPB)		zscons_regs[4] |= SB2;	else		zscons_regs[4] |= SB1;		sgisercon = con;	brg = BPS_TO_BRG(baud, ZS_CLOCK / info->clk_divisor);	zscons_regs[12] = brg & 0xff;	zscons_regs[13] = (brg >> 8) & 0xff;	memcpy(info->curregs, zscons_regs, sizeof(zscons_regs));	memcpy(info->pendregs, zscons_regs, sizeof(zscons_regs));    	load_zsregs(info->zs_channel, zscons_regs);	ZS_CLEARERR(info->zs_channel);	ZS_CLEARFIFO(info->zs_channel);	return 0;}static struct console sgi_console_driver = {	name:		"ttyS",	write:		zs_console_write,	device:		zs_console_device,	wait_key:	zs_console_wait_key,	setup:		zs_console_setup,	flags:		CON_PRINTBUFFER,	index:		-1,};/* *	Register console. */void __init sgi_serial_console_init(void){	register_console(&sgi_console_driver);}__initcall(rs_init);

⌨️ 快捷键说明

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