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