Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
3c238487 MK |
2 | * Copyright (c) 1982,1986,1988 Regents of the University of California. |
3 | * All rights reserved. | |
da7c5cc6 | 4 | * |
3c238487 MK |
5 | * Redistribution and use in source and binary forms are permitted |
6 | * provided that this notice is preserved and that due credit is given | |
7 | * to the University of California at Berkeley. The name of the University | |
8 | * may not be used to endorse or promote products derived from this | |
9 | * software without specific prior written permission. This software | |
10 | * is provided ``as is'' without express or implied warranty. | |
11 | * | |
2e5d9362 | 12 | * @(#)if_css.c 7.5 (Berkeley) %G% |
da7c5cc6 | 13 | */ |
ee6d9923 SL |
14 | |
15 | #include "css.h" | |
9a0b0c74 | 16 | #if NCSS > 0 |
ee6d9923 SL |
17 | |
18 | /* | |
19 | * DEC/CSS IMP11-A ARPAnet IMP interface driver. | |
20 | * Since "imp11a" is such a mouthful, it is called | |
21 | * "css" after the LH/DH being called "acc". | |
22 | * | |
23 | * Configuration notes: | |
24 | * | |
25 | * As delivered from DEC/CSS, it | |
26 | * is addressed and vectored as two DR11-B's. This makes | |
27 | * Autoconfig almost IMPOSSIBLE. To make it work, the | |
28 | * interrupt vectors must be restrapped to make the vectors | |
29 | * consecutive. The 020 hole between the CSR addresses is | |
30 | * tolerated, althought that could be cleaned-up also. | |
31 | * | |
32 | * Additionally, the TRANSMIT side of the IMP11-A has the | |
33 | * lower address of the two subunits, so the vector ordering | |
34 | * in the CONFIG file is reversed from most other devices. | |
35 | * It should be: | |
36 | * | |
37 | * device css0 .... cssxint cssrint | |
38 | * | |
39 | * If you get it wrong, it will still autoconfig, but will just | |
fd4d8418 | 40 | * sit there with RECEIVE IDLE indicated on the front panel. |
ee6d9923 | 41 | */ |
a6e960e7 JB |
42 | #include "param.h" |
43 | #include "systm.h" | |
44 | #include "mbuf.h" | |
45 | #include "buf.h" | |
46 | #include "protosw.h" | |
47 | #include "socket.h" | |
48 | #include "vmmac.h" | |
a9687d27 | 49 | |
3c238487 MK |
50 | #include "../machine/pte.h" |
51 | ||
ee6d9923 | 52 | #include "../net/if.h" |
d2cc167c | 53 | #include "../netimp/if_imp.h" |
a9687d27 BJ |
54 | |
55 | #include "../vax/cpu.h" | |
56 | #include "../vax/mtpr.h" | |
a6e960e7 JB |
57 | #include "if_cssreg.h" |
58 | #include "if_uba.h" | |
a9687d27 BJ |
59 | #include "../vaxuba/ubareg.h" |
60 | #include "../vaxuba/ubavar.h" | |
ee6d9923 SL |
61 | |
62 | int cssprobe(), cssattach(), cssrint(), cssxint(); | |
63 | struct uba_device *cssinfo[NCSS]; | |
64 | u_short cssstd[] = { 0 }; | |
65 | struct uba_driver cssdriver = | |
66 | { cssprobe, 0, cssattach, 0, cssstd, "css", cssinfo }; | |
ee6d9923 | 67 | |
3c238487 | 68 | int cssinit(), cssoutput(), cssdown(), cssreset(); |
ee6d9923 SL |
69 | |
70 | /* | |
71 | * "Lower half" of IMP interface driver. | |
72 | * | |
73 | * Each IMP interface is handled by a common module which handles | |
74 | * the IMP-host protocol and a hardware driver which manages the | |
75 | * hardware specific details of talking with the IMP. | |
76 | * | |
77 | * The hardware portion of the IMP driver handles DMA and related | |
78 | * management of UNIBUS resources. The IMP protocol module interprets | |
79 | * contents of these messages and "controls" the actions of the | |
80 | * hardware module during IMP resets, but not, for instance, during | |
81 | * UNIBUS resets. | |
82 | * | |
83 | * The two modules are coupled at "attach time", and ever after, | |
84 | * through the imp interface structure. Higher level protocols, | |
85 | * e.g. IP, interact with the IMP driver, rather than the CSS. | |
86 | */ | |
87 | struct css_softc { | |
3c238487 MK |
88 | struct imp_softc *css_imp; /* pointer to IMP's imp_softc struct */ |
89 | struct ifuba css_ifuba; /* UNIBUS resources */ | |
90 | struct mbuf *css_iq; /* input reassembly queue */ | |
91 | short css_olen; /* size of last message sent */ | |
92 | char css_flush; /* flush remainder of message */ | |
ee6d9923 SL |
93 | } css_softc[NCSS]; |
94 | ||
95 | /* | |
96 | * Reset the IMP and cause a transmitter interrupt by | |
97 | * performing a null DMA. | |
98 | */ | |
99 | cssprobe(reg) | |
100 | caddr_t reg; | |
101 | { | |
102 | register int br, cvec; /* r11, r10 value-result */ | |
103 | register struct cssdevice *addr = (struct cssdevice *)reg; | |
104 | ||
ee6d9923 SL |
105 | #ifdef lint |
106 | br = 0; cvec = br; br = cvec; | |
107 | cssrint(0); cssxint(0); | |
108 | #endif | |
109 | ||
ee6d9923 SL |
110 | addr->css_icsr = CSS_CLR; |
111 | addr->css_ocsr = CSS_CLR; | |
112 | DELAY(50000); | |
113 | addr->css_icsr = 0; | |
114 | addr->css_ocsr = 0; | |
115 | DELAY(50000); | |
116 | ||
117 | addr->css_oba = 0; | |
118 | addr->css_owc = -1; | |
119 | addr->css_ocsr = CSS_IE | CSS_GO; /* enable interrupts */ | |
120 | DELAY(50000); | |
121 | addr->css_ocsr = 0; | |
122 | ||
123 | return (1); | |
124 | } | |
125 | ||
126 | /* | |
127 | * Call the IMP module to allow it to set up its internal | |
128 | * state, then tie the two modules together by setting up | |
129 | * the back pointers to common data structures. | |
130 | */ | |
131 | cssattach(ui) | |
35718d8f | 132 | register struct uba_device *ui; |
ee6d9923 SL |
133 | { |
134 | register struct css_softc *sc = &css_softc[ui->ui_unit]; | |
135 | register struct impcb *ip; | |
ee6d9923 | 136 | |
35718d8f MK |
137 | if ((sc->css_imp = impattach(ui->ui_driver->ud_dname, ui->ui_unit, |
138 | cssreset)) == 0) | |
fd4d8418 | 139 | return; |
3c238487 | 140 | ip = &sc->css_imp->imp_cb; |
ee6d9923 | 141 | ip->ic_init = cssinit; |
3c238487 MK |
142 | ip->ic_output = cssoutput; |
143 | ip->ic_down = cssdown; | |
ee6d9923 SL |
144 | sc->css_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEED16; |
145 | #ifdef notdef | |
04ecf99a | 146 | sc->css_ifuba.ifu_flags |= UBA_NEEDBDP; |
ee6d9923 SL |
147 | #endif |
148 | } | |
149 | ||
150 | /* | |
151 | * Reset interface after UNIBUS reset. | |
152 | * If interface is on specified uba, reset its state. | |
153 | */ | |
154 | cssreset(unit, uban) | |
155 | int unit, uban; | |
156 | { | |
157 | register struct uba_device *ui; | |
3c238487 | 158 | register struct css_softc *sc; |
ee6d9923 | 159 | |
ee6d9923 SL |
160 | if (unit >= NCSS || (ui = cssinfo[unit]) == 0 || ui->ui_alive == 0 || |
161 | ui->ui_ubanum != uban) | |
162 | return; | |
163 | printf(" css%d", unit); | |
164 | sc = &css_softc[unit]; | |
3c238487 | 165 | sc->css_imp->imp_if.if_flags &= ~IFF_RUNNING; |
35718d8f | 166 | cssoflush(unit); |
ee6d9923 | 167 | /* must go through IMP to allow it to set state */ |
3c238487 | 168 | (*sc->css_imp->imp_if.if_init)(sc->css_imp->imp_if.if_unit); |
ee6d9923 SL |
169 | } |
170 | ||
171 | /* | |
172 | * Initialize interface: clear recorded pending operations, | |
173 | * and retrieve, and reinitialize UNIBUS resources. | |
174 | */ | |
175 | cssinit(unit) | |
176 | int unit; | |
177 | { | |
178 | register struct css_softc *sc; | |
179 | register struct uba_device *ui; | |
180 | register struct cssdevice *addr; | |
181 | int x, info; | |
182 | ||
ee6d9923 SL |
183 | if (unit >= NCSS || (ui = cssinfo[unit]) == 0 || ui->ui_alive == 0) { |
184 | printf("css%d: not alive\n", unit); | |
185 | return(0); | |
186 | } | |
187 | sc = &css_softc[unit]; | |
188 | ||
189 | /* | |
190 | * Header length is 0 to if_ubainit since we have to pass | |
191 | * the IMP leader up to the protocol interpretaion | |
192 | * routines. If we had the deader length as | |
193 | * sizeof(struct imp_leader), then the if_ routines | |
194 | * would assume we handle it on input and output. | |
195 | */ | |
196 | ||
3c238487 MK |
197 | if ((sc->css_imp->imp_if.if_flags & IFF_RUNNING) == 0 && |
198 | if_ubainit(&sc->css_ifuba, ui->ui_ubanum, 0, | |
199 | (int)btoc(IMP_RCVBUF)) == 0) { | |
ee6d9923 SL |
200 | printf("css%d: can't initialize\n", unit); |
201 | ui->ui_alive = 0; | |
3c238487 | 202 | sc->css_imp->imp_if.if_flags &= ~(IFF_UP | IFF_RUNNING); |
ee6d9923 SL |
203 | return(0); |
204 | } | |
3c238487 | 205 | sc->css_imp->imp_if.if_flags |= IFF_RUNNING; |
ee6d9923 SL |
206 | addr = (struct cssdevice *)ui->ui_addr; |
207 | ||
208 | /* reset the imp interface. */ | |
209 | x = spl5(); | |
210 | addr->css_icsr = CSS_CLR; | |
211 | addr->css_ocsr = CSS_CLR; | |
212 | DELAY(100); | |
213 | addr->css_icsr = 0; | |
214 | addr->css_ocsr = 0; | |
215 | addr->css_icsr = IN_HRDY; /* close the relay */ | |
216 | DELAY(5000); | |
217 | splx(x); | |
218 | ||
219 | /* | |
220 | * This may hang if the imp isn't really there. | |
221 | * Will test and verify safe operation. | |
222 | */ | |
223 | ||
224 | x = 500; | |
225 | while (x-- > 0) { | |
226 | if ((addr->css_icsr & (IN_HRDY|IN_IMPNR)) == IN_HRDY) | |
227 | break; | |
228 | addr->css_icsr = IN_HRDY; /* close the relay */ | |
229 | DELAY(5000); | |
230 | } | |
231 | ||
232 | if (x <= 0) { | |
233 | printf("css%d: imp doesn't respond, icsr=%b\n", unit, | |
234 | CSS_INBITS, addr->css_icsr); | |
235 | goto down; | |
236 | } | |
237 | ||
238 | /* | |
239 | * Put up a read. We can't restart any outstanding writes | |
240 | * until we're back in synch with the IMP (i.e. we've flushed | |
241 | * the NOOPs it throws at us). | |
3c238487 | 242 | * Note: IMP_RCVBUF includes the leader. |
ee6d9923 SL |
243 | */ |
244 | ||
245 | x = spl5(); | |
246 | info = sc->css_ifuba.ifu_r.ifrw_info; | |
247 | addr->css_iba = (u_short)info; | |
3c238487 | 248 | addr->css_iwc = -(IMP_RCVBUF >> 1); |
ee6d9923 SL |
249 | addr->css_icsr = |
250 | IN_HRDY | CSS_IE | IN_WEN | ((info & 0x30000) >> 12) | CSS_GO; | |
251 | splx(x); | |
252 | return(1); | |
253 | ||
254 | down: | |
255 | ui->ui_alive = 0; | |
256 | return(0); | |
257 | } | |
258 | ||
3c238487 MK |
259 | /* |
260 | * Drop the host ready line to mark host down. | |
261 | * UNTESTED. | |
262 | */ | |
263 | cssdown(unit) | |
264 | int unit; | |
265 | { | |
266 | register struct cssdevice *addr; | |
3c238487 MK |
267 | |
268 | addr = (struct cssdevice *)(cssinfo[unit]->ui_addr); | |
269 | /* reset the imp interface. */ | |
3c238487 MK |
270 | addr->css_icsr = CSS_CLR; |
271 | addr->css_ocsr = CSS_CLR; | |
272 | DELAY(100); | |
273 | addr->css_icsr = 0; | |
274 | addr->css_ocsr = 0; | |
35718d8f | 275 | cssoflush(unit); |
3c238487 MK |
276 | return (1); |
277 | } | |
278 | ||
35718d8f MK |
279 | cssoflush(unit) |
280 | int unit; | |
281 | { | |
2e5d9362 | 282 | register struct css_softc *sc = &css_softc[unit]; |
35718d8f | 283 | |
2e5d9362 MK |
284 | sc->css_imp->imp_cb.ic_oactive = 0; |
285 | if (sc->css_ifuba.ifu_xtofree) { | |
286 | m_freem(sc->css_ifuba.ifu_xtofree); | |
287 | sc->css_ifuba.ifu_xtofree = 0; | |
35718d8f MK |
288 | } |
289 | } | |
290 | ||
ee6d9923 SL |
291 | /* |
292 | * Start output on an interface. | |
293 | */ | |
3c238487 MK |
294 | cssoutput(unit, m) |
295 | int unit; | |
296 | struct mbuf *m; | |
ee6d9923 | 297 | { |
3c238487 | 298 | int info; |
ee6d9923 SL |
299 | struct uba_device *ui = cssinfo[unit]; |
300 | register struct css_softc *sc = &css_softc[unit]; | |
301 | register struct cssdevice *addr; | |
ee6d9923 | 302 | |
ee6d9923 | 303 | sc->css_olen = if_wubaput(&sc->css_ifuba, m); |
ee6d9923 SL |
304 | /* |
305 | * Have request mapped to UNIBUS for transmission. | |
306 | * Purge any stale data from the BDP, and start the output. | |
307 | */ | |
308 | if (sc->css_ifuba.ifu_flags & UBA_NEEDBDP) | |
309 | UBAPURGE(sc->css_ifuba.ifu_uba, sc->css_ifuba.ifu_w.ifrw_bdp); | |
310 | addr = (struct cssdevice *)ui->ui_addr; | |
311 | info = sc->css_ifuba.ifu_w.ifrw_info; | |
312 | addr->css_oba = (u_short)info; | |
313 | addr->css_owc = -((sc->css_olen + 1) >> 1); | |
3c238487 MK |
314 | addr->css_ocsr = |
315 | (u_short)(CSS_IE | OUT_ENLB | ((info & 0x30000) >> 12) | CSS_GO); | |
316 | sc->css_imp->imp_cb.ic_oactive = 1; | |
ee6d9923 SL |
317 | } |
318 | ||
319 | /* | |
320 | * Output interrupt handler. | |
321 | */ | |
322 | cssxint(unit) | |
323 | { | |
324 | register struct uba_device *ui = cssinfo[unit]; | |
325 | register struct css_softc *sc = &css_softc[unit]; | |
326 | register struct cssdevice *addr; | |
327 | ||
ee6d9923 | 328 | addr = (struct cssdevice *)ui->ui_addr; |
3c238487 | 329 | if (sc->css_imp->imp_cb.ic_oactive == 0) { |
ee6d9923 SL |
330 | printf("css%d: stray output interrupt csr=%b\n", |
331 | unit, addr->css_ocsr, CSS_OUTBITS); | |
332 | return; | |
333 | } | |
3c238487 MK |
334 | sc->css_imp->imp_if.if_opackets++; |
335 | sc->css_imp->imp_cb.ic_oactive = 0; | |
ee6d9923 | 336 | if (addr->css_ocsr & CSS_ERR){ |
3c238487 | 337 | sc->css_imp->imp_if.if_oerrors++; |
ee6d9923 SL |
338 | printf("css%d: output error, ocsr=%b icsr=%b\n", unit, |
339 | addr->css_ocsr, CSS_OUTBITS, | |
340 | addr->css_icsr, CSS_INBITS); | |
341 | } | |
342 | if (sc->css_ifuba.ifu_xtofree) { | |
343 | m_freem(sc->css_ifuba.ifu_xtofree); | |
344 | sc->css_ifuba.ifu_xtofree = 0; | |
345 | } | |
3c238487 | 346 | impstart(sc->css_imp); |
ee6d9923 SL |
347 | } |
348 | ||
349 | /* | |
350 | * Input interrupt handler | |
351 | */ | |
352 | cssrint(unit) | |
353 | { | |
354 | register struct css_softc *sc = &css_softc[unit]; | |
355 | register struct cssdevice *addr; | |
ee6d9923 SL |
356 | struct mbuf *m; |
357 | int len, info; | |
358 | ||
3c238487 | 359 | sc->css_imp->imp_if.if_ipackets++; |
ee6d9923 SL |
360 | |
361 | /* | |
362 | * Purge BDP; flush message if error indicated. | |
363 | */ | |
364 | ||
365 | addr = (struct cssdevice *)cssinfo[unit]->ui_addr; | |
366 | if (sc->css_ifuba.ifu_flags & UBA_NEEDBDP) | |
367 | UBAPURGE(sc->css_ifuba.ifu_uba, sc->css_ifuba.ifu_r.ifrw_bdp); | |
368 | if (addr->css_icsr & CSS_ERR) { | |
369 | printf("css%d: recv error, csr=%b\n", unit, | |
370 | addr->css_icsr, CSS_INBITS); | |
3c238487 | 371 | sc->css_imp->imp_if.if_ierrors++; |
ee6d9923 SL |
372 | sc->css_flush = 1; |
373 | } | |
374 | ||
375 | if (sc->css_flush) { | |
376 | if (addr->css_icsr & IN_EOM) | |
377 | sc->css_flush = 0; | |
378 | goto setup; | |
379 | } | |
380 | ||
3c238487 MK |
381 | len = IMP_RCVBUF + (addr->css_iwc << 1); |
382 | if (len < 0 || len > IMP_RCVBUF) { | |
ee6d9923 | 383 | printf("css%d: bad length=%d\n", len); |
3c238487 | 384 | sc->css_imp->imp_if.if_ierrors++; |
ee6d9923 SL |
385 | goto setup; |
386 | } | |
387 | ||
388 | /* | |
fd4d8418 | 389 | * The offset parameter is always 0 since using |
ee6d9923 SL |
390 | * trailers on the ARPAnet is insane. |
391 | */ | |
3c238487 | 392 | m = if_rubaget(&sc->css_ifuba, len, 0, &sc->css_imp->imp_if); |
ee6d9923 SL |
393 | if (m == 0) |
394 | goto setup; | |
395 | if ((addr->css_icsr & IN_EOM) == 0) { | |
396 | if (sc->css_iq) | |
397 | m_cat(sc->css_iq, m); | |
398 | else | |
399 | sc->css_iq = m; | |
400 | goto setup; | |
401 | } | |
402 | if (sc->css_iq) { | |
403 | m_cat(sc->css_iq, m); | |
404 | m = sc->css_iq; | |
405 | sc->css_iq = 0; | |
406 | } | |
407 | impinput(unit, m); | |
408 | ||
409 | setup: | |
410 | /* | |
411 | * Setup for next message. | |
412 | */ | |
413 | info = sc->css_ifuba.ifu_r.ifrw_info; | |
414 | addr->css_iba = (u_short)info; | |
3c238487 | 415 | addr->css_iwc = - (IMP_RCVBUF >> 1); |
ee6d9923 SL |
416 | addr->css_icsr = |
417 | IN_HRDY | CSS_IE | IN_WEN | ((info & 0x30000) >> 12) | CSS_GO; | |
418 | } | |
9a0b0c74 | 419 | #endif |