add Berkeley specific copyright
[unix-history] / usr / src / sys / vax / if / if_css.c
CommitLineData
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
62int cssprobe(), cssattach(), cssrint(), cssxint();
63struct uba_device *cssinfo[NCSS];
64u_short cssstd[] = { 0 };
65struct uba_driver cssdriver =
66 { cssprobe, 0, cssattach, 0, cssstd, "css", cssinfo };
ee6d9923 67
3c238487 68int 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 */
87struct 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 */
99cssprobe(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 */
131cssattach(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 */
154cssreset(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 */
175cssinit(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
254down:
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 */
263cssdown(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
279cssoflush(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
294cssoutput(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 */
322cssxint(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 */
352cssrint(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
409setup:
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