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

📄 rs232.c

📁 minix3.1.1源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  switch (tp->tty_termios.c_cflag & CSIZE) {	/* XXX - are U_Dn like CSn? */	case CS5:	line_controls |= U_D5; break;	case CS5:	line_controls |= U_D6; break;	case CS5:	line_controls |= U_D7; break;	case CS5:	line_controls |= U_D8; break;  }  lock();  MFP->mf_ucr = line_controls;  MFP->mf_tddr = divisor;  unlock();#endif /* MACHINE == ATARI */}/*===========================================================================* *				rs_init					     * *===========================================================================*/PUBLIC void rs_init(tp)tty_t *tp;			/* which TTY */{  int dummy;/* Initialize RS232 for one line. */  register rs232_t *rs;  int line;#if (MACHINE == IBM_PC)  port_t this_8250;  int irq;  long v;#endif  /* Associate RS232 and TTY structures. */  line = tp - &tty_table[NR_CONS];  rs = tp->tty_priv = &rs_lines[line];  rs->tty = tp;  /* Set up input queue. */  rs->ihead = rs->itail = rs->ibuf;#if (MACHINE == IBM_PC)  /* Precalculate port numbers for speed. Magic numbers in the code (once). */  this_8250 = addr_8250[line];  rs->xmit_port = this_8250 + 0;  rs->recv_port = this_8250 + 0;  rs->div_low_port = this_8250 + 0;  rs->div_hi_port = this_8250 + 1;  rs->int_enab_port = this_8250 + 1;  rs->int_id_port = this_8250 + 2;  rs->line_ctl_port = this_8250 + 3;  rs->modem_ctl_port = this_8250 + 4;  rs->line_status_port = this_8250 + 5;  rs->modem_status_port = this_8250 + 6;#endif  /* Set up the hardware to a base state, in particular   *	o turn off DTR (MC_DTR) to try to stop the external device.   *	o be careful about the divisor latch.  Some BIOS's leave it enabled   *	  here and that caused trouble (no interrupts) in version 1.5 by   *	  hiding the interrupt enable port in the next step, and worse trouble   *	  (continual interrupts) in an old version by hiding the receiver   *	  port in the first interrupt.  Call rs_ioctl() early to avoid this.   *	o disable interrupts at the chip level, to force an edge transition   *	  on the 8259 line when interrupts are next enabled and active.   *	  RS232 interrupts are guaranteed to be disabled now by the 8259   *	  mask, but there used to be trouble if the mask was set without   *	  handling a previous interrupt.   */  istop(rs);			/* sets modem_ctl_port */  rs_config(rs);#if (MACHINE == IBM_PC)  sys_outb(rs->int_enab_port, 0);#endif  /* Clear any harmful leftover interrupts.  An output interrupt is harmless   * and will occur when interrupts are enabled anyway.  Set up the output   * queue using the status from clearing the modem status interrupt.   */#if (MACHINE == IBM_PC)  sys_inb(rs->line_status_port, &dummy);  sys_inb(rs->recv_port, &dummy);#endif  rs->ostate = devready(rs) | ORAW | OSWREADY;	/* reads modem_ctl_port */  rs->ohead = rs->otail = rs->obuf;#if (MACHINE == IBM_PC)  /* Enable interrupts for both interrupt controller and device. */  irq = (line & 1) == 0 ? RS232_IRQ : SECONDARY_IRQ;  rs->irq = irq;  rs->irq_hook_id = rs->irq;	/* call back with irq line number */  if (sys_irqsetpolicy(irq, IRQ_REENABLE, &rs->irq_hook_id) != OK) {  	printf("RS232: Couldn't obtain hook for irq %d\n", irq);  } else {  	if (sys_irqenable(&rs->irq_hook_id) != OK)  {  		printf("RS232: Couldn't enable irq %d (hooked)\n", irq);  	}  }  rs_irq_set |= (1 << irq);  sys_outb(rs->int_enab_port, IE_LINE_STATUS_CHANGE | IE_MODEM_STATUS_CHANGE				| IE_RECEIVER_READY | IE_TRANSMITTER_READY);#else /* MACHINE == ATARI */  /* Initialize the 68901 chip, then enable interrupts. */  MFP->mf_scr = 0x00;  MFP->mf_tcdcr |= T_Q004;  MFP->mf_rsr = R_ENA;  MFP->mf_tsr = T_ENA;  MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^		 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));  MFP->mf_ddr = (MFP->mf_ddr & ~ (IO_SCTS|IO_SDCD));  MFP->mf_iera |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);  MFP->mf_imra |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);  MFP->mf_ierb |= (IB_SCTS|IB_SDCD);  MFP->mf_imrb |= (IB_SCTS|IB_SDCD);#endif /* MACHINE == ATARI */  /* Fill in TTY function hooks. */  tp->tty_devread = rs_read;  tp->tty_devwrite = rs_write;  tp->tty_echo = rs_echo;  tp->tty_icancel = rs_icancel;  tp->tty_ocancel = rs_ocancel;  tp->tty_ioctl = rs_ioctl;  tp->tty_break = rs_break;  tp->tty_close = rs_close;  /* Tell external device we are ready. */  istart(rs);}/*===========================================================================* *				rs_interrupt				     * *===========================================================================*/PUBLIC void rs_interrupt(m)message *m;			/* which TTY */{	unsigned long irq_set;	int i;	rs232_t *rs;	irq_set= m->NOTIFY_ARG;	for (i= 0, rs = rs_lines; i<NR_RS_LINES; i++, rs++)	{		if (irq_set & (1 << rs->irq))			rs232_handler(rs);	}}/*===========================================================================* *				rs_icancel				     * *===========================================================================*/PRIVATE int rs_icancel(tp, dummy)tty_t *tp;			/* which TTY */int dummy;{/* Cancel waiting input. */  rs232_t *rs = tp->tty_priv;  lock();  rs->icount = 0;  rs->itail = rs->ihead;  istart(rs);  unlock();  return 0;	/* dummy */}/*===========================================================================* *				rs_ocancel				     * *===========================================================================*/PRIVATE int rs_ocancel(tp, dummy)tty_t *tp;			/* which TTY */int dummy;{/* Cancel pending output. */  rs232_t *rs = tp->tty_priv;  lock();  rs->ostate &= ~(ODONE | OQUEUED);  rs->ocount = 0;  rs->otail = rs->ohead;  unlock();  return 0;	/* dummy */}/*===========================================================================* *				rs_read					     * *===========================================================================*/PRIVATE int rs_read(tp, try)tty_t *tp;			/* which tty */int try;{/* Process characters from the circular input buffer. */  rs232_t *rs = tp->tty_priv;  int icount, count, ostate;  if (!(tp->tty_termios.c_cflag & CLOCAL)) {  	if (try) return 1;	/* Send a SIGHUP if hangup detected. */	lock();	ostate = rs->ostate;	rs->ostate &= ~ODEVHUP;		/* save ostate, clear DEVHUP */	unlock();	if (ostate & ODEVHUP) {		sigchar(tp, SIGHUP);		tp->tty_termios.c_ospeed = B0;	/* Disable further I/O. */		return;	}  }  if (try) {  	if (rs->icount > 0)	  	return 1;	return 0;  }  while ((count = rs->icount) > 0) {	icount = bufend(rs->ibuf) - rs->itail;	if (count > icount) count = icount;	/* Perform input processing on (part of) the input buffer. */	if ((count = in_process(tp, rs->itail, count)) == 0) break;	lock();			/* protect interrupt sensitive variables */	rs->icount -= count;	if (!rs->idevready && rs->icount < RS_ILOWWATER) istart(rs);	unlock();	if ((rs->itail += count) == bufend(rs->ibuf)) rs->itail = rs->ibuf;  }}/*===========================================================================* *				rs_ostart				     * *===========================================================================*/PRIVATE void rs_ostart(rs)rs232_t *rs;			/* which rs line */{/* Tell RS232 there is something waiting in the output buffer. */  rs->ostate |= OQUEUED;  if (txready(rs)) out_int(rs);}/*===========================================================================* *				rs_break				     * *===========================================================================*/PRIVATE int rs_break(tp, dummy)tty_t *tp;			/* which tty */int dummy;{/* Generate a break condition by setting the BREAK bit for 0.4 sec. */  rs232_t *rs = tp->tty_priv;  int line_controls;  sys_inb(rs->line_ctl_port, &line_controls);  sys_outb(rs->line_ctl_port, line_controls | LC_BREAK);  /* XXX */  /* milli_delay(400); */				/* ouch */  printf("RS232 break\n");  sys_outb(rs->line_ctl_port, line_controls);  return 0;	/* dummy */}/*===========================================================================* *				rs_close				     * *===========================================================================*/PRIVATE int rs_close(tp, dummy)tty_t *tp;			/* which tty */int dummy;{/* The line is closed; optionally hang up. */  rs232_t *rs = tp->tty_priv;  int r;  if (tp->tty_termios.c_cflag & HUPCL) {	sys_outb(rs->modem_ctl_port, MC_OUT2 | MC_RTS);  }  return 0;	/* dummy */}/* Low level (interrupt) routines. */#if (MACHINE == IBM_PC)/*===========================================================================* *				rs232_handler				     * *===========================================================================*/PRIVATE void rs232_handler(rs)struct rs232 *rs;{/* Interrupt hander for RS232. */  while (TRUE) {  	int v;	/* Loop to pick up ALL pending interrupts for device.	 * This usually just wastes time unless the hardware has a buffer	 * (and then we have to worry about being stuck in the loop too long).	 * Unfortunately, some serial cards lock up without this.	 */	sys_inb(rs->int_id_port, &v);	switch (v) {	case IS_RECEIVER_READY:		in_int(rs);		continue;	case IS_TRANSMITTER_READY:		out_int(rs);		continue;	case IS_MODEM_STATUS_CHANGE:		modem_int(rs);		continue;	case IS_LINE_STATUS_CHANGE:		line_int(rs);		continue;	}	return;  }}#endif /* MACHINE == IBM_PC */#if (MACHINE == ATARI)/*===========================================================================* *				siaint					     * *===========================================================================*/PRIVATE void siaint(type)int    type;	       /* interrupt type */{/* siaint is the rs232 interrupt procedure for Atari ST's. For ST there are * as much as 5 interrupt lines used for rs232. The trap type byte left on the * stack by the assembler interrupt handler identifies the interrupt cause. */  register unsigned char  code;  register rs232_t *rs = &rs_lines[0];  int s = lock();  switch (type & 0x00FF)  {	case 0x00:	       /* receive buffer full */		in_int(rs);		break;	case 0x01:	       /* receive error */		line_int(rs);		break;	case 0x02:	       /* transmit buffer empty */		out_int(rs);		break;	case 0x03:	       /* transmit error */		code = MFP->mf_tsr;		if (code & ~(T_ENA | T_UE | T_EMPTY))		{		    printf("sia: transmit error: status=%x\r\n", code);		    /* MFP->mf_udr = lastchar; */ /* retry */		}		break;	case 0x04:		/* modem lines change */		modem_int(rs);		break;  }  restore(s);}#endif /* MACHINE == ATARI *//*===========================================================================* *				in_int					     * *===========================================================================*/PRIVATE void in_int(rs)register rs232_t *rs;		/* line with input interrupt */{/* Read the data which just arrived. * If it is the oxoff char, clear OSWREADY, else if OSWREADY was clear, set * it and restart output (any char does this, not just xon). * Put data in the buffer if room, otherwise discard it. * Set a flag for the clock interrupt handler to eventually notify TTY. */  int c;#if (MACHINE == IBM_PC)  sys_inb(rs->recv_port, &c);#else /* MACHINE == ATARI */  c = MFP->mf_udr;#endif  if (!(rs->ostate & ORAW)) {	if (c == rs->oxoff) {		rs->ostate &= ~OSWREADY;	} else	if (!(rs->ostate & OSWREADY)) {		rs->ostate |= OSWREADY;		if (txready(rs)) out_int(rs);	}  }  if (rs->icount == buflen(rs->ibuf)) return;	/* input buffer full, discard */  if (++rs->icount == RS_IHIGHWATER && rs->idevready) istop(rs);  *rs->ihead = c;  if (++rs->ihead == bufend(rs->ibuf)) rs->ihead = rs->ibuf;  if (rs->icount == 1) {	rs->tty->tty_events = 1;	force_timeout();  }}/*===========================================================================* *				line_int				     * *===========================================================================*/PRIVATE void line_int(rs)register rs232_t *rs;		/* line with line status interrupt */{/* Check for and record errors. */#if (MACHINE == IBM_PC)  sys_inb(rs->line_status_port, &rs->lstatus);#else /* MACHINE == ATARI */  rs->lstatus = MFP->mf_rsr;  MFP->mf_rsr &= R_ENA;  rs->pad = MFP->mf_udr;	/* discard char in case of LS_OVERRUN_ERR */#endif /* MACHINE == ATARI */  if (rs->lstatus & LS_FRAMING_ERR) ++rs->framing_errors;  if (rs->lstatus & LS_OVERRUN_ERR) ++rs->overrun_errors;  if (rs->lstatus & LS_PARITY_ERR) ++rs->parity_errors;  if (rs->lstatus & LS_BREAK_INTERRUPT) ++rs->break_interrupts;}/*===========================================================================* *				modem_int				     * *===========================================================================*/PRIVATE void modem_int(rs)register rs232_t *rs;		/* line with modem interrupt */{/* Get possibly new device-ready status, and clear ODEVREADY if necessary. * If the device just became ready, restart output. */#if (MACHINE == ATARI)  /* Set active edge interrupt so that next change causes a new interrupt */  MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^		 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));#endif  if (devhup(rs)) {	rs->ostate |= ODEVHUP;	rs->tty->tty_events = 1;	force_timeout();  }  if (!devready(rs))	rs->ostate &= ~ODEVREADY;  else if (!(rs->ostate & ODEVREADY)) {	rs->ostate |= ODEVREADY;	if (txready(rs)) out_int(rs);  }}/*===========================================================================* *				out_int					    * *===========================================================================*/PRIVATE void out_int(rs)register rs232_t *rs;		/* line with output interrupt */{/* If there is output to do and everything is ready, do it (local device is * known ready). * Notify TTY when the buffer goes empty. */  if (rs->ostate >= (ODEVREADY | OQUEUED | OSWREADY)) {	/* Bit test allows ORAW and requires the others. */#if (MACHINE == IBM_PC)	sys_outb(rs->xmit_port, *rs->otail);#else /* MACHINE == ATARI */	MFP->mf_udr = *rs->otail;#endif	if (++rs->otail == bufend(rs->obuf)) rs->otail = rs->obuf;	if (--rs->ocount == 0) {		rs->ostate ^= (ODONE | OQUEUED);  /* ODONE on, OQUEUED off */		rs->tty->tty_events = 1;		force_timeout();	} else	if (rs->ocount == RS_OLOWWATER) {	/* running low? */		rs->tty->tty_events = 1;		force_timeout();	}  }}#endif /* NR_RS_LINES > 0 */

⌨️ 快捷键说明

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