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