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

📄 dz.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
  if (--info->count < 0) {    printk("ds_close: bad serial port count for ttys%d: %d\n",	   info->line, info->count);    info->count = 0;  }  if (info->count) {    restore_flags (flags);    return;  }  info->flags |= DZ_CLOSING;  /*   * Save the termios structure, since this port may have   * separate termios for callout and dialin.   */  if (info->flags & DZ_NORMAL_ACTIVE)    info->normal_termios = *tty->termios;  if (info->flags & DZ_CALLOUT_ACTIVE)    info->callout_termios = *tty->termios;  /*   * Now we wait for the transmit buffer to clear; and we notify    * the line discipline to only process XON/XOFF characters.   */  tty->closing = 1;  if (info->closing_wait != DZ_CLOSING_WAIT_NONE)    tty_wait_until_sent (tty, info->closing_wait);  /*   * At this point we stop accepting input.  To do this, we   * disable the receive line status interrupts.   */  shutdown (info);  if (tty->driver.flush_buffer)    tty->driver.flush_buffer (tty);  if (tty->ldisc.flush_buffer)    tty->ldisc.flush_buffer (tty);  tty->closing = 0;  info->event = 0;  info->tty = 0;  if (tty->ldisc.num != ldiscs[N_TTY].num) {    if (tty->ldisc.close)      (tty->ldisc.close)(tty);    tty->ldisc = ldiscs[N_TTY];    tty->termios->c_line = N_TTY;    if (tty->ldisc.open)      (tty->ldisc.open)(tty);  }  if (info->blocked_open) {    if (info->close_delay) {      current->state = TASK_INTERRUPTIBLE;      schedule_timeout(info->close_delay);    }    wake_up_interruptible (&info->open_wait);  }  info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING);  wake_up_interruptible (&info->close_wait);  restore_flags (flags);}/* * dz_hangup () --- called by tty_hangup() when a hangup is signaled. */static void dz_hangup (struct tty_struct *tty){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;    dz_flush_buffer (tty);  shutdown (info);  info->event = 0;  info->count = 0;  info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE);  info->tty = 0;  wake_up_interruptible (&info->open_wait);}/* * ------------------------------------------------------------ * rs_open() and friends * ------------------------------------------------------------ */static int block_til_ready (struct tty_struct *tty, struct file *filp, struct dz_serial *info){  DECLARE_WAITQUEUE(wait, current);   int retval;  int do_clocal = 0;  /*   * If the device is in the middle of being closed, then block   * until it's done, and then try again.   */  if (info->flags & DZ_CLOSING) {    interruptible_sleep_on (&info->close_wait);    return -EAGAIN;  }  /*   * If this is a callout device, then just make sure the normal   * device isn't being used.   */  if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {    if (info->flags & DZ_NORMAL_ACTIVE)      return -EBUSY;        if ((info->flags & DZ_CALLOUT_ACTIVE) &&	(info->flags & DZ_SESSION_LOCKOUT) &&	(info->session != current->session))      return -EBUSY;        if ((info->flags & DZ_CALLOUT_ACTIVE) &&	(info->flags & DZ_PGRP_LOCKOUT) &&	(info->pgrp != current->pgrp))      return -EBUSY;    info->flags |= DZ_CALLOUT_ACTIVE;    return 0;  }  /*   * If non-blocking mode is set, or the port is not enabled,   * then make the check up front and then exit.   */  if ((filp->f_flags & O_NONBLOCK) ||      (tty->flags & (1 << TTY_IO_ERROR))) {    if (info->flags & DZ_CALLOUT_ACTIVE)      return -EBUSY;    info->flags |= DZ_NORMAL_ACTIVE;    return 0;  }  if (info->flags & DZ_CALLOUT_ACTIVE) {    if (info->normal_termios.c_cflag & CLOCAL)      do_clocal = 1;  } else {    if (tty->termios->c_cflag & CLOCAL)      do_clocal = 1;  }  /*   * Block waiting for the carrier detect and the line to become   * free (i.e., not in use by the callout).  While we are in   * this loop, info->count is dropped by one, so that   * dz_close() knows when to free things.  We restore it upon   * exit, either normal or abnormal.   */  retval = 0;  add_wait_queue (&info->open_wait, &wait);  info->count--;  info->blocked_open++;  while (1) {    set_current_state(TASK_INTERRUPTIBLE);    if (tty_hung_up_p (filp) || !(info->is_initialized)) {      retval = -EAGAIN;      break;    }    if (!(info->flags & DZ_CALLOUT_ACTIVE) &&	!(info->flags & DZ_CLOSING) && do_clocal)      break;    if (signal_pending (current)) {      retval = -ERESTARTSYS;      break;    }    schedule();  }		  current->state = TASK_RUNNING;  remove_wait_queue (&info->open_wait, &wait);  if (!tty_hung_up_p(filp))    info->count++;  info->blocked_open--;  if (retval)    return retval;  info->flags |= DZ_NORMAL_ACTIVE;  return 0;}       /* * This routine is called whenever a serial port is opened.  It * enables interrupts for a serial port. It also performs the  * serial-specific initialization for the tty structure. */static int dz_open (struct tty_struct *tty, struct file *filp){  struct dz_serial *info;  int retval, line;  line = MINOR(tty->device) - tty->driver.minor_start;  /* The dz lines for the mouse/keyboard must be   * opened using their respective drivers.   */  if ((line < 0) || (line >= DZ_NB_PORT))    return -ENODEV;  if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE))    return -ENODEV;  info = lines[line];  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)    return retval;  if ((info->count == 1) && (info->flags & DZ_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;  return 0;}static void show_serial_version (void){  printk("%s%s\n", dz_name, dz_version);}int __init dz_init(void){  int i, flags;  struct dz_serial *info;  /* Setup base handler, and timer table. */  init_bh (SERIAL_BH, do_serial_bh);  show_serial_version ();  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 = DZ_NB_PORT;  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 = dz_open;  serial_driver.close = dz_close;  serial_driver.write = dz_write;  serial_driver.flush_chars = dz_flush_chars;  serial_driver.write_room = dz_write_room;  serial_driver.chars_in_buffer = dz_chars_in_buffer;  serial_driver.flush_buffer = dz_flush_buffer;  serial_driver.ioctl = dz_ioctl;  serial_driver.throttle = dz_throttle;  serial_driver.unthrottle = dz_unthrottle;  serial_driver.send_xchar = dz_send_xchar;  serial_driver.set_termios = dz_set_termios;  serial_driver.stop = dz_stop;  serial_driver.start = dz_start;  serial_driver.hangup = dz_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();   for (i=0; i < DZ_NB_PORT;  i++)      {      info = &multi[i];       lines[i] = info;    info->magic = SERIAL_MAGIC;      if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))       info->port = (unsigned long) KN01_DZ11_BASE;      else       info->port = (unsigned long) KN02_DZ11_BASE;    info->line = i;    info->tty = 0;    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);     /* If we are pointing to address zero then punt - not correctly       set up in setup.c to handle this. */    if (! info->port)      return 0;    printk("ttyS%02d at 0x%04x (irq = %d)\n", info->line, info->port, SERIAL);  }  /* reset the chip */#ifndef CONFIG_SERIAL_CONSOLE  dz_out(info, DZ_CSR, DZ_CLR);  while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR) ;  wbflush();    /* enable scanning */   dz_out(info, DZ_CSR, DZ_MSE); #endif    /* order matters here... the trick is that flags     is updated... in request_irq - to immediatedly obliterate     it is unwise. */  restore_flags(flags);   if (request_irq (SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0]))    panic ("Unable to register DZ interrupt\n");   return 0;}#ifdef CONFIG_SERIAL_CONSOLEstatic void dz_console_put_char (unsigned char ch){  unsigned long flags;  int  loops = 2500;  unsigned short tmp = ch;  /* this code sends stuff out to serial device - spinning its      wheels and waiting. */  /* force the issue - point it at lines[3]*/  dz_console=&multi[CONSOLE_LINE];  save_flags(flags);  cli();    /* spin our wheels */  while (((dz_in(dz_console,DZ_CSR) & DZ_TRDY) != DZ_TRDY) &&  loops--)    ;    /* Actually transmit the character. */  dz_out (dz_console, DZ_TDR, tmp);  restore_flags(flags); }/*  * ------------------------------------------------------------------- * dz_console_print () * * dz_console_print is registered for printk. * The console_lock must be held when we get here. * -------------------------------------------------------------------  */static void dz_console_print (struct console *cons, 			      const char *str, 			      unsigned int count){#ifdef DEBUG_DZ  prom_printf((char *)str);#endif  while (count--)     {    if (*str == '\n')	dz_console_put_char ('\r');      dz_console_put_char (*str++);  }}static int dz_console_wait_key(struct console *co){    return 0;}static kdev_t dz_console_device(struct console *c){	return MKDEV(TTY_MAJOR, 64 + c->index);}static int __init dz_console_setup(struct console *co, char *options){  	int	baud = 9600;	int	bits = 8;	int	parity = 'n';	int	cflag = CREAD | HUPCL | CLOCAL;	char	*s;	unsigned short mask,tmp;	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 |= DZ_B1200;		break;	case 2400:		cflag |= DZ_B2400;		break;	case 4800:		cflag |= DZ_B4800;		break;	case 9600:	default:		cflag |= DZ_B9600;		break;	}	switch(bits) {	case 7:		cflag |= DZ_CS7;		break;	default:	case 8:		cflag |= DZ_CS8;		break;	}	switch(parity) {	case 'o': case 'O':		cflag |= DZ_PARODD;		break;	case 'e': case 'E':		cflag |= DZ_PARENB;		break;	}	co->cflag = cflag;	/* TOFIX: force to console line */	dz_console = &multi[CONSOLE_LINE];    	if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) 	dz_console->port = KN01_DZ11_BASE;       	else        		dz_console->port = KN02_DZ11_BASE; 	dz_console->line = CONSOLE_LINE;	dz_out(dz_console, DZ_CSR, DZ_CLR);	while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR)	  ;	/* enable scanning */	dz_out(dz_console, DZ_CSR, DZ_MSE);         /*  Set up flags... */	dz_console->cflags = 0;	dz_console->cflags |= DZ_B9600;	dz_console->cflags |= DZ_CS8;	dz_console->cflags |= DZ_PARENB;	dz_out (dz_console, DZ_LPR, dz_console->cflags);	mask = 1 << dz_console->line;	tmp = dz_in (dz_console, DZ_TCR);       /* read the TX flag */	if (!(tmp & mask)) {	  tmp |= mask;                   /* set the TX flag */	  dz_out (dz_console, DZ_TCR, tmp); 	}		return 0;}static struct console dz_sercons = {	name:		"ttyS",	write:		dz_console_print,	device:		dz_console_device,	wait_key:	dz_console_wait_key,	setup:		dz_console_setup,	flags:		CON_CONSDEV | CON_PRINTBUFFER,	index:		CONSOLE_LINE,};void __init dz_serial_console_init(void){	register_console(&dz_sercons);}#endif /* ifdef CONFIG_SERIAL_CONSOLE */

⌨️ 快捷键说明

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