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

📄 dz.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
  dz_out (info, DZ_LPR, info->cflags);  if (info->xmit_buf) {               /* free Tx buffer */    free_page ((unsigned long)info->xmit_buf);    info->xmit_buf = 0;  }  if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {    tmp = dz_in (info, DZ_TCR);    if (tmp & DZ_MODEM_DTR) {      tmp &= ~DZ_MODEM_DTR;      dz_out (info, DZ_TCR, tmp);    }  }  if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);  info->is_initialized = 0;  restore_flags (flags);}/*  * ------------------------------------------------------------------- * change_speed () * * set the baud rate. * -------------------------------------------------------------------  */static void change_speed (struct dz_serial *info){  unsigned long flags;  unsigned cflag;  int baud;  if (!info->tty || !info->tty->termios) return;    save_flags (flags);  cli ();    info->cflags = info->line;  cflag = info->tty->termios->c_cflag;  switch (cflag & CSIZE) {  case CS5: info->cflags |= DZ_CS5; break;  case CS6: info->cflags |= DZ_CS6; break;  case CS7: info->cflags |= DZ_CS7; break;  case CS8:   default:  info->cflags |= DZ_CS8;  }  if (cflag & CSTOPB) info->cflags |= DZ_CSTOPB;  if (cflag & PARENB) info->cflags |= DZ_PARENB;  if (cflag & PARODD) info->cflags |= DZ_PARODD;    baud = tty_get_baud_rate (info->tty);  switch (baud) {  case 50  :  info->cflags |= DZ_B50;   break;  case 75  :  info->cflags |= DZ_B75;   break;  case 110 :  info->cflags |= DZ_B110;  break;  case 134 :  info->cflags |= DZ_B134;  break;   case 150 :  info->cflags |= DZ_B150;  break;  case 300 :  info->cflags |= DZ_B300;  break;   case 600 :  info->cflags |= DZ_B600;  break;  case 1200:  info->cflags |= DZ_B1200; break;   case 1800:  info->cflags |= DZ_B1800; break;  case 2000:  info->cflags |= DZ_B2000; break;  case 2400:  info->cflags |= DZ_B2400; break;  case 3600:  info->cflags |= DZ_B3600; break;   case 4800:  info->cflags |= DZ_B4800; break;  case 7200:  info->cflags |= DZ_B7200; break;   case 9600:   default  :  info->cflags |= DZ_B9600;   }  info->cflags |= DZ_RXENAB;  dz_out (info, DZ_LPR, info->cflags);  /* setup accept flag */  info->read_status_mask = DZ_OERR;  if (I_INPCK(info->tty))   info->read_status_mask |= (DZ_FERR | DZ_PERR);     /* characters to ignore */  info->ignore_status_mask = 0;  if (I_IGNPAR(info->tty))    info->ignore_status_mask |= (DZ_FERR | DZ_PERR);  restore_flags (flags);}/*  * ------------------------------------------------------------------- * dz_flush_char () * * Flush the buffer. * -------------------------------------------------------------------  */static void dz_flush_chars (struct tty_struct *tty){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;  unsigned long flags; if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf)    return; save_flags (flags); cli ();   dz_start (info->tty); restore_flags (flags);}/*  * ------------------------------------------------------------------- * dz_write () * * main output routine. * -------------------------------------------------------------------  */static int dz_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;  unsigned long flags;  int c, ret = 0;  if (!tty ) return ret;  if (!info->xmit_buf) return ret;  if (!tmp_buf) tmp_buf = tmp_buffer;  if (from_user) {    down (&tmp_buf_sem);    while (1) {      c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));      if (c <= 0) break;      c -= copy_from_user (tmp_buf, buf, c);      if (!c) {        if (!ret) ret = -EFAULT;        break;      }      save_flags (flags);      cli ();      c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));      memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);      info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));      info->xmit_cnt += c;      restore_flags(flags);      buf += c;      count -= c;      ret += c;    }        up (&tmp_buf_sem);  } else {    while (1) {      save_flags (flags);      cli ();           c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));      if (c <= 0) {        restore_flags (flags);        break;      }      memcpy (info->xmit_buf + info->xmit_head, buf, c);      info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));      info->xmit_cnt += c;      restore_flags (flags);      buf += c;      count -= c;      ret += c;    }  }  if (info->xmit_cnt)    {      if (!tty->stopped) 	{	  if (!tty->hw_stopped)	    {	      dz_start (info->tty);	    }	}    }  return ret;}/*  * ------------------------------------------------------------------- * dz_write_room () * * compute the amount of space available for writing. * -------------------------------------------------------------------  */static int dz_write_room (struct tty_struct *tty){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;  int ret;                                  ret = DZ_XMIT_SIZE - info->xmit_cnt - 1;  if (ret < 0) ret = 0;  return ret;}/*  * ------------------------------------------------------------------- * dz_chars_in_buffer () * * compute the amount of char left to be transmitted * -------------------------------------------------------------------  */static int dz_chars_in_buffer (struct tty_struct *tty){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;    return info->xmit_cnt;}/*  * ------------------------------------------------------------------- * dz_flush_buffer () * * Empty the output buffer * -------------------------------------------------------------------  */static void dz_flush_buffer (struct tty_struct *tty){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;                                  cli ();  info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;  sti ();  wake_up_interruptible (&tty->write_wait);  if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)    (tty->ldisc.write_wakeup)(tty);}/* * ------------------------------------------------------------ * dz_throttle () and dz_unthrottle () *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled (or not). * ------------------------------------------------------------ */static void dz_throttle (struct tty_struct *tty){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;    if (I_IXOFF(tty))    info->x_char = STOP_CHAR(tty);}static void dz_unthrottle (struct tty_struct *tty){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;    if (I_IXOFF(tty)) {    if (info->x_char)      info->x_char = 0;    else      info->x_char = START_CHAR(tty);  }}static void dz_send_xchar (struct tty_struct *tty, char ch){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;  info->x_char = ch;  if (ch) dz_start (info->tty);}/* * ------------------------------------------------------------ * rs_ioctl () and friends * ------------------------------------------------------------ */static int get_serial_info (struct dz_serial *info, struct serial_struct *retinfo){  struct serial_struct tmp;    if (!retinfo)    return -EFAULT;  memset (&tmp, 0, sizeof(tmp));  tmp.type = info->type;  tmp.line = info->line;  tmp.port = info->port;  tmp.irq = SERIAL;  tmp.flags = info->flags;  tmp.baud_base = info->baud_base;  tmp.close_delay = info->close_delay;  tmp.closing_wait = info->closing_wait;    return copy_to_user (retinfo, &tmp, sizeof(*retinfo));}static int set_serial_info (struct dz_serial *info, struct serial_struct *new_info){  struct serial_struct new_serial;  struct dz_serial old_info;  int retval = 0;  if (!new_info)    return -EFAULT;  copy_from_user (&new_serial, new_info, sizeof(new_serial));  old_info = *info;  if (!suser())    return -EPERM;  if (info->count > 1)    return -EBUSY;  /*   * OK, past this point, all the error checking has been done.   * At this point, we start making changes.....   */    info->baud_base = new_serial.baud_base;  info->type = new_serial.type;  info->close_delay = new_serial.close_delay;  info->closing_wait = new_serial.closing_wait;  retval = startup (info);  return retval;}/* * get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically *          is emptied.  On bus types like RS485, the transmitter must *          release the bus after transmitting. This must be done when *          the transmit shift register is empty, not be done when the *          transmit holding register is empty.  This functionality *          allows an RS485 driver to be written in user space.  */static int get_lsr_info (struct dz_serial *info, unsigned int *value){  unsigned short status = dz_in (info, DZ_LPR);  return put_user (status, value);}/* * This routine sends a break character out the serial port. */static void send_break (struct dz_serial *info, int duration){  unsigned long flags;  unsigned short tmp, mask;  if (!info->port)    return;  mask = 1 << info->line;  tmp = dz_in (info, DZ_TCR);  tmp |= mask;  current->state = TASK_INTERRUPTIBLE;  save_flags (flags);  cli();    dz_out (info, DZ_TCR, tmp);    schedule_timeout(duration);    tmp &= ~mask;  dz_out (info, DZ_TCR, tmp);    restore_flags (flags);}static int dz_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg){  int error;  struct dz_serial * info = (struct dz_serial *)tty->driver_data;  int retval;  if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&      (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&      (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {    if (tty->flags & (1 << TTY_IO_ERROR))      return -EIO;  }  switch (cmd) {  case TCSBRK:    /* SVID version: non-zero arg --> no break */    retval = tty_check_change (tty);    if (retval)      return retval;    tty_wait_until_sent (tty, 0);    if (!arg)      send_break (info, HZ/4); /* 1/4 second */    return 0;  case TCSBRKP:   /* support for POSIX tcsendbreak() */    retval = tty_check_change (tty);    if (retval)      return retval;    tty_wait_until_sent (tty, 0);    send_break (info, arg ? arg*(HZ/10) : HZ/4);    return 0;  case TIOCGSOFTCAR:    error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(long));    if (error)      return error;    put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);    return 0;  case TIOCSSOFTCAR:    error = get_user (arg, (unsigned long *)arg);    if (error)      return error;    tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));    return 0;  case TIOCGSERIAL:    error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct));    if (error)      return error;    return get_serial_info (info, (struct serial_struct *)arg);  case TIOCSSERIAL:    return set_serial_info (info, (struct serial_struct *) arg);  case TIOCSERGETLSR: /* Get line status register */    error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(unsigned int));    if (error)      return error;    else      return get_lsr_info (info, (unsigned int *)arg);  case TIOCSERGSTRUCT:    error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct dz_serial));    if (error)      return error;    copy_to_user((struct dz_serial *)arg, info, sizeof(struct dz_serial));    return 0;      default:    return -ENOIOCTLCMD;  }  return 0;}static void dz_set_termios (struct tty_struct *tty,			    struct termios *old_termios){  struct dz_serial *info = (struct dz_serial *)tty->driver_data;  if (tty->termios->c_cflag == old_termios->c_cflag)    return;  change_speed (info);  if ((old_termios->c_cflag & CRTSCTS) &&      !(tty->termios->c_cflag & CRTSCTS)) {    tty->hw_stopped = 0;    dz_start (tty);  }}/* * ------------------------------------------------------------ * dz_close() *  * This routine is called when the serial port gets closed.  First, we * wait for the last remaining data to be sent.  Then, we turn off * the transmit enable and receive enable flags. * ------------------------------------------------------------ */static void dz_close (struct tty_struct *tty, struct file *filp){  struct dz_serial * info = (struct dz_serial *)tty->driver_data;  unsigned long flags;  if (!info) return;          save_flags (flags);   cli();          if (tty_hung_up_p (filp)) {    restore_flags (flags);    return;  }  if ((tty->count == 1) && (info->count != 1)) {    /*     * Uh, oh.  tty->count is 1, which means that the tty     * structure will be freed.  Info->count should always     * be one in these conditions.  If it's greater than     * one, we've got real problems, since it means the     * serial port won't be shutdown.     */    printk("dz_close: bad serial port count; tty->count is 1, "                       "info->count is %d\n", info->count);                info->count = 1;  }

⌨️ 快捷键说明

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