xref: /original-bsd/sys/vax/uba/lpa.c (revision f0fd5f8a)
1 /*	lpa.c	4.9	82/10/20	*/
2 
3 #include "lpa.h"
4 #if NLPA > 0
5 
6 #include "../h/param.h"
7 #include "../h/dir.h"
8 #include "../h/user.h"
9 #include "../h/buf.h"
10 #include "../h/proc.h"
11 #include "../h/ioctl.h"
12 #include "../h/uio.h"
13 
14 #include "../vaxuba/ubavar.h"
15 
16 /*
17  * LPA driver for -- Asa Romberger
18  *
19  *	open
20  *	write microcode
21  *	write dedicated mode dispatch table
22  *	ioctl TIOCSETP to set parameters
23  *		struct iocb {
24  *			short *baddr;	buffer address
25  *			short rate;	- 1,000,000 / frequency in Hz
26  *			short wc;	15-13 = number of buffers - 1
27  *					12-0 = buffer size in words
28  *		} iocb;
29  *	read - 1 character indicating buffer index
30  *		fill or empty buffer
31  * minor device number = DDCCCCCC where:
32  *	DD	= 00 for analog input
33  *		= 01 for analog output
34  *	CCCCCC	= channel number
35  */
36  *	define NOMCODE to eliminate the microcode download check
37  */
38 /* #define TRACELPA */
39 /* #define NOMCODE */
40 
41 #ifdef TRACELPA
42 #	define TRACER(x)	printf(x)
43 #	define TRACERN(x, d)	printf(x, d)
44 #else
45 #	define TRACER(x)
46 #	define TRACERN(x, d)
47 #endif
48 
49 	/* PRIORITY AT WHICH PROGRAM SHOULD RUN */
50 	/* THIS SHOULD EVENTUALLY  TELL UNIX THIS IS A REAL-TIME DEVICE */
51 
52 #define NICE	0
53 
54 #define inc(v)		(sc->v = ((sc->v + 1) % sc->sc_nbuf))
55 
56 #define LPAPRI		(PZERO + 0)
57 #define LPAUNIT(dev)	0
58 #define LPADEVICE(dev)	(((dev) >> 6) & 03)
59 #define LPACHANNEL(dev)	((dev) & 077)
60 
61 int	lpaprobe(), lpaattach(), lpaiintr(), lpaointr();
62 u_short	lpastd[] = {0170460, 0};
63 struct	uba_device *lpadinfo[NLPA];
64 struct uba_driver lpadriver =
65   {lpaprobe, 0, lpaattach, 0, lpastd, "lpa", lpadinfo, 0, 0, 0 };
66 
67 struct lpa_softc {
68 	int	sc_flag;	/* flags, as defined below */
69 	int	sc_device;	/* device: 0 = analog in, 1 = analog out */
70 	int	sc_channel;	/* device channel number */
71 	struct buf sc_ubuffer;	/* user buffer header */
72 	int	sc_ubabuf;	/* uba allocation pointer for buffer */
73 	int	sc_ubufn;	/* present buffer that user is accessing */
74 	int	sc_lbufn;	/* present buffer that lpa is accessing */
75 	int	sc_lbufnx;	/* next buffer for lpa (value in ustat) */
76 	int	sc_nbuf;	/* number of buffers */
77 	int	sc_count;	/* buffer size in words */
78 	short	sc_ustat;	/* user status word */
79 	struct buf sc_ustatbuf;	/* dummy user status word buffer for ubasetup */
80 	int	sc_ubaustat;	/* uba allocation pointer for ustat */
81 	struct buf *sc_buffer;	/* scratch buffer header */
82 	int	sc_start;	/* 0 if lpa operation has been started */
83 } lpa_softc[NLPA];
84 
85 /* flags for sc_flag */
86 #define OPEN	01		/* device is open */
87 #define MCODE	02		/* microcode has been loaded */
88 #define DMDT	04		/* dedicated mode dispatch table loaded */
89 #define STTY	010		/* stty call and device initialized */
90 #define SLEEP	020		/* sleeping */
91 
92 /* bits for ustat */
93 #define DONE	0100000		/* done */
94 #define STOP	0040000		/* stop data transfer */
95 #define NBI	0003400		/* next buffer index */
96 #define LBI	0000003		/* last buffer index */
97 
98 struct lpadevice {
99 	short	lcim;		/* control in and maintenance */
100 	short	lcos;		/* control and status out */
101 	short	lrda;		/* request description array address word */
102 	short	lms;		/* maintenance status */
103 };
104 
105 /* control in and maintenance register bits */
106 #define	READYI	0000200		/* ready in */
107 #define IIE	0000100		/* in interrupt enable */
108 #define RDAEXT	0000014		/* rda address extension */
109 #define RDAEXTOFFSET	2	/* offset of RDAEXT from right side */
110 #define GO	0000001		/* go */
111 #define RUN	0100000		/* run */
112 #define RESET	0040000		/* reset */
113 #define CWRITE	0020000		/* cram write */
114 #define EA	0004000		/* enable arbitration */
115 #define ROMO	0002000		/* rom O */
116 #define ROMI	0001000		/* rom I */
117 #define SMICRO	0000400		/* step microprocessor */
118 
119 /* control and status out register bits */
120 #define READYO	0200		/* ready out */
121 #define OIE	0100		/* out interrupt enable */
122 #define UINDEX	0007		/* user index */
123 #define ERROR	0100000		/* error */
124 #define ESTAT	0060000		/* error status */
125 #define ESCODE	0017400		/* error sub code */
126 #define ECODE	0077400		/* error status + error sub code */
127 #define OVERRUN	0243		/* overrun error */
128 
129 /* LPA COMMAND DESCRIPTION AREA */
130 
131 /* INIT COMMAND */
132 #define INIT	0		/* mode */
133 #define MCVERS	4		/* microcode version */
134 #define ACLOCKA	0170404		/* LPA bus addresses */
135 #define ACLOCKB	0170432
136 #define AAD1	0170400
137 #define AAD2	1		/* 0170440 - DOES NOT EXIST */
138 #define ADA	0170420
139 #define ADIO1	1		/* 0167770 - DOES NOT EXIST */
140 #define ADIO2	1		/* 0167760 - DOES NOT EXIST */
141 #define ADIO3	1		/* 0167750 - DOES NOT EXIST */
142 #define ADIO4	1		/* 0167740 - DOES NOT EXIST */
143 #define ADIO5	1		/* 0167730 - DOES NOT EXIST */
144 
145 /* CLOCK START COMMAND */
146 #define CLOCK	1		/* mode */
147 #define CLOCKA	0<<4		/* clock A */
148 	/* clock status word */
149 #define ENACTR	1		/* enable counter */
150 #define R1M	1<<1		/* 1 MHz rate */
151 #define R100K	2<<1		/* 100 KHz rate */
152 #define R10K	3<<1		/* 10 KHz rate */
153 #define R1K	4<<1		/* 1 KHz rate */
154 #define R100	5<<1		/* 100 Hz rate */
155 #define REXT	6<<1		/* external rate (from st1 input) */
156 #define R60	7<<1		/* line frequency rate */
157 #define MFIE	0100		/* mode flag interrupt enable */
158 #define MSI	0<<8		/* single interval mode */
159 #define MRI	1<<8		/* repeat interval mode */
160 #define MEET	2<<8		/* external event time mode */
161 #define MEETZ	3<<8		/* external event time mode from zero base */
162 #define ST1EC	020000		/* st1 enable counter */
163 #define ST1IE	040000		/* st1 interrupt enable */
164 
165 /* DATA TRANSFER START COMMAND */
166 #define DTS	2		/* mode */
167 #define SCHAN	1<<8		/* single channel */
168 
169 lpaprobe(reg)
170 	caddr_t reg;
171 {
172 	register int br, cvec;	/* value result */
173 	register struct lpadevice *lpaaddr = (struct lpadevice *)reg;
174 
175 #ifdef lint
176 	br = 0; cvec = br; br = cvec;
177 #endif
178 	/* this should force an interrupt, stall, clear the lpa */
179 	br = 0x15;
180 	cvec = 0330;
181 TRACER("PROBE\n");
182 	return (sizeof (struct lpadevice));
183 }
184 
185 lpaattach(ui)
186 	register struct upa_device *ui;
187 {
188 
189 }
190 
191 lpaopen(dev, flag)
192 	dev_t dev;
193 	int flag;
194 {
195 	register int unit = LPAUNIT(dev);
196 	register struct lpa_softc *sc = &lpa_softc[unit];
197 	register struct uba_device *ui = lpadinfo[unit];
198 	register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr;
199 
200 TRACER("OPEN\n");
201 	if (unit >= NLPA || sc->sc_flag & OPEN || ui == 0 ||
202 	    ui->ui_alive == 0)
203 		return (ENXIO);
204 	(void) spl7();
205 	lpaaddr->lcim = RESET;
206 	lpaaddr->lcim = 0;
207 	(void) spl0();
208 	lpaaddr->lcos = 0;	/* clear the registers as a precaution */
209 	lpaaddr->lrda = 0;
210 	lpaaddr->lms = 0;
211 	sc->sc_flag = OPEN;
212 	sc->sc_device = LPADEVICE(dev);
213 	sc->sc_channel = LPACHANNEL(dev);
214 	sc->sc_buffer = geteblk();
215 	sc->sc_buffer->b_error = 0;
216 	sc->sc_buffer->b_proc = u.u_procp;
217 	sc->sc_ubufn = -1;
218 	/* THIS SHOULD EVENTUALLY SPECIFY "REAL-TIME" */
219 	u.u_procp->p_nice = NICE;
220 	return (0);
221 }
222 
223 lpaclose(dev, flag)
224 	dev_t dev;
225 	int flag;
226 {
227 	register int unit = LPAUNIT(dev);
228 	register struct lpa_softc *sc = &lpa_softc[unit];
229 	register struct uba_device *ui = lpadinfo[unit];
230 	register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr;
231 
232 	if (sc->sc_device && sc->sc_ubufn >= 0 && (sc->sc_flag & ERROR) == 0) {
233 		if (sc->sc_start)
234 			lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum);
235 		sc->sc_flag |= STOP;
236 		(void) spl5();
237 		while (sc->sc_flag & STOP) {
238 TRACER("SLEEP\n");
239 			sc->sc_flag |= SLEEP;
240 			sleep((caddr_t)sc, LPAPRI);
241 		}
242 	}
243 	(void) spl7();
244 	lpaaddr->lcim = RESET;
245 	lpaaddr->lcim = 0;
246 	(void) spl0();
247 	if (sc->sc_ubabuf) {
248 		ubarelse(ui->ui_ubanum, &sc->sc_ubabuf);
249 		sc->sc_ubabuf = 0;
250 		(void) spl6();
251 		vsunlock(sc->sc_ubuffer.b_un.b_addr, sc->sc_ubuffer.b_bcount,
252 			(sc->sc_device)? B_READ : B_WRITE);
253 		u.u_procp->p_flag &= ~SPHYSIO;
254 		(void) spl0();
255 	}
256 	if (sc->sc_ubaustat) {
257 		ubarelse(ui->ui_ubanum, &sc->sc_ubaustat);
258 		sc->sc_ubaustat = 0;
259 	}
260 	if (sc->sc_buffer) {
261 		brelse(sc->sc_buffer);
262 		sc->sc_buffer = 0;
263 	}
264 	sc->sc_flag = 0;
265 TRACER("CLOSE\n");
266 }
267 
268 lpawrite(dev, uio)
269 	dev_t dev;
270 	struct uio *uio;
271 {
272 	register int unit = LPAUNIT(dev);
273 	register struct lpa_softc *sc = &lpa_softc[unit];
274 	register struct uba_device *ui = lpadinfo[unit];
275 	register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr;
276 	register int f;
277 
278 TRACER("WRITE\n");
279 	f = sc->sc_flag;
280 	if ((f & OPEN) == 0)
281 		return (ENXIO);
282 	if ((f & MCODE) == 0)		/* first write is the microcode */
283 		return (lpamcode(lpaaddr, sc, uio));
284 	if ((f & DMDT) == 0)		/* second write is the dispatch table */
285 		return (lpadmdt(lpaaddr, sc, ui->ui_ubanum, uio));
286 	return (ENXIO);
287 }
288 
289 lpamcode(lpaaddr, sc, uio)
290 	register struct lpadevice *lpaaddr;
291 	register struct lpa_softc *sc;
292 	struct uio *uio;
293 {
294 	short v, r;
295 	register int mcaddr;
296 	int error;
297 
298 	mcaddr = 0;
299 	while (uio->uio_resid) {
300 		error = uiomove(&v, 2, UIO_WRITE, uio);
301 		if (error)
302 			break;
303 		lpaaddr->lcim = 0;		/* load microcode word */
304 		lpaaddr->lrda = mcaddr;
305 		lpaaddr->lms = v;
306 		lpaaddr->lcim = ROMO;
307 		lpaaddr->lcim |= CWRITE;
308 		lpaaddr->lcim = 0;		/* verify microcode word */
309 		lpaaddr->lrda = mcaddr;
310 		lpaaddr->lcim = ROMO;
311 		if ((r = lpaaddr->lms) != v) {
312 			/* download failure */
313 			printf("LPA MICROCODE FAIL: exp:%o got:%o\n", v, r);
314 			return (ENXIO);
315 		}
316 		mcaddr++;
317 	}
318 	lpaaddr->lcim = RUN | EA;	/* turn it on */
319 	sc->sc_flag |= MCODE;
320 	lpaaddr->lcim |= IIE;
321 	lpaaddr->lcos |= OIE;
322 	return (error);
323 TRACER("MCODE\n");
324 }
325 
326 lpadmdt(lpaaddr, sc, ubanum, uio)
327 	register struct lpadevice *lpaaddr;
328 	register struct lpa_softc *sc;
329 	register short ubanum;
330 	struct uio *uio;
331 {
332 	register short *p;
333 	register int n;
334 	int error;
335 
336 	p = (short *) sc->sc_buffer->b_un.b_addr;		/* INIT */
337 	*p++ = (MCVERS << 8) | INIT;	/* mode */
338 	*p++ = ACLOCKA;		/* LPA bus device addresses */
339 	*p++ = ACLOCKB;
340 	*p++ = AAD1;
341 	*p++ = AAD2;
342 	*p++ = ADA;
343 	*p++ = ADIO1;
344 	*p++ = ADIO2;
345 	*p++ = ADIO3;
346 	*p++ = ADIO4;
347 	*p++ = ADIO5;
348 	n = min(uio->uio_resid, 256);	/* dedicated mode dispatch table */
349 	error = uiomove((char *)p, n, UIO_WRITE, uio);
350 	if (error)
351 		return (error);
352 	n >>= 1;
353 	p += n;
354 	while (n++ < 128)
355 		*p++ = 0;
356 	lpacmd(sc->sc_buffer, lpaaddr, sc, ubanum);
357 	sc->sc_flag |= DMDT;
358 	return (0);
359 TRACER("DMDT\n");
360 }
361 
362 lpaioctl(dev, cmd, data, flag)
363 	dev_t dev;
364 	caddr_t data;
365 {
366 	register int unit = LPAUNIT(dev);
367 	register struct lpa_softc *sc = &lpa_softc[unit];
368 	register struct uba_device *ui = lpadinfo[unit];
369 	register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr;
370 	register short *p;
371 	register int i;
372 	register int v;
373 	struct iocb {
374 		short *baddr;
375 		short rate;
376 		short wc;
377 	} *iocb;
378 
379 TRACER("IOCTL IN\n");
380 	if (cmd != TIOCSETP || (sc->sc_flag & DMDT) == 0)
381 		return (ENXIO);
382 	iocb = (struct iocb *)data;
383 	p = (short *) sc->sc_buffer->b_un.b_addr;	/* CLOCK START */
384 	*p++ = CLOCK | CLOCKA;			/* mode */
385 	*p++ = ENACTR | R1M | MFIE | MRI;	/* clock status */
386 	*p = iocb->rate;			/* clock preset */
387 	lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum);
388 TRACER("CLOCK STARTED\n");
389 	p = (short *) sc->sc_buffer->b_un.b_addr;	/* DATA TRANSFER START*/
390 	*p++ = (sc->sc_device << 7) | DTS | SCHAN;	/* mode */
391 	sc->sc_count = iocb->wc & 017777;	/* word count per buffer */
392 	*p++ = sc->sc_count;
393 							/* user status word */
394 	sc->sc_ustatbuf.b_un.b_addr = (caddr_t) &sc->sc_ustat;
395 	sc->sc_ustatbuf.b_flags = 0;
396 	sc->sc_ustatbuf.b_bcount = 2;
397 	sc->sc_ustatbuf.b_proc = u.u_procp;
398 	sc->sc_ubaustat = ubasetup(ui->ui_ubanum, &sc->sc_ustatbuf, 0);
399 	v = sc->sc_ubaustat;
400 	*p++ = v;
401 	*p = (v >> 16) & 03;		/* into low portion of word */
402 	sc->sc_nbuf = (iocb->wc >> 13) & 07;	/* number of buffers */
403 	*p++ |= sc->sc_nbuf++ << 8;		/* into high portion of word */
404 					/* buffer addresses */
405 	if (useracc(sc->sc_ubuffer.b_un.b_addr = (caddr_t) iocb->baddr,
406 	    sc->sc_ubuffer.b_bcount = sc->sc_count * sc->sc_nbuf * 2,
407 	    (i = (sc->sc_device)? B_READ : B_WRITE) ) == NULL) {
408 TRACER("USER BUFFER FAULT\n");
409 		return (EFAULT);
410 	}
411 	sc->sc_ubuffer.b_flags = B_PHYS | B_BUSY | i;
412 	sc->sc_ubuffer.b_proc = u.u_procp;
413 	u.u_procp->p_flag |= SPHYSIO;
414 	vslock(sc->sc_ubuffer.b_un.b_addr, sc->sc_ubuffer.b_bcount);
415 	sc->sc_ubabuf = ubasetup(ui->ui_ubanum, &sc->sc_ubuffer, 0);
416 	v = sc->sc_ubabuf;
417 	for (i = 0; i < sc->sc_nbuf; i++) {
418 		*p++ = v;
419 		*p++ = (v >> 16) & 03;
420 		v += sc->sc_count * 2;
421 	}
422 	for ( ; i <= 7; i++) {
423 		*p++ = 0;
424 		*p++ = 0;
425 	}
426 	*p++ = 0; *p++ = 0;		/* random channel list address */
427 	*p++ = 0;			/* delay */
428 	*p++ = sc->sc_channel;		/* start channel, channel inc */
429 	*p++ = 1;			/* number of samples in a sequence */
430 	*p++ = 0;			/* dwell */
431 	*p++ = 0;			/* start word no., event mark word */
432 	*p++ = 0;			/* start word mask */
433 	*p = 0;				/* event mark mask */
434 	sc->sc_ustat = 0;
435 	sc->sc_start = (sc->sc_device)? sc->sc_nbuf+1 : 1;
436 	sc->sc_lbufn = 0;
437 	sc->sc_lbufnx = 0;
438 	sc->sc_flag |= STTY;
439 TRACER("IOCTL OUT\n");
440 	return (0);
441 }
442 
443 lparead(dev, uio)
444 	dev_t dev;
445 	struct uio *uio;
446 {
447 	register int unit = LPAUNIT(dev);
448 	register struct lpa_softc *sc = &lpa_softc[unit];
449 	register struct uba_device *ui = lpadinfo[unit];
450 	register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr;
451 
452 TRACER("READ\n");
453 	if ((sc->sc_flag & STTY) == 0)
454 		return (ENXIO);
455 	if (sc->sc_flag & ERROR)
456 		return (ENXIO);
457 	if (sc->sc_start)
458 		if (--sc->sc_start == 0) {
459 			lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum);
460 TRACER("START\n");
461 		}
462 	inc(sc_ubufn);
463 	if (sc->sc_start == 0) {
464 		(void) spl5();
465 		while (sc->sc_ubufn == sc->sc_lbufn) {
466 			if (sc->sc_flag & ERROR)
467 				return (ENXIO);
468 TRACER("SLEEP\n");
469 			sc->sc_flag |= SLEEP;
470 			sleep(sc, LPAPRI);
471 		}
472 		(void) spl0();
473 	}
474 TRACERN("READ %d\n", sc->sc_ubufn);
475 	return (uiomove(&sc->sc_ubufn, 1, UIO_READ, uio));
476 }
477 
478 lpacmd(bp, lpaaddr, sc, ubanum)
479 	register struct buf *bp;
480 	register struct lpadevice *lpaaddr;
481 	register struct lpa_softc *sc;
482 	register short ubanum;
483 {
484 	int ubareg;
485 
486 TRACER("CMD\n");
487 	ubareg = ubasetup(ubanum, bp, UBA_NEEDBDP);
488 	lpawait(lpaaddr, sc);
489 	lpaaddr->lrda = ubareg;
490 	lpaaddr->lcim &= ~RDAEXT;
491 	lpaaddr->lcim |= ((ubareg >> (16-RDAEXTOFFSET)) & RDAEXT) | GO;
492 	lpawait(lpaaddr, sc);
493 	ubarelse(ubanum, &ubareg);
494 }
495 
496 lpawait(lpaaddr, sc)
497 	register struct lpadevice *lpaaddr;
498 	register struct lpa_softc *sc;
499 {
500 
501 	(void) spl5();
502 	while ((lpaaddr->lcim & READYI) == 0) {
503 TRACER("SLEEP\n");
504 		sc->sc_flag |= SLEEP;
505 		sleep((caddr_t)sc, LPAPRI);
506 	}
507 	(void) spl0();
508 }
509 
510 lpaiintr(unit)
511 	int unit;
512 {
513 	register struct lpa_softc *sc = &lpa_softc[unit];
514 
515 TRACER("{I");
516 	if (sc->sc_flag & SLEEP) {
517 TRACER("<WAKEUP>");
518 		wakeup((caddr_t)sc);
519 		sc->sc_flag &= ~SLEEP;
520 	}
521 TRACER("}");
522 }
523 
524 lpaointr(unit)
525 	int unit;
526 {
527 	register int c, m;
528 	register struct lpa_softc *sc = &lpa_softc[unit];
529 	register struct uba_device *ui = lpadinfo[unit];
530 	register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr;
531 	int spx;
532 
533 TRACER("{O");
534 	if (sc->sc_flag & SLEEP) {
535 TRACER("<WAKEUP>");
536 		wakeup(sc);
537 		sc->sc_flag &= ~SLEEP;
538 	}
539 	c = lpaaddr->lcos;
540 	m = lpaaddr->lms;
541 	lpaaddr->lcos &= ~READYO;
542 	if (c & ERROR) {
543 TRACER("<ERROR>");
544 		c = (c >> 8) & 0377;
545 		if ((sc->sc_flag & STOP) == 0 || (c != OVERRUN)) {
546 			printf("LPA ERROR %o %o\n", c, m&0177777);
547 			sc->sc_flag |= ERROR;
548 		}
549 		sc->sc_flag &= ~STOP;
550 TRACER("}\n");
551 		return;
552 	}
553 TRACERN("<LPA %d>", sc->sc_lbufnx);
554 	sc->sc_lbufn = sc->sc_lbufnx;
555 	if (sc->sc_ubufn == sc->sc_lbufnx && c & ECODE) {
556 TRACER("<STOP?>");
557 		if (sc->sc_flag & STOP)
558 			return;
559 		printf("LPA OVERRUN\n");
560 		sc->sc_flag |= ERROR;
561 	}
562 	inc(sc_lbufnx);
563 TRACERN("<USTAT %o>", sc->sc_ustat);
564 	spx = spl7();
565 	sc->sc_ustat &= ~NBI;
566 	sc->sc_ustat |= sc->sc_lbufnx << 8;
567 	sc->sc_ustat &= ~DONE;
568 	(void) splx(spx);
569 TRACERN("<LPAN %d>}", sc->sc_lbufnx);
570 }
571 
572 lpareset(uban)
573 	int uban;
574 {
575 	register struct uba_device *ui;
576 	register struct lpadevice *lpaaddr;
577 	register struct lpa_softc *sc;
578 	register int unit;
579 
580 TRACER("LPA RESET\n");
581 	for (unit = 0; unit < NLPA; unit++) {
582 		if ((ui = lpadinfo[unit]) == 0 ||
583 		    ui->ui_ubanum != uban || ui->ui_alive == 0)
584 			continue;
585 		printf(" lpa%d", unit);
586 		lpaaddr = (struct lpadevice *)ui->ui_addr;
587 		sc = &lpa_softc[unit];
588 		sc->sc_flag |= ERROR;
589 		(void) spl7();
590 		lpaaddr->lcim = RESET;
591 		lpaaddr->lcim = 0;
592 		(void) spl0();
593 		if (sc->sc_flag & SLEEP) {
594 			wakeup((caddr_t)sc);
595 			sc->sc_flag &= ~SLEEP;
596 		}
597 	}
598 }
599 #endif NLPA
600