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