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

📄 zs.c

📁 自己根据lkd和情境分析
💻 C
📖 第 1 页 / 共 5 页
字号:
				 * everything in I/O is implicitly mapped				 * anyways by our clever TLB miss handling				 * scheme, so don't fail here.  -DaveM				 */				if (central_bus == NULL) {					for_each_sbus(sbus) {						for_each_sbusdev(sdev, sbus) {							if (sdev->prom_node == zsnode)								goto found;						}					}				}			found:				if (sdev == NULL && central_bus == NULL)					prom_halt();				if (central_bus == NULL) {					mapped_addr =					    sbus_ioremap(&sdev->resource[0], 0,							 PAGE_SIZE, "Zilog Registers");				} else {					struct linux_prom_registers zsregs[1];					int err;					err = prom_getproperty(zsnode, "reg",							       (char *)&zsregs[0],							       sizeof(zsregs));					if (err == -1) {						prom_printf("ZS: Cannot map Zilog regs.\n");						prom_halt();					}					apply_fhc_ranges(central_bus->child, &zsregs[0], 1);					apply_central_ranges(central_bus, &zsregs[0], 1);					mapped_addr =						((((u64)zsregs[0].which_io)<<32UL)|						 ((u64)zsregs[0].phys_addr));				}			} else if(len % sizeof(unsigned int)) {				prom_printf("WHOOPS:  proplen for %s "					    "was %d, need multiple of "					    "%d\n", "address", len,					    sizeof(unsigned int));				panic("zilog: address property");			}			zs_nodes[chip] = zsnode;			len = prom_getproperty(zsnode, "interrupts",					       (char *) &sun4u_ino,					       (sizeof(sun4u_ino)));			if(!irq) {				if (central_bus) {					unsigned long iclr, imap;					iclr = central_bus->child->fhc_regs.uregs + FHC_UREGS_ICLR;					imap = central_bus->child->fhc_regs.uregs + FHC_UREGS_IMAP;					irq = zilog_irq = build_irq(12, 0, iclr, imap);				} else {					irq = zilog_irq = 						sbus_build_irq(sbus_root, sun4u_ino);				}			}			break;		}		zsnode = prom_getsibling(zsnode);		seen++;	}	if(!zsnode)		panic("get_zs: whee chip not found");	if(!vaddr[0] && !mapped_addr)		panic("get_zs: whee no serial chip mappable");	if (mapped_addr != 0) {		return (struct sun_zslayout *) mapped_addr;	} else {		return (struct sun_zslayout *) prom_virt_to_phys((unsigned long)vaddr[0], 0);	}}#else /* !(__sparc_v9__) */static struct sun_zslayout * __init get_zs(int chip){	struct linux_prom_irqs tmp_irq[2];	unsigned int paddr = 0;	unsigned int vaddr[2] = { 0, 0 };	int zsnode, tmpnode, iospace, slave, len;	int cpunode = 0, bbnode = 0;	static int irq = 0;	int chipid = chip;	iospace = 0;	if(chip < 0 || chip >= NUM_SERIAL)		panic("get_zs bogon zs chip number");	if(sparc_cpu_model == sun4) {		struct resource dummy_resource;		/* 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;		dummy_resource.start = paddr;		dummy_resource.end = paddr + 8 - 1;		dummy_resource.flags = IORESOURCE_IO;		vaddr[0] = sbus_ioremap(&dummy_resource, 0,					8, "Zilog Serial");	} else {		/* Can use the prom for other machine types */		zsnode = prom_getchild(prom_root_node);		if (sparc_cpu_model == sun4d) {			int no = 0;			tmpnode = zsnode;			zsnode = 0;			bbnode = 0;			while (tmpnode && (tmpnode = prom_searchsiblings(tmpnode, "cpu-unit"))) {				bbnode = prom_getchild(tmpnode);				if (bbnode && (bbnode = prom_searchsiblings(bbnode, "bootbus"))) {					if (no == (chip >> 1)) {						cpunode = tmpnode;						zsnode = prom_getchild(bbnode);						chipid = (chip & 1);						break;					}					no++;				}				tmpnode = prom_getsibling(tmpnode);			}			if (!tmpnode)				panic ("get_zs: couldn't find %dth bootbus\n", chip >> 1);		} else {			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 == chipid) {				/* The one we want */				if (sparc_cpu_model != sun4d) {					len = prom_getproperty(zsnode, "address",							       (void *) vaddr,							       sizeof(vaddr));        				if (len % sizeof(unsigned int)) {						prom_printf("WHOOPS:  proplen for %s "							"was %d, need multiple of "							"%d\n", "address", len,							sizeof(unsigned int));						panic("zilog: address property");					}				} else {					/* On sun4d don't have address property :( */					struct linux_prom_registers zsreg[4];					struct resource res;										if (prom_getproperty(zsnode, "reg", (char *)zsreg, sizeof(zsreg)) == -1) {						prom_printf ("Cannot map zs regs\n");						prom_halt();					}					prom_apply_generic_ranges(bbnode, cpunode, zsreg, 1);					res.start = zsreg[0].phys_addr;					res.end = res.start + 8 - 1;					res.flags = zsreg[0].which_io | IORESOURCE_IO;					vaddr[0] = sbus_ioremap(&res, 0,								8, "Zilog Serial");				}				zs_nodes[chip] = zsnode;				len = prom_getproperty(zsnode, "intr",						       (char *) tmp_irq,						       sizeof(tmp_irq));				if (len % sizeof(struct linux_prom_irqs)) {					prom_printf(					      "WHOOPS:  proplen for %s "					      "was %d, need multiple of "					      "%d\n", "intr", len,					      sizeof(struct linux_prom_irqs));					panic("zilog: intr property");				}				if(!irq) {					irq = zilog_irq = tmp_irq[0].pri;				} else {					if(tmp_irq[0].pri != irq)						panic("zilog: bogon irqs");				}				break;			}			zsnode = prom_getsibling(zsnode);		}		if(!zsnode)			panic("get_zs whee chip not found");	}	if(!vaddr[0])		panic("get_zs whee no serial chip mappable");	return (struct sun_zslayout *)(unsigned long) vaddr[0];}#endif/* This is for the auto baud rate detection in the mouse driver. */void zs_change_mouse_baud(int newbaud){	int channel = MOUSE_LINE;	int brg;	zs_soft[channel].zs_baud = newbaud;	brg = BPS_TO_BRG(zs_soft[channel].zs_baud,			 (ZS_CLOCK / zs_soft[channel].clk_divisor));	write_zsreg(zs_soft[channel].zs_channel, R12, (brg & 0xff));	write_zsreg(zs_soft[channel].zs_channel, R13, ((brg >> 8) & 0xff));}void __init zs_init_alloc_failure(const char *table_name){	prom_printf("zs_probe: Cannot alloc %s.\n", table_name);	prom_halt();}void * __init zs_alloc_bootmem(unsigned long size){	void *ret;	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);	if (ret != NULL)		memset(ret, 0, size);	return ret;}void __init zs_alloc_tables(void){	zs_chips = (struct sun_zslayout **)		zs_alloc_bootmem(NUM_SERIAL * sizeof(struct sun_zslayout *));	if (zs_chips == NULL)		zs_init_alloc_failure("zs_chips");	zs_channels = (struct sun_zschannel **)		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct sun_zschannel *));	if (zs_channels == NULL)		zs_init_alloc_failure("zs_channels");	zs_nodes = (int *)		zs_alloc_bootmem(NUM_SERIAL * sizeof(int));	if (zs_nodes == NULL)		zs_init_alloc_failure("zs_nodes");	zs_soft = (struct sun_serial *)		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct sun_serial));	if (zs_soft == NULL)		zs_init_alloc_failure("zs_soft");	zs_ttys = (struct tty_struct *)		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct tty_struct));	if (zs_ttys == NULL)		zs_init_alloc_failure("zs_ttys");	serial_table = (struct tty_struct **)		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct tty_struct *));	if (serial_table == NULL)		zs_init_alloc_failure("serial_table");	serial_termios = (struct termios **)		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct termios *));	if (serial_termios == NULL)		zs_init_alloc_failure("serial_termios");	serial_termios_locked = (struct termios **)		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct termios *));	if (serial_termios_locked == NULL)		zs_init_alloc_failure("serial_termios_locked");}int __init zs_probe(void){	int node;	if(sparc_cpu_model == sun4)		goto no_probe;	NUM_SERIAL = 0;		node = prom_getchild(prom_root_node);	if (sparc_cpu_model == sun4d) {		int bbnode;				while (node && (node = prom_searchsiblings(node, "cpu-unit"))) {			bbnode = prom_getchild(node);			if (bbnode && prom_searchsiblings(bbnode, "bootbus"))				NUM_SERIAL += 2;			node = prom_getsibling(node);		}		goto no_probe;	}#ifdef __sparc_v9__	else if (sparc_cpu_model == sun4u) {		int central_node;		/* Central bus zilogs must be checked for first,		 * since Enterprise boxes might have SBUSes as well.		 */		central_node = prom_finddevice("/central");		if(central_node != 0 && central_node != -1)			node = prom_searchsiblings(prom_getchild(central_node), "fhc");		else			node = prom_searchsiblings(node, "sbus");		if(node != 0 && node != -1)			node = prom_getchild(node);		if(node == 0 || node == -1)			return -ENODEV;	}#endif /* __sparc_v9__ */	else {		node = prom_searchsiblings(node, "obio");		if(node)			node = prom_getchild(node);		NUM_SERIAL = 2;		goto no_probe;	}	node = prom_searchsiblings(node, "zs");	if (!node)		return -ENODEV;			NUM_SERIAL = 2;no_probe:	zs_alloc_tables();	/* Fill in rs_ops struct... */#ifdef CONFIG_SERIAL_CONSOLE	sunserial_setinitfunc(zs_console_init);#endif	sunserial_setinitfunc(zs_init);	rs_ops.rs_kgdb_hook = zs_kgdb_hook;	rs_ops.rs_change_mouse_baud = zs_change_mouse_baud;	sunkbd_setinitfunc(sun_kbd_init);	kbd_ops.compute_shiftstate = sun_compute_shiftstate;	kbd_ops.setledstate = sun_setledstate;	kbd_ops.getledstate = sun_getledstate;	kbd_ops.setkeycode = sun_setkeycode;	kbd_ops.getkeycode = sun_getkeycode;#if defined(__sparc_v9__) && defined(CONFIG_PCI)	sunkbd_install_keymaps(sun_key_maps, sun_keymap_count,			       sun_func_buf, sun_func_table,			       sun_funcbufsize, sun_funcbufleft,			       sun_accent_table, sun_accent_table_size);#endif	return 0;}static inline void zs_prepare(void){	int channel, chip;	unsigned long flags;	if (!NUM_SERIAL)		return;		save_and_cli(flags);		/* Set up our interrupt linked list */	zs_chain = &zs_soft[0];	for(channel = 0; channel < NUM_CHANNELS - 1; channel++) {		zs_soft[channel].zs_next = &zs_soft[channel + 1];		zs_soft[channel].line = channel;	}	zs_soft[channel].zs_next = 0;	/* Initialize Softinfo */	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		 * zs_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].cons_keyb = 0;		zs_soft[channel].cons_mouse = 0;		zs_soft[channel].channelA = 1;		/* 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].cons_keyb = 0;		zs_soft[channel].cons_mouse = 0;		zs_soft[channel].channelA = 0;	}		restore_flags(flags);}int __init zs_init(void){	int channel, brg, i;	unsigned long flags;	struct sun_serial *info;	char dummy;	/* Setup base handler, and timer table. */	init_bh(SERIAL_BH, do_serial_bh);	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.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;	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 = zs_open;	serial_driver.close = zs_close;	serial_driver.write = zs_write;	serial_driver.flush_chars = zs_flush_chars;	serial_driver.write_room = zs_write_room;	serial_driver.chars_in_buffer = zs_chars_in_buffer;	serial_driver.flush_buffer = zs_flush_buffer;	serial_driver.ioctl = zs_ioctl;	serial_driver.throttle = zs_throttle;	serial_driver.unthrottle = zs_unthrottle;	serial_driver.set_termios = zs_set_termios;	serial_driver.stop = zs_stop;	serial_driver.start = zs_start;	serial_driver.hangup = zs_hangup;	/* I'm too lazy, someone write versions of this for us. -DaveM */	/* I just did. :-) -AIB 2001-12-23 */	serial_driver.read_proc = zs_read_proc;	/*	 * The callout device is just like normal device except for	 * major number and the subtype code.	 */	callout_driver = serial_driver;	callout_driver.name = "cua/%d";	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");	save_flags(flags); cli();	/* Initialize Softinfo */	zs_prepare();	/* Grab IRQ line before poking the chips so we do	 * not lose any interrupts.	 */	if (request_irq(zilog_irq, zs_interrupt, SA_SHIRQ,			"Zilog8530", zs_chain)) {		prom_printf("Unable to attach zs intr\n");		prom_halt();	}	/* Initialize Hardware */	for(channel = 0; channel < NUM_CHANNELS; channel++) {		/* Hardware reset each chip */		if (!(channel & 1)) {			write_zsreg(zs_soft[channel].zs_channel, R9, FHWRES);			ZSDELAY_LONG();			dummy = read_zsreg(zs_soft[channel].zs_channel, R0);		}		if(channel == KEYBOARD_LINE) {			zs_soft[channel].cons_keyb = 1;			zs_soft[channel].parity_mask = 0xff;			zs_kbdchan = zs_soft[channel].zs_channel;			write_

⌨️ 快捷键说明

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