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

📄 rio_linux.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
  RIOServiceHost(p, HostP, irq);  rio_dprintk ( RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n",                 (int) ptr, HostP->Type);  clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks);  rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n",                irq, HostP->Ivec);   func_exit ();  return IRQ_HANDLED;}static void rio_pollfunc (unsigned long data){  func_enter ();  rio_interrupt (0, &p->RIOHosts[data], NULL);  p->RIOHosts[data].timer.expires = jiffies + rio_poll;  add_timer (&p->RIOHosts[data].timer);  func_exit ();}/* ********************************************************************** * *                Here are the routines that actually                     * *              interface with the generic_serial driver                  * * ********************************************************************** *//* Ehhm. I don't know how to fiddle with interrupts on the Specialix    cards. ....   Hmm. Ok I figured it out. You don't.  -- REW */static void rio_disable_tx_interrupts (void * ptr) {  func_enter();  /*  port->gs.flags &= ~GS_TX_INTEN; */  func_exit();}static void rio_enable_tx_interrupts (void * ptr) {  struct Port *PortP = ptr;  /* int hn; */  func_enter();  /* hn = PortP->HostP - p->RIOHosts;     rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);     rio_interrupt (-1,(void *) hn, NULL); */  RIOTxEnable((char *) PortP);  /*    * In general we cannot count on "tx empty" interrupts, although   * the interrupt routine seems to be able to tell the difference.    */  PortP->gs.flags &= ~GS_TX_INTEN;  func_exit();}static void rio_disable_rx_interrupts (void * ptr) {  func_enter();  func_exit();}static void rio_enable_rx_interrupts (void * ptr) {  /*  struct rio_port *port = ptr; */  func_enter();  func_exit();}/* Jeez. Isn't this simple?  */static int rio_get_CD (void * ptr) {  struct Port *PortP = ptr;  int rv;  func_enter();  rv = (PortP->ModemState & MSVR1_CD) != 0;  rio_dprintk (RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);    func_exit();    return rv;}/* Jeez. Isn't this simple? Actually, we can sync with the actual port   by just pushing stuff into the queue going to the port... */static int rio_chars_in_buffer (void * ptr) {  func_enter();  func_exit();    return 0;}/* Nothing special here... */static void rio_shutdown_port (void * ptr) {  struct Port *PortP;  func_enter();  PortP = (struct Port *)ptr;  PortP->gs.tty = NULL;#if 0  port->gs.flags &= ~ GS_ACTIVE;  if (!port->gs.tty) {    rio_dprintk (RIO_DBUG_TTY, "No tty.\n");    return;  }  if (!port->gs.tty->termios) {    rio_dprintk (RIO_DEBUG_TTY, "No termios.\n");    return;  }  if (port->gs.tty->termios->c_cflag & HUPCL) {    rio_setsignals (port, 0, 0);  }#endif  func_exit();}/* I haven't the foggiest why the decrement use count has to happen   here. The whole linux serial drivers stuff needs to be redesigned.   My guess is that this is a hack to minimize the impact of a bug   elsewhere. Thinking about it some more. (try it sometime) Try   running minicom on a serial port that is driven by a modularized   driver. Have the modem hangup. Then remove the driver module. Then   exit minicom.  I expect an "oops".  -- REW */static void rio_hungup (void *ptr){  struct Port *PortP;  func_enter();    PortP = (struct Port *)ptr;  PortP->gs.tty = NULL;  func_exit ();}/* The standard serial_close would become shorter if you'd wrap it like   this.    rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;} */static void rio_close (void *ptr){  struct Port *PortP;  func_enter ();  PortP = (struct Port *)ptr;  riotclose (ptr);  if(PortP->gs.count) {    printk (KERN_ERR "WARNING port count:%d\n", PortP->gs.count);    PortP->gs.count = 0;   }                  PortP->gs.tty = NULL;  func_exit ();}static int rio_fw_ioctl (struct inode *inode, struct file *filp,		         unsigned int cmd, unsigned long arg){  int rc = 0;  func_enter();  /* The "dev" argument isn't used. */  rc = riocontrol (p, 0, cmd, (void *)arg, capable(CAP_SYS_ADMIN));  func_exit ();  return rc;}extern int RIOShortCommand(struct rio_info *p, struct Port *PortP,               int command, int len, int arg);static int rio_ioctl (struct tty_struct * tty, struct file * filp,                      unsigned int cmd, unsigned long arg){  int rc;  struct Port *PortP;  int ival;  func_enter();  PortP = (struct Port *)tty->driver_data;  rc  = 0;  switch (cmd) {#if 0  case TIOCGSOFTCAR:    rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),                  (unsigned int *) arg);    break;#endif  case TIOCSSOFTCAR:    if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {      tty->termios->c_cflag =        (tty->termios->c_cflag & ~CLOCAL) |        (ival ? CLOCAL : 0);    }    break;  case TIOCGSERIAL:    if ((rc = verify_area(VERIFY_WRITE, (void *) arg,                          sizeof(struct serial_struct))) == 0)      rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg);    break;  case TCSBRK:    if ( PortP->State & RIO_DELETED ) {      rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n");      rc = -EIO;          } else {      if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) {         rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");         rc = -EIO;      }              }    break;  case TCSBRKP:    if ( PortP->State & RIO_DELETED ) {      rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n");      rc = -EIO;          } else {      int l;      l = arg?arg*100:250;      if (l > 255) l = 255;      if (RIOShortCommand(p, PortP, SBREAK, 2, arg?arg*100:250) == RIO_FAIL) {         rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");         rc = -EIO;      }              }    break;  case TIOCSSERIAL:    if ((rc = verify_area(VERIFY_READ, (void *) arg,                          sizeof(struct serial_struct))) == 0)      rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);    break;#if 0  /*   * note: these IOCTLs no longer reach here.  Use   * tiocmset/tiocmget driver methods instead.  The   * #if 0 disablement predates this comment.   */  case TIOCMGET:    if ((rc = verify_area(VERIFY_WRITE, (void *) arg,                          sizeof(unsigned int))) == 0) {      ival = rio_getsignals(port);      put_user(ival, (unsigned int *) arg);    }    break;  case TIOCMBIS:    if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {      rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),                           ((ival & TIOCM_RTS) ? 1 : -1));    }    break;  case TIOCMBIC:    if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {      rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),                           ((ival & TIOCM_RTS) ? 0 : -1));    }    break;  case TIOCMSET:    if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {      rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),                           ((ival & TIOCM_RTS) ? 1 : 0));    }    break;#endif  default:    rc = -ENOIOCTLCMD;    break;  }  func_exit();  return rc;}/* The throttle/unthrottle scheme for the Specialix card is different * from other drivers and deserves some explanation.  * The Specialix hardware takes care of XON/XOFF * and CTS/RTS flow control itself.  This means that all we have to * do when signalled by the upper tty layer to throttle/unthrottle is * to make a note of it here.  When we come to read characters from the * rx buffers on the card (rio_receive_chars()) we look to see if the * upper layer can accept more (as noted here in rio_rx_throt[]).  * If it can't we simply don't remove chars from the cards buffer.  * When the tty layer can accept chars, we again note that here and when * rio_receive_chars() is called it will remove them from the cards buffer. * The card will notice that a ports buffer has drained below some low * water mark and will unflow control the line itself, using whatever * flow control scheme is in use for that port. -- Simon Allen */static void rio_throttle (struct tty_struct * tty){  struct Port *port = (struct Port *)tty->driver_data;    func_enter();  /* If the port is using any type of input flow   * control then throttle the port.   */  if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) {    port->State |= RIO_THROTTLE_RX;  }  func_exit();}static void rio_unthrottle (struct tty_struct * tty){  struct Port *port = (struct Port *)tty->driver_data;  func_enter();  /* Always unthrottle even if flow control is not enabled on   * this port in case we disabled flow control while the port   * was throttled   */  port->State &= ~RIO_THROTTLE_RX;  func_exit();  return;}/* ********************************************************************** * *                    Here are the initialization routines.               * * ********************************************************************** */static struct vpd_prom *get_VPD_PROM (struct Host *hp){  static struct vpd_prom vpdp;  char *p;  int i;  func_enter();  rio_dprintk (RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",               hp->Caddr + RIO_VPD_ROM);  p = (char *) &vpdp;  for (i=0;i< sizeof (struct vpd_prom);i++)    *p++ = readb (hp->Caddr+RIO_VPD_ROM + i*2);      /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */  /* Terminate the identifier string.      *** requires one extra byte in struct vpd_prom *** */  *p++=0;   if (rio_debug & RIO_DEBUG_PROBE)    my_hd ((char *)&vpdp, 0x20);    func_exit();  return &vpdp;}static struct tty_operations rio_ops = {	.open  = riotopen,	.close = gs_close,	.write = gs_write,	.put_char = gs_put_char,	.flush_chars = gs_flush_chars,	.write_room = gs_write_room,	.chars_in_buffer = gs_chars_in_buffer,	.flush_buffer = gs_flush_buffer,	.ioctl = rio_ioctl,	.throttle = rio_throttle,	.unthrottle = rio_unthrottle,	.set_termios = gs_set_termios,	.stop = gs_stop,	.start = gs_start,	.hangup = gs_hangup,};static int rio_init_drivers(void){	int error = -ENOMEM;	rio_driver = alloc_tty_driver(256);	if (!rio_driver)		goto out;	rio_driver2 = alloc_tty_driver(256);	if (!rio_driver2)		goto out1;	func_enter();	rio_driver->owner = THIS_MODULE;	rio_driver->driver_name = "specialix_rio";	rio_driver->name = "ttySR";	rio_driver->major = RIO_NORMAL_MAJOR0;	rio_driver->type = TTY_DRIVER_TYPE_SERIAL;	rio_driver->subtype = SERIAL_TYPE_NORMAL;	rio_driver->init_termios = tty_std_termios;	rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	rio_driver->flags = TTY_DRIVER_REAL_RAW;	tty_set_operations(rio_driver, &rio_ops);	rio_driver2->owner = THIS_MODULE;	rio_driver2->driver_name = "specialix_rio";	rio_driver2->name = "ttySR";	rio_driver2->major = RIO_NORMAL_MAJOR1;	rio_driver2->type = TTY_DRIVER_TYPE_SERIAL;	rio_driver2->subtype = SERIAL_TYPE_NORMAL;	rio_driver2->init_termios = tty_std_termios;	rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	rio_driver2->flags = TTY_DRIVER_REAL_RAW;	tty_set_operations(rio_driver2, &rio_ops);	rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);	if ((error = tty_register_driver(rio_driver)))		goto out2;	if ((error = tty_register_driver(rio_driver2)))		goto out3;	func_exit();	return 0;out3:	tty_unregister_driver(rio_driver);out2:	put_tty_driver(rio_driver2);out1:	put_tty_driver(rio_driver);out:	printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n",	     error);	return 1;}static void * ckmalloc (int size)

⌨️ 快捷键说明

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