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

📄 sunserial.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			else				retval = -ERESTARTSYS;	#else			retval = -EAGAIN;#endif			break;		}		if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&		    !(info->flags & ZILOG_CLOSING) && do_clocal)			break;		if (current->signal & ~current->blocked) {			retval = -ERESTARTSYS;			break;		}#ifdef SERIAL_DEBUG_OPEN		printk("block_til_ready blocking: ttys%d, count = %d\n",		       info->line, info->count);#endif		schedule();	}	current->state = TASK_RUNNING;	remove_wait_queue(&info->open_wait, &wait);	if (!tty_hung_up_p(filp))		info->count++;	info->blocked_open--;#ifdef SERIAL_DEBUG_OPEN	printk("block_til_ready after blocking: ttys%d, count = %d\n",	       info->line, info->count);#endif	if (retval)		return retval;	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 sun_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;	if((line == KEYBOARD_LINE) || (line == MOUSE_LINE))		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);	}	info->session = current->session;	info->pgrp = current->pgrp;#ifdef SERIAL_DEBUG_OPEN	printk("rs_open ttys%d successful...", info->line);#endif	return 0;}/* Finally, routines used to initialize the serial driver. */static void show_serial_version(void){	printk("Sparc Zilog8530 serial driver version 1.00\n");}/* Probe the PROM for the request zs chip number. */static inline struct sun_zslayout *get_zs(int chip){	struct linux_prom_irqs tmp_irq;	unsigned long paddr = 0;	unsigned long vaddr = 0;	int zsnode, tmpnode, iospace, slave;	static int irq = 0;#if CONFIG_AP1000        printk("No zs chip\n");        return NULL;#endif	iospace = 0;	if(chip < 0 || chip >= NUM_SERIAL)		panic("get_zs bogon zs chip number");	if(sparc_cpu_model == sun4) {		/* Grrr, these have to be hardcoded aieee */		switch(chip) {		case 0:			paddr = 0xf1000000;			break;		case 1:			paddr = 0xf0000000;			break;		};		iospace = 0;		zs_nodes[chip] = 0;		if(!irq)			zilog_irq = irq = 12;		vaddr = (unsigned long)			sparc_alloc_io((char *) paddr, 0, 8,				       "Zilog Serial", iospace, 0);	} else {		/* Can use the prom for other machine types */		zsnode = prom_getchild(prom_root_node);		tmpnode = prom_searchsiblings(zsnode, "obio");		if(tmpnode)			zsnode = prom_getchild(tmpnode);		if(!zsnode)			panic("get_zs no zs serial prom node");		while(zsnode) {			zsnode = prom_searchsiblings(zsnode, "zs");			slave = prom_getintdefault(zsnode, "slave", -1);			if(slave==chip) {				/* The one we want */				vaddr = (unsigned long)					prom_getintdefault(zsnode, "address",							       0xdeadbeef);				if(vaddr == 0xdeadbeef)					prom_halt();				zs_nodes[chip] = zsnode;				prom_getproperty(zsnode, "intr",						 (char *) &tmp_irq,						 sizeof(tmp_irq));#ifdef OLD_STYLE_IRQ				tmp_irq.pri &= 0xf;#endif				if(!irq) {					irq = zilog_irq = tmp_irq.pri;				} else {					if(tmp_irq.pri != irq)						panic("zilog: bogon irqs");				}				break;			}			zsnode = prom_getsibling(zsnode);		}		if(!zsnode)			panic("get_zs whee chip not found");	}	if(!vaddr)		panic("get_zs whee no serial chip mappable");	return (struct sun_zslayout *) vaddr;}extern void register_console(void (*proc)(const char *));static inline voidrs_cons_check(struct sun_serial *ss, int channel){	int i, o, io;	static consout_registered = 0;	static 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;	/* Register the console output putchar, if necessary */	if((zs_cons_chanout == channel)) {		o = 1;		/* double whee.. */		if(!consout_registered) {			register_console(zs_console_print);			consout_registered = 1;		}	}	/* 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;	if(ss->zs_baud != 9600)		panic("Console baud rate weirdness");	/* 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;extern void keyboard_zsinit(void);extern void sun_mouse_zsinit(void);/* rs_init inits the driver */int rs_init(void){	int chip, channel, i, flags;	struct sun_serial *info;#if CONFIG_AP1000        printk("not doing rs_init()\n");        return 0;#endif	/* Setup base handler, and timer table. */	init_bh(SERIAL_BH, do_serial_bh);	timer_table[RS_TIMER].fn = rs_timer;	timer_table[RS_TIMER].expires = 0;	show_serial_version();	/* Initialize the tty_driver structure */	/* SPARC: 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 = &zs_soft[2];	zs_soft[2].zs_next = &zs_soft[3];	zs_soft[3].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]->channelA;			zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;			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((channel<KEYBOARD_LINE) && (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);		if(channel == KEYBOARD_LINE) {			/* Tell keyboard driver about our presence. */			if(zs_soft[channel].zs_baud != 1200)				panic("Weird keyboard serial baud rate");			zs_soft[channel].cons_keyb = 1;			zs_kbdchan = zs_soft[channel].zs_channel;			/* Enable Rx/Tx, IRQs, and inform kbd driver */			write_zsreg(zs_soft[channel].zs_channel, R1,				    (EXT_INT_ENAB | INT_ALL_Rx));			write_zsreg(zs_soft[channel].zs_channel, R4,				    (PAR_EVEN | X16CLK | SB1));			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, R11,				    (TCBR | RCBR));			write_zsreg(zs_soft[channel].zs_channel, R14,				    (BRSRC | BRENABL));			write_zsreg(zs_soft[channel].zs_channel, R3, (Rx8|RxENABLE));			write_zsreg(zs_soft[channel].zs_channel, R5,				    (Tx8 | TxENAB | DTR | RTS));#if 0			write_zsreg(zs_soft[channel].zs_channel, R15,				    (DCDIE | CTSIE | TxUIE | BRKIE));#endif			ZS_CLEARERR(zs_soft[channel].zs_channel);			ZS_CLEARFIFO(zs_soft[channel].zs_channel);		}		/* 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 not keyboard/mouse and is console serial		 * line, then enable receiver interrupts.		 */		if(channel<KEYBOARD_LINE && 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));		}		if(channel == MOUSE_LINE) {			/* Tell mouse driver about our presence. */			if(zs_soft[channel].zs_baud != 1200)				panic("Weird mouse serial baud rate");			zs_soft[channel].cons_mouse = 1;			zs_mousechan = zs_soft[channel].zs_channel;			/* Enable Rx, IRQs, and inform mouse driver */			write_zsreg(zs_soft[channel].zs_channel, R1, (INT_ALL_Rx));			write_zsreg(zs_soft[channel].zs_channel, R9, (NV|MIE));			write_zsreg(zs_soft[channel].zs_channel, R3, (Rx8|RxENABLE));#if 0 /* XXX hangs sun4c's sometimes */			write_zsreg(zs_soft[channel].zs_channel, R15,				    (DCDIE | CTSIE | TxUIE | BRKIE));#endif			sun_mouse_zsinit();		} else {			zs_soft[channel].cons_mouse = 0;		}	}	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;		info->open_wait = 0;		info->close_wait = 0;		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 | SA_STATIC_ALLOC),			"Zilog8530", NULL))		panic("Unable to attach zs intr\n");	restore_flags(flags);	keyboard_zsinit();	return 0;}/* * register_serial and unregister_serial allows for serial ports to be * configured at run-time, to support PCMCIA modems. *//* SPARC: 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 channel){	if(chip)		panic("rs_cons_hook called with chip not zero");	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[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]);	rs_cons_check(&zs_soft[channel], channel);	if(out)		zs_cons_chanout = ((chip * 2) + channel);	else		zs_cons_chanin = ((chip * 2) + channel);}/* 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. */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);}

⌨️ 快捷键说明

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