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 */
dnprobe(reg)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*/
dnopen(dev,flag)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*/
dnclose(dev,flag)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
dnwrite(dev,uio)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
dnintr(dev)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