📄 zs.c
字号:
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 + -