xref: /original-bsd/sys/vax/uba/dn.c (revision e1db577d)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)dn.c	7.7 (Berkeley) 12/16/90
7  */
8 
9 #include "dn.h"
10 #if NDN > 0
11 /*
12  * DN-11 ACU interface
13  */
14 #include "../include/pte.h"
15 
16 #include "sys/param.h"
17 #include "sys/systm.h"
18 #include "sys/user.h"
19 #include "sys/buf.h"
20 #include "sys/map.h"
21 #include "sys/conf.h"
22 #include "sys/uio.h"
23 
24 #include "ubavar.h"
25 
26 struct dndevice {
27 	u_short	dn_reg[4];
28 };
29 
30 struct uba_device *dninfo[NDN];
31 int dnprobe(), dnattach(), dnintr();
32 u_short dnstd[] = { 0175200, 0 };
33 struct uba_driver dndriver =
34 	{ dnprobe, 0, dnattach, 0, dnstd, "dn", dninfo };
35 
36 #define	CRQ	0x001		/* call request */
37 #define	DPR	0x002		/* digit present */
38 #define	MENABLE	0x004		/* master enable */
39 #define MAINT	0x008		/* maintenance mode */
40 #define	PND	0x010		/* present next digit */
41 #define	DSS	0x020		/* data set status */
42 #define	IENABLE	0x040		/* interrupt enable */
43 #define	DONE	0x080		/* operation complete */
44 #define	DLO	0x1000		/* data line occupied */
45 #define	ACR	0x4000		/* abandon call and retry */
46 #define	PWI	0x8000		/* power indicate */
47 
48 #define	DNPRI	(PZERO+5)
49 #define DNUNIT(dev)	(minor(dev)>>2)
50 #define DNREG(dev)	((dev)&03)
51 
52 #define OBUFSIZ	40		/* largest phone # dialer can handle */
53 
54 /*
55  * There's no good way to determine the correct number of dialers attached
56  * to a single device (especially when dialers such as Vadic-821 MACS
57  * exist which can address four chassis, each with its own dialer).
58  */
59 dnprobe(reg)
60 	caddr_t reg;
61 {
62 	register int br, cvec;	/* value-result, must be r11, r10 */
63 	register struct dndevice *dnaddr = (struct dndevice *)reg;
64 
65 #ifdef lint
66 	br = 0; cvec = 0; br = cvec; cvec = br;
67 	dnintr(0);
68 #endif
69 	/*
70 	 * If there's at least one dialer out there it better be
71 	 * at chassis 0.
72 	 */
73 	dnaddr->dn_reg[0] = MENABLE|IENABLE|DONE;
74 	DELAY(5);
75 	dnaddr->dn_reg[0] = 0;
76 	return (sizeof (struct dndevice));
77 }
78 
79 /*ARGSUSED*/
80 dnattach(ui)
81 	struct uba_device *ui;
82 {
83 
84 }
85 
86 /*ARGSUSED*/
87 dnopen(dev, flag)
88 	dev_t dev;
89 	int flag;
90 {
91 	register struct dndevice *dp;
92 	register u_short unit, *dnreg;
93 	register struct uba_device *ui;
94 	register short dialer;
95 
96 	if ((unit = DNUNIT(dev)) >= NDN || (ui = dninfo[unit]) == 0 ||
97 	    ui->ui_alive == 0)
98 		return (ENXIO);
99 	dialer = DNREG(dev);
100 	dp = (struct dndevice *)ui->ui_addr;
101 	if (dp->dn_reg[dialer] & PWI)
102 		return (ENXIO);
103 	dnreg = &(dp->dn_reg[dialer]);
104 	if (*dnreg&(DLO|CRQ))
105 		return (EBUSY);
106 	dp->dn_reg[0] |= MENABLE;
107 	*dnreg = IENABLE|MENABLE|CRQ;
108 	return (0);
109 }
110 
111 /*ARGSUSED*/
112 dnclose(dev, flag)
113 	dev_t dev;
114 {
115 	register struct dndevice *dp;
116 
117 	dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr;
118 	dp->dn_reg[DNREG(dev)] = MENABLE;
119 	return (0);
120 }
121 
122 dnwrite(dev, uio)
123 	dev_t dev;
124 	struct uio *uio;
125 {
126 	register u_short *dnreg;
127 	register int cc;
128 	register struct dndevice *dp;
129 	char obuf[OBUFSIZ];
130 	register char *cp;
131 	extern lbolt;
132 	int error;
133 
134 	dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr;
135 	dnreg = &(dp->dn_reg[DNREG(dev)]);
136 	cc = MIN(uio->uio_resid, OBUFSIZ);
137 	cp = obuf;
138 	error = uiomove(cp, cc, uio);
139 	if (error)
140 		return (error);
141 	while ((*dnreg & (PWI|ACR|DSS)) == 0 && cc >= 0 && error == 0) {
142 		(void) spl4();
143 		if ((*dnreg & PND) == 0 || cc == 0)
144 			error = tsleep((caddr_t)dnreg, DNPRI | PCATCH,
145 			   devout, 0);
146 		else switch(*cp) {
147 
148 		case '-':
149 			error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH,
150 			    devout, 0);
151 			if (error == 0)
152 				error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH,
153 				    devout, 0);
154 			break;
155 
156 		case 'f':
157 			*dnreg &= ~CRQ;
158 			error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH,
159 			    devout, 0);
160 			*dnreg |= CRQ;
161 			break;
162 
163 		case '*': case ':':
164 			*cp = 012;
165 			goto dial;
166 
167 		case '#': case ';':
168 			*cp = 013;
169 			goto dial;
170 
171 		case 'e': case '<':
172 			*cp = 014;
173 			goto dial;
174 
175 		case 'w': case '=':
176 			*cp = 015;
177 			goto dial;
178 
179 		default:
180 			if (*cp < '0' || *cp > '9')
181 				break;
182 		dial:
183 			*dnreg = (*cp << 8) | (IENABLE|MENABLE|DPR|CRQ);
184 			error = tsleep((caddr_t)dnreg, DNPRI | PCATCH,
185 			    devout, 0);
186 		}
187 		cp++, cc--;
188 		spl0();
189 	}
190 	if (error)
191 		return (error);
192 	if (*dnreg & (PWI|ACR))
193 		return (EIO);
194 	return (0);
195 }
196 
197 dnintr(dev)
198 	dev_t dev;
199 {
200 	register u_short *basereg, *dnreg;
201 
202 	basereg = (u_short *)dninfo[dev]->ui_addr;
203 	*basereg &= ~MENABLE;
204 	for (dnreg = basereg; dnreg < basereg + 4; dnreg++)
205 		if (*dnreg & DONE) {
206 			*dnreg &= ~(DONE|DPR);
207 			wakeup((caddr_t)dnreg);
208 		}
209 	*basereg |= MENABLE;
210 }
211 #endif
212