?? zs.c
字號(hào):
* 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; writ
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -