home *** CD-ROM | disk | FTP | other *** search
- #
- /*
- */
-
- /*
- * DH-11 driver
- * This driver calls on the DHDM driver.
- * If the DH has no DM11-BB, then the latter will
- * be fake. To insure loading of the correct DM code,
- * lib2 should have dhdm.o, dh.o and dhfdm.o in that order.
- */
-
- #include "../param.h"
- #include "../conf.h"
- #include "../user.h"
- #include "../tty.h"
- #include "../proc.h"
-
- #define DHADDR 0160020
- #define NDH11 16 /* number of lines */
- #define DHNCH 8 /* max number of DMA chars */
-
- struct tty dh11[NDH11];
- /*
- * Place from which to do DMA on output
- */
- char dh_clist[NDH11][DHNCH];
-
- /*
- * Used to communicate the number of lines to the DM
- */
- int ndh11 NDH11;
-
- /*
- * Hardware control bits
- */
- #define BITS6 01
- #define BITS7 02
- #define BITS8 03
- #define TWOSB 04
- #define PENABLE 020
- /* DEC manuals incorrectly say this bit causes generation of even parity. */
- #define OPAR 040
- #define HDUPLX 040000
-
- #define IENABLE 030100
- #define PERROR 010000
- #define FRERROR 020000
- #define XINT 0100000
- #define SSPEED 7 /* standard speed: 300 baud */
-
- /*
- * Software copy of last dhbar
- */
- int dhsar;
-
- struct dhregs {
- int dhcsr;
- int dhnxch;
- int dhlpr;
- int dhcar;
- int dhbcr;
- int dhbar;
- int dhbreak;
- int dhsilo;
- };
-
- /*
- * Open a DH11 line.
- */
- dhopen(dev, flag)
- {
- register struct tty *tp;
- extern dhstart();
-
- if (dev.d_minor >= NDH11) {
- u.u_error = ENXIO;
- return;
- }
- tp = &dh11[dev.d_minor];
- tp->t_addr = dhstart;
- tp->t_dev = dev;
- DHADDR->dhcsr =| IENABLE;
- tp->t_state =| WOPEN|SSTART;
- if ((tp->t_state&ISOPEN) == 0) {
- tp->t_erase = CERASE;
- tp->t_kill = CKILL;
- tp->t_speeds = SSPEED | (SSPEED<<8);
- tp->t_flags = ODDP|EVENP|ECHO;
- dhparam(tp);
- }
- dmopen(dev);
- tp->t_state =& ~WOPEN;
- tp->t_state =| ISOPEN;
- if (u.u_procp->p_ttyp == 0)
- u.u_procp->p_ttyp = tp;
- }
-
- /*
- * Close a DH11 line.
- */
- dhclose(dev)
- {
- register struct tty *tp;
-
- tp = &dh11[dev.d_minor];
- dmclose(dev);
- tp->t_state =& (CARR_ON|SSTART);
- wflushtty(tp);
- }
-
- /*
- * Read from a DH11 line.
- */
- dhread(dev)
- {
- ttread(&dh11[dev.d_minor]);
- }
-
- /*
- * write on a DH11 line
- */
- dhwrite(dev)
- {
- ttwrite(&dh11[dev.d_minor]);
- }
-
- /*
- * DH11 receiver interrupt.
- */
- dhrint()
- {
- register struct tty *tp;
- register int c;
-
- while ((c = DHADDR->dhnxch) < 0) { /* char. present */
- tp = &dh11[(c>>8)&017];
- if (tp >= &dh11[NDH11])
- continue;
- if((tp->t_state&ISOPEN)==0 || (c&PERROR)) {
- wakeup(tp);
- continue;
- }
- if (c&FRERROR) /* break */
- if (tp->t_flags&RAW)
- c = 0; /* null (for getty) */
- else
- c = 0177; /* DEL (intr) */
- ttyinput(c, tp);
- }
- }
-
- /*
- * stty/gtty for DH11
- */
- dhsgtty(dev, av)
- int *av;
- {
- register struct tty *tp;
- register r;
-
- tp = &dh11[dev.d_minor];
- if (ttystty(tp, av))
- return;
- dhparam(tp);
- }
-
- /*
- * Set parameters from open or stty into the DH hardware
- * registers.
- */
- dhparam(atp)
- struct tty *atp;
- {
- register struct tty *tp;
- register int lpr;
-
- tp = atp;
- spl5();
- DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE;
- /*
- * Hang up line?
- */
- if (tp->t_speeds.lobyte==0) {
- tp->t_flags =| HUPCL;
- dmclose(tp->t_dev);
- return;
- }
- lpr = (tp->t_speeds.hibyte<<10) | (tp->t_speeds.lobyte<<6);
- if (tp->t_speeds.lobyte == 4) /* 134.5 baud */
- lpr =| BITS6|PENABLE|HDUPLX; else
- if (tp->t_flags&EVENP)
- if (tp->t_flags&ODDP)
- lpr =| BITS8; else
- lpr =| BITS7|PENABLE; else
- lpr =| BITS7|OPAR|PENABLE;
- if (tp->t_speeds.lobyte == 3) /* 110 baud */
- lpr =| TWOSB;
- DHADDR->dhlpr = lpr;
- spl0();
- }
-
- /*
- * DH11 transmitter interrupt.
- * Restart each line which used to be active but has
- * terminated transmission since the last interrupt.
- */
- dhxint()
- {
- register struct tty *tp;
- register ttybit, bar;
-
- bar = dhsar & ~DHADDR->dhbar;
- DHADDR->dhcsr =& ~XINT;
- ttybit = 1;
- for (tp = dh11; bar; tp++) {
- if(bar&ttybit) {
- dhsar =& ~ttybit;
- bar =& ~ttybit;
- tp->t_state =& ~BUSY;
- dhstart(tp);
- }
- ttybit =<< 1;
- }
- }
-
- /*
- * Start (restart) transmission on the given DH11 line.
- */
- dhstart(atp)
- struct tty *atp;
- {
- extern ttrstrt();
- register c, nch;
- register struct tty *tp;
- int sps;
- char *cp;
-
- sps = PS->integ;
- spl5();
- tp = atp;
- /*
- * If it's currently active, or delaying,
- * no need to do anything.
- */
- if (tp->t_state&(TIMEOUT|BUSY))
- goto out;
- /*
- * t_char is a delay indicator which may have been
- * left over from the last start.
- * Arrange for the delay.
- */
- if (c = tp->t_char) {
- tp->t_char = 0;
- timeout(ttrstrt, tp, (c&0177)+6);
- tp->t_state =| TIMEOUT;
- goto out;
- }
- cp = dh_clist[tp->t_dev.d_minor];
- nch = 0;
- /*
- * Copy DHNCH characters, or up to a delay indicator,
- * to the DMA area.
- */
- while (nch > -DHNCH && (c = getc(&tp->t_outq))>=0) {
- if (c >= 0200) {
- tp->t_char = c;
- break;
- }
- *cp++ = c;
- nch--;
- }
- /*
- * If the writer was sleeping on output overflow,
- * wake him when low tide is reached.
- */
- if (tp->t_outq.c_cc<=TTLOWAT && tp->t_state&ASLEEP) {
- tp->t_state =& ~ASLEEP;
- wakeup(&tp->t_outq);
- }
- /*
- * If any characters were set up, start transmission;
- * otherwise, check for possible delay.
- */
- if (nch) {
- DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE;
- DHADDR->dhcar = cp+nch;
- DHADDR->dhbcr = nch;
- c = 1<<tp->t_dev.d_minor;
- DHADDR->dhbar =| c;
- dhsar =| c;
- tp->t_state =| BUSY;
- } else if (c = tp->t_char) {
- tp->t_char = 0;
- timeout(ttrstrt, tp, (c&0177)+6);
- tp->t_state =| TIMEOUT;
- }
- out:
- PS->integ = sps;
- }
-