* Loaded with dhdm if there are DM-11's otherwise with dhfdm.
* NB: WE HAVEN'T TESTED dhdm CODE ON VAX.
/* This is to block the clock because we are using the silos */
/* SHOULD RATHER QUEUE SOFTWARE INTERRUPT AT CLOCK TIME */
#define UBACVT(x,uban) (cbase[uban] + (short)((x)-(char *)cfree))
int dhcntrlr(), dhslave(), dhrint(), dhxint();
struct uba_dinfo
*dhinfo
[NDH11
];
int (*dhivec
[])() = { dhrint
, dhxint
, 0 }; /* note: order matters */
struct uba_driver dhdriver
=
{ dhcntrlr
, dhslave
, (int (*)())0, 0, 0, dhstd
, dhinfo
, dhivec
};
struct tty dh11
[NDH11
*16];
/* DEC manuals incorrectly say this bit causes generation of even parity. */
#define SSPEED 7 /* standard speed: 300 baud */
#define TURNON 03 /* CD lead + line enable */
#define TURNOFF 01 /* line enable */
#define DTR 02 /* data terminal ready */
#define RQS 04 /* request to send */
* Software copy of last dhbar
((struct device
*)reg
)->un
.dhcsr
|= IENABLE
;
/* get it to interrupt */
dhslave(ui
, reg
, slaveno
)
/* could fill in local tables for the dh here */
register struct device
*addr
;
register struct uba_dinfo
*ui
;
if (unit
>= NDH11
*16 || (ui
= dhinfo
[dh
])->ui_alive
== 0) {
addr
= (struct device
*)ui
->ui_addr
;
tp
->t_addr
= (caddr_t
)addr
;
if (dh_ubinfo
[ui
->ui_ubanum
]) {
/* 512+ is a kludge to try to get around a hardware problem */
dh_ubinfo
[ui
->ui_ubanum
] =
512+NCLIST
*sizeof(struct cblock
), 0);
cbase
[ui
->ui_ubanum
] = (short)dh_ubinfo
[ui
->ui_ubanum
];
if ((tp
->t_state
&ISOPEN
) == 0) {
tp
->t_flags
= ODDP
|EVENP
|ECHO
;
if (tp
->t_state
&XCLUDE
&& u
.u_uid
!=0) {
(*linesw
[tp
->t_line
].l_open
)(dev
, tp
);
(*linesw
[tp
->t_line
].l_close
)(tp
);
* Turn of the break bit in case somebody did a TIOCSBRK without
((struct device
*)(tp
->t_addr
))->dhbreak
&= ~(1<<(unit
&017));
if (tp
->t_state
&HUPCLS
|| (tp
->t_state
&ISOPEN
)==0)
dmctl(unit
, TURNOFF
, DMSET
);
(*linesw
[tp
->t_line
].l_read
)(tp
);
(*linesw
[tp
->t_line
].l_write
)(tp
);
* DH11 receiver interrupt.
register struct device
*addr
;
register struct tty
*tp0
;
register struct uba_dinfo
*ui
;
s
= spl6(); /* see comment in clock.c */
addr
= (struct device
*)ui
->ui_addr
;
while ((c
= addr
->dhnxch
) < 0) { /* char. present */
if (tp
>= &dh11
[NDH11
*16])
if((tp
->t_state
&ISOPEN
)==0) {
if ((tp
->t_flags
&(EVENP
|ODDP
))==EVENP
|| (tp
->t_flags
&(EVENP
|ODDP
))==ODDP
)
if (c
&FRERROR
) /* break */
c
= 0; /* null (for getty) */
if (tp
->t_line
== NETLDISC
) {
(*linesw
[tp
->t_line
].l_rint
)(c
,tp
);
dhioctl(dev
, cmd
, addr
, flag
)
register unit
= minor(dev
);
cmd
= (*linesw
[tp
->t_line
].l_ioctl
)(tp
, cmd
, addr
);
if (ttioctl(tp
, cmd
, addr
, flag
)) {
if (cmd
==TIOCSETP
||cmd
==TIOCSETN
)
((struct device
*)(tp
->t_addr
))->dhbreak
|= 1<<(unit
&017);
((struct device
*)(tp
->t_addr
))->dhbreak
&= ~(1<<(unit
&017));
dmctl(unit
, DTR
|RQS
, DMBIS
);
dmctl(unit
, DTR
|RQS
, DMBIC
);
* Set parameters from open or stty into the DH hardware
register struct device
*addr
;
addr
= (struct device
*)tp
->t_addr
;
addr
->un
.dhcsrl
= (unit
&017) | IENAB
;
dmctl(unit
, TURNOFF
, DMSET
);
lpar
= ((tp
->t_ospeed
)<<10) | ((tp
->t_ispeed
)<<6);
if ((tp
->t_ispeed
) == 4) /* 134.5 baud */
lpar
|= BITS6
|PENABLE
|HDUPLX
;
else if ((tp
->t_flags
&RAW
) || (tp
->t_local
&LLITOUT
))
if ((tp
->t_flags
&EVENP
) == 0)
if ((tp
->t_ospeed
) == 3) /* 110 baud */
* DH11 transmitter interrupt.
* Restart each line which used to be active but has
* terminated transmission since the last interrupt.
register struct device
*addr
;
short ttybit
, bar
, *sbar
;
register struct uba_dinfo
*ui
;
s
= spl6(); /* block the clock */
addr
= (struct device
*)ui
->ui_addr
;
addr
->un
.dhcsr
&= (short)~XINT
;
if (addr
->un
.dhcsr
& NXM
) {
addr
->un
.dhcsr
|= CLRNXM
;
bar
= *sbar
& ~addr
->dhbar
;
unit
= dh
* 16; ttybit
= 1;
for(; bar
; unit
++, ttybit
<<= 1) {
addr
->un
.dhcsrl
= (unit
&017)|IENAB
;
UBACVT(tp
->t_outq
.c_cf
,ui
->ui_ubanum
));
(*linesw
[tp
->t_line
].l_start
)(tp
);
* Start (restart) transmission on the given DH11 line.
register struct device
*addr
;
register int nch
, dh
, unit
;
* If it's currently active, or delaying,
* no need to do anything.
addr
= (struct device
*)tp
->t_addr
;
if (tp
->t_state
&(TIMEOUT
|BUSY
|TTSTOP
))
if ((tp
->t_state
&ASLEEP
) && tp
->t_outq
.c_cc
<=TTLOWAT(tp
)) {
mcstart(tp
->t_chan
, (caddr_t
)&tp
->t_outq
);
wakeup((caddr_t
)&tp
->t_outq
);
if (tp
->t_outq
.c_cc
== 0)
nch
= ndqb(&tp
->t_outq
, 0);
nch
= ndqb(&tp
->t_outq
, 0200);
timeout(ttrstrt
, (caddr_t
)tp
, (nch
&0177)+6);
addr
->un
.dhcsrl
= (unit
&017)|IENAB
;
addr
->dhcar
= UBACVT(tp
->t_outq
.c_cf
,
* Assume call is made at spl6.
register struct device
*addr
;
addr
= (struct device
*)tp
->t_addr
;
if (tp
->t_state
& BUSY
) {
addr
->un
.dhcsrl
= (unit
&017) | IENAB
;
if ((tp
->t_state
&TTSTOP
)==0)
* Silo control is fixed strategy
* here, paralleling only option available
register struct device
*addr
;
register struct uba_dinfo
*ui
;
addr
= (struct device
*)ui
->ui_addr
;
if ((dhisilo
& (1<<dh
)) == 0) {
* Reset state of driver if UBA reset was necessary.
* Reset the csrl and lpr registers on open lines, and
register struct device
*addr
;
register struct uba_dinfo
*ui
;
/*** WE SHOULD LOOK TO SEE IF UBA BEING RESET IS INTERESTING ***/
for (uba
= 0; uba
< numuba
; uba
++)
ubarelse(uba
, &dh_ubinfo
[uba
]);
dh_ubinfo
[uba
] = uballoc(uba
, (caddr_t
)cfree
,
512+NCLIST
*sizeof (struct cblock
), 0);
cbase
[uba
] = (short)dh_ubinfo
;
((struct device
*)dhinfo
[dh
]->ui_addr
)->un
.dhcsr
|=
for (unit
= 0; unit
< NDH11
*16; unit
++) {
if (tp
->t_state
& (ISOPEN
|WOPEN
)) {
dmctl(unit
, TURNON
, DMSET
);
#include "../dev/dhfdm.c"