BSD 4_3_Tahoe release
[unix-history] / usr / src / sys / tahoevba / ik.c
CommitLineData
5db86c85 1/*
ca67e7b4 2 * @(#)ik.c 7.1 (Berkeley) 5/31/88
5db86c85 3 */
6fcffbdd
SL
4
5#include "ik.h"
6#if NIK > 0
7/*
8 * PS300/IKON DR-11W Device Driver.
9 */
10#include "param.h"
11#include "buf.h"
12#include "cmap.h"
13#include "conf.h"
ca67e7b4 14#include "dir.h"
6fcffbdd
SL
15#include "dkstat.h"
16#include "map.h"
17#include "systm.h"
18#include "user.h"
19#include "vmmac.h"
20#include "proc.h"
ca67e7b4 21#include "uio.h"
6fcffbdd 22#include "kernel.h"
e1111228 23#include "syslog.h"
6fcffbdd
SL
24
25#include "../tahoe/mtpr.h"
26#include "../tahoe/pte.h"
27
28#include "../tahoevba/vbavar.h"
29#include "../tahoevba/ikreg.h"
30#include "../tahoevba/psreg.h"
31#include "../tahoevba/psproto.h"
32
93d65f53
SL
33int ikprobe(), ikattach(), iktimer();
34struct vba_device *ikinfo[NIK];
35long ikstd[] = { 0 };
36struct vba_driver ikdriver = { ikprobe, 0, ikattach, 0, ikstd, "ik", ikinfo };
6fcffbdd 37
93d65f53 38#define splik() spl4()
6fcffbdd
SL
39/*
40 * Devices are organized in pairs with the odd valued
41 * device being used for ``diagnostic'' purposes. That
42 * is diagnostic devices don't get auto-attach'd and
43 * detach'd on open-close.
44 */
93d65f53
SL
45#define IKUNIT(dev) (minor(dev) >> 1)
46#define IKDIAG(dev) (minor(dev) & 01) /* is a diagnostic unit */
47
48struct ik_softc {
49 uid_t is_uid; /* uid of open processes */
50 u_short is_timeout; /* current timeout (seconds) */
51 u_short is_error; /* internal error codes */
52 u_short is_flags;
53#define IKF_ATTACHED 0x1 /* unit is attached (not used yet) */
54 union {
55 u_short w[2];
56 u_long l;
57 } is_nameaddr; /* address of last symbol lookup */
7ea0073c 58 caddr_t is_buf[PS_MAXDMA];/* i/o buffer XXX */
6fcffbdd
SL
59} ik_softc[NIK];
60
93d65f53
SL
61struct buf iktab[NIK]; /* unit command queue headers */
62struct buf rikbuf[NIK]; /* buffers for read/write operations */
63struct buf cikbuf[NIK]; /* buffers for control operations */
6fcffbdd
SL
64
65/* buf overlay definitions */
93d65f53 66#define b_command b_resid
6fcffbdd 67
93d65f53
SL
68int ikdiotimo = PS_DIOTIMO; /* dio polling timeout */
69int iktimeout = PS_TIMEOUT; /* attention/dma timeout (in hz) */
6fcffbdd
SL
70
71ikprobe(reg, vi)
93d65f53 72 caddr_t reg;
6fcffbdd
SL
73 struct vba_device *vi;
74{
93d65f53 75 register int br, cvec; /* r12, r11 */
6fcffbdd
SL
76 register struct ikdevice *ik;
77
9d61b7ff
SL
78#ifdef lint
79 br = 0; cvec = br; br = cvec;
80 ikintr(0);
81#endif
93d65f53
SL
82 if (badaddr(reg, 2))
83 return (0);
6fcffbdd
SL
84 ik = (struct ikdevice *)reg;
85 ik->ik_vec = --vi->ui_hd->vh_lastiv;
93d65f53 86 /*
7ea0073c
SL
87 * Use extended non-privileged address modifier
88 * to avoid address overlap with 24-bit devices.
93d65f53
SL
89 */
90 ik->ik_mod = 0xf1; /* address modifier */
91 /*
92 * Try and reset the PS300. Since this
93 * won't work if it's powered off, we
94 * can't use sucess/failure to decide
95 * if the device is present.
96 */
6fcffbdd 97 br = 0;
93d65f53
SL
98 (void) psreset(ik, IKCSR_IENA);
99 if (br == 0) /* XXX */
6fcffbdd 100 br = 0x18, cvec = ik->ik_vec; /* XXX */
93d65f53 101 return (sizeof (struct ikdevice));
6fcffbdd
SL
102}
103
104/*
105 * Perform a ``hard'' reset.
106 */
107psreset(ik, iena)
93d65f53 108 register struct ikdevice *ik;
6fcffbdd
SL
109{
110
93d65f53
SL
111 ik->ik_csr = IKCSR_MCLR|iena;
112 DELAY(10000);
113 ik->ik_csr = IKCSR_FNC3|iena;
114 if (!iena)
115 return (dioread(ik) == PS_RESET);
116 return (1);
6fcffbdd
SL
117}
118
119ikattach(vi)
93d65f53 120 struct vba_device *vi;
6fcffbdd 121{
6fcffbdd 122
93d65f53 123 ik_softc[vi->ui_unit].is_uid = -1;
6fcffbdd
SL
124}
125
126/*
127 * Open a PS300 and attach. We allow multiple
128 * processes with the same uid to share a unit.
129 */
130/*ARGSUSED*/
131ikopen(dev, flag)
93d65f53
SL
132 dev_t dev;
133 int flag;
6fcffbdd 134{
93d65f53
SL
135 register int unit = IKUNIT(dev);
136 register struct ik_softc *sc;
137 struct vba_device *vi;
138 struct ikdevice *ik;
139 int reset;
140
141 if (unit >= NIK || (vi = ikinfo[unit]) == 0 || vi->ui_alive == 0)
142 return (ENXIO);
143 sc = &ik_softc[unit];
9d61b7ff 144 if (sc->is_uid != (uid_t)-1 && sc->is_uid != u.u_uid)
93d65f53 145 return (EBUSY);
9d61b7ff 146 if (sc->is_uid == (uid_t)-1) {
93d65f53 147 sc->is_timeout = 0;
9d61b7ff 148 timeout(iktimer, (caddr_t)unit, hz);
93d65f53
SL
149 /*
150 * Perform PS300 attach for first process.
151 */
152 if (!IKDIAG(dev)) {
153 reset = 0;
154 again:
155 if (ikcommand(dev, PS_ATTACH, 1)) {
156 /*
157 * If attach fails, perform a hard
158 * reset once, then retry the command.
159 */
160 ik = (struct ikdevice *)ikinfo[unit]->ui_addr;
161 if (!reset++ && psreset(ik, 0))
162 goto again;
9d61b7ff 163 untimeout(iktimer, (caddr_t)unit);
93d65f53
SL
164 return (EIO);
165 }
166 }
167 sc->is_uid = u.u_uid;
168 }
169 return (0);
6fcffbdd
SL
170}
171
172/*ARGSUSED*/
173ikclose(dev, flag)
93d65f53
SL
174 dev_t dev;
175 int flag;
6fcffbdd 176{
93d65f53 177 int unit = IKUNIT(dev);
6fcffbdd
SL
178 register struct ik_softc *sc = &ik_softc[unit];
179
93d65f53
SL
180 if (!IKDIAG(dev))
181 (void) ikcommand(dev, PS_DETACH, 1); /* auto detach */
182 sc->is_uid = -1;
9d61b7ff 183 untimeout(iktimer, (caddr_t)unit);
6fcffbdd
SL
184}
185
186ikread(dev, uio)
93d65f53
SL
187 dev_t dev;
188 struct uio *uio;
6fcffbdd
SL
189{
190
93d65f53 191 return (ikrw(dev, uio, B_READ));
6fcffbdd
SL
192}
193
194ikwrite(dev, uio)
93d65f53
SL
195 dev_t dev;
196 struct uio *uio;
6fcffbdd
SL
197{
198
93d65f53 199 return (ikrw(dev, uio, B_WRITE));
6fcffbdd
SL
200}
201
202/*
203 * Take read/write request and perform physical i/o
204 * transaction with PS300. This involves constructing
205 * a physical i/o request vector based on the uio
206 * vector, performing the dma, and, finally, moving
207 * the data to it's final destination (because of CCI
208 * VERSAbus bogosities).
209 */
210ikrw(dev, uio, rw)
93d65f53
SL
211 dev_t dev;
212 register struct uio *uio;
213 int rw;
6fcffbdd 214{
93d65f53
SL
215 int error, unit = IKUNIT(dev), s, wrcmd;
216 register struct buf *bp;
217 register struct iovec *iov;
218 register struct psalist *ap;
219 struct ik_softc *sc = &ik_softc[unit];
220
221 if (unit >= NIK)
222 return (ENXIO);
223 bp = &rikbuf[unit];
224 error = 0, iov = uio->uio_iov, wrcmd = PS_WRPHY;
225 for (; !error && uio->uio_iovcnt; iov++, uio->uio_iovcnt--) {
226 /*
227 * Hack way to set PS300 address w/o doing an lseek
228 * and specify write physical w/ refresh synchronization.
229 */
230 if (iov->iov_len == 0) {
231 if ((int)iov->iov_base&PSIO_SYNC)
232 wrcmd = PS_WRPHY_SYNC;
233 uio->uio_offset = (int)iov->iov_base & ~PSIO_SYNC;
234 continue;
235 }
236 if (iov->iov_len > PS_MAXDMA) {
237 sc->is_error = PSERROR_INVALBC, error = EINVAL;
238 continue;
239 }
240 if ((int)uio->uio_offset&01) {
241 sc->is_error = PSERROR_BADADDR, error = EINVAL;
242 continue;
243 }
244 s = splbio();
245 while (bp->b_flags&B_BUSY) {
246 bp->b_flags |= B_WANTED;
247 sleep((caddr_t)bp, PRIBIO+1);
248 }
249 splx(s);
250 bp->b_flags = B_BUSY | rw;
251 /*
252 * Construct address descriptor in buffer.
253 */
254 ap = (struct psalist *)sc->is_buf;
255 ap->nblocks = 1;
256 /* work-around dr300 word swapping */
257 ap->addr[0] = uio->uio_offset & 0xffff;
258 ap->addr[1] = uio->uio_offset >> 16;
259 ap->wc = (iov->iov_len + 1) >> 1;
260 if (rw == B_WRITE) {
261 error = copyin(iov->iov_base, (caddr_t)&ap[1],
9d61b7ff 262 (unsigned)iov->iov_len);
93d65f53
SL
263 if (!error)
264 error = ikcommand(dev, wrcmd,
265 iov->iov_len + sizeof (*ap));
266 } else {
267 caddr_t cp;
268 int len;
269
270 error = ikcommand(dev, PS_RDPHY, sizeof (*ap));
271 cp = (caddr_t)&ap[1], len = iov->iov_len;
272 for (; len > 0; len -= NBPG, cp += NBPG)
273 mtpr(P1DC, cp);
274 if (!error)
275 error = copyout((caddr_t)&ap[1], iov->iov_base,
9d61b7ff 276 (unsigned)iov->iov_len);
93d65f53
SL
277 }
278 (void) splbio();
279 if (bp->b_flags&B_WANTED)
280 wakeup((caddr_t)bp);
281 splx(s);
282 uio->uio_resid -= iov->iov_len;
283 uio->uio_offset += iov->iov_len;
284 bp->b_flags &= ~(B_BUSY|B_WANTED);
285 }
286 return (error);
6fcffbdd
SL
287}
288
289/*
290 * Perform a PS300 command.
291 */
292ikcommand(dev, com, count)
93d65f53
SL
293 dev_t dev;
294 int com, count;
6fcffbdd 295{
93d65f53
SL
296 register struct buf *bp;
297 register int s;
298
299 bp = &cikbuf[IKUNIT(dev)];
300 s = splik();
301 while (bp->b_flags&B_BUSY) {
302 if (bp->b_flags&B_DONE)
303 break;
304 bp->b_flags |= B_WANTED;
305 sleep((caddr_t)bp, PRIBIO);
306 }
307 bp->b_flags = B_BUSY|B_READ;
308 splx(s);
309 bp->b_dev = dev;
310 bp->b_command = com;
311 bp->b_bcount = count;
312 ikstrategy(bp);
ca67e7b4 313 biowait(bp);
93d65f53
SL
314 if (bp->b_flags&B_WANTED)
315 wakeup((caddr_t)bp);
316 bp->b_flags &= B_ERROR;
ca67e7b4 317 return (geterror(bp));
6fcffbdd
SL
318}
319
320/*
321 * Physio strategy routine
322 */
323ikstrategy(bp)
93d65f53 324 register struct buf *bp;
6fcffbdd 325{
93d65f53
SL
326 register struct buf *dp;
327
328 /*
329 * Put request at end of controller queue.
330 */
331 dp = &iktab[IKUNIT(bp->b_dev)];
332 bp->av_forw = NULL;
333 (void) splik();
334 if (dp->b_actf != NULL) {
335 dp->b_actl->av_forw = bp;
336 dp->b_actl = bp;
337 } else
338 dp->b_actf = dp->b_actl = bp;
339 if (!dp->b_active)
340 ikstart(dp);
341 (void) spl0();
6fcffbdd
SL
342}
343
344/*
345 * Start the next command on the controller's queue.
346 */
347ikstart(dp)
93d65f53 348 register struct buf *dp;
6fcffbdd 349{
93d65f53
SL
350 register struct buf *bp;
351 register struct ikdevice *ik;
352 register struct ik_softc *sc;
93d65f53
SL
353 u_short bc, csr;
354 u_int addr;
355 int unit;
6fcffbdd
SL
356
357loop:
93d65f53
SL
358 /*
359 * Pull a request off the controller queue
360 */
361 if ((bp = dp->b_actf) == NULL) {
362 dp->b_active = 0;
363 return;
364 }
365 /*
366 * Mark controller busy and process this request.
367 */
368 dp->b_active = 1;
369 unit = IKUNIT(bp->b_dev);
370 sc = &ik_softc[unit];
371 ik = (struct ikdevice *)ikinfo[unit]->ui_addr;
9d61b7ff 372 switch ((int)bp->b_command) {
93d65f53
SL
373
374 case PS_ATTACH: /* logical unit attach */
375 case PS_DETACH: /* logical unit detach */
376 case PS_LOOKUP: /* name lookup */
377 case PS_RDPHY: /* physical i/o read */
378 case PS_WRPHY: /* physical i/o write */
379 case PS_WRPHY_SYNC: /* physical i/o write w/ sync */
380 /*
381 * Handshake command and, optionally,
382 * byte count and byte swap flag.
383 */
9d61b7ff 384 if (sc->is_error = diowrite(ik, (u_short)bp->b_command))
93d65f53
SL
385 goto bad;
386 if (bp->b_command < PS_DETACH) {
9d61b7ff 387 if (sc->is_error = diowrite(ik, (u_short)bp->b_bcount))
93d65f53 388 goto bad;
9d61b7ff 389 if (sc->is_error = diowrite(ik, (u_short)0 /* !swab */))
93d65f53
SL
390 goto bad;
391 }
392 /*
393 * Set timeout and wait for an attention interrupt.
394 */
395 sc->is_timeout = iktimeout;
396 return;
397
398 case PS_DMAOUT: /* dma data host->PS300 */
399 bc = bp->b_bcount;
400 csr = IKCSR_CYCLE;
401 break;
402
403 case PS_DMAIN: /* dma data PS300->host */
404 bc = bp->b_bcount;
405 csr = IKCSR_CYCLE|IKCSR_FNC1;
406 break;
407
408 default:
409 log(LOG_ERR, "ik%d: bad cmd %x\n", unit, bp->b_command);
410 sc->is_error = PSERROR_BADCMD;
411 goto bad;
412 }
413 /* initiate dma transfer */
9d61b7ff 414 addr = vtoph((struct proc *)0, (unsigned)sc->is_buf);
93d65f53
SL
415 ik->ik_bahi = addr >> 17;
416 ik->ik_balo = (addr >> 1) & 0xffff;
417 ik->ik_wc = ((bc + 1) >> 1) - 1; /* round & convert */
418 ik->ik_pulse = IKPULSE_RATTF|IKPULSE_RDMAF;
419 sc->is_timeout = iktimeout;
420 ik->ik_csr = IKCSR_IENA|IKCSR_GO|csr;
421 return;
6fcffbdd 422bad:
93d65f53
SL
423 bp->b_flags |= B_ERROR;
424 dp->b_actf = bp->av_forw; /* remove from queue */
425 biodone(bp);
426 goto loop;
6fcffbdd
SL
427}
428
429#define FETCHWORD(i) { \
93d65f53
SL
430 v = dioread(ik); \
431 if (v == -1) { \
432 sc->is_error = PSERROR_NAMETIMO; \
433 goto bad; \
434 } \
435 sc->is_nameaddr.w[i] = v; \
6fcffbdd
SL
436}
437
438/*
439 * Process a device interrupt.
440 */
441ikintr(ikon)
93d65f53 442 int ikon;
6fcffbdd 443{
93d65f53
SL
444 register struct ikdevice *ik;
445 register struct buf *bp, *dp;
446 struct ik_softc *sc;
447 register u_short data;
9d61b7ff 448 int v;
93d65f53
SL
449
450 /* should go by controller, but for now... */
451 if (ikinfo[ikon] == 0)
452 return;
453 ik = (struct ikdevice *)ikinfo[ikon]->ui_addr;
454 /*
455 * Discard all non-attention interrupts. The
456 * interrupts we're throwing away should all be
457 * associated with DMA completion.
458 */
459 data = ik->ik_data;
460 if ((ik->ik_csr&(IKCSR_ATTF|IKCSR_STATC)) != IKCSR_ATTF) {
461 ik->ik_pulse = IKPULSE_RATTF|IKPULSE_RDMAF|IKPULSE_SIENA;
462 return;
463 }
464 /*
465 * Fetch attention code immediately.
466 */
467 ik->ik_csr = IKCSR_RATTF|IKCSR_RDMAF|IKCSR_FNC1;
468 ik->ik_pulse = IKPULSE_FNC2;
469 /*
470 * Get device and block structures, and a pointer
471 * to the vba_device for the device. We receive an
472 * unsolicited interrupt whenever the PS300 is power
473 * cycled (so ignore it in that case).
474 */
475 dp = &iktab[ikon];
476 if ((bp = dp->b_actf) == NULL) {
477 if (PS_CODE(data) != PS_RESET) /* power failure */
478 log(LOG_WARNING, "ik%d: spurious interrupt, code %x\n",
479 ikon, data);
480 goto enable;
481 }
482 sc = &ik_softc[IKUNIT(bp->b_dev)];
483 sc->is_timeout = 0; /* disable timer */
484 switch (PS_CODE(data)) {
485
486 case PS_LOOKUP: /* name lookup */
487 if (data == PS_LOOKUP) { /* dma name */
488 bp->b_command = PS_DMAOUT;
489 goto opcont;
490 }
491 if (data == PS_DMAOK(PS_LOOKUP)) {
492 /* reenable interrupt and wait for address */
493 sc->is_timeout = iktimeout;
494 goto enable;
495 }
496 /*
497 * Address should be present, extract it one
498 * word at a time from the PS300 (yech).
499 */
500 if (data != PS_ADROK(PS_LOOKUP))
501 goto bad;
502 FETCHWORD(0);
503 FETCHWORD(1);
504 goto opdone;
505
506 case PS_WRPHY_SYNC: /* physical i/o write w/ sync */
507 if (data == PS_WRPHY_SYNC) { /* start dma transfer */
508 bp->b_command = PS_DMAOUT;
509 goto opcont;
510 }
511 if (data != PS_DMAOK(PS_WRPHY_SYNC))
512 goto bad;
513 goto opdone;
514
515 case PS_WRPHY: /* physical i/o write */
516 if (data == PS_WRPHY) { /* start dma transfer */
517 bp->b_command = PS_DMAOUT;
518 goto opcont;
519 }
520 if (data != PS_DMAOK(PS_WRPHY))
521 goto bad;
522 goto opdone;
523
524 case PS_ATTACH: /* attach unit */
525 case PS_DETACH: /* detach unit */
526 case PS_ABORT: /* abort code from ps300 */
527 if (data != bp->b_command)
528 goto bad;
529 goto opdone;
530
531 case PS_RDPHY: /* physical i/o read */
532 if (data == PS_RDPHY) { /* dma address list */
533 bp->b_command = PS_DMAOUT;
534 goto opcont;
535 }
536 if (data == PS_ADROK(PS_RDPHY)) {
537 /* collect read byte count and start dma */
538 bp->b_bcount = dioread(ik);
539 if (bp->b_bcount == -1)
540 goto bad;
541 bp->b_command = PS_DMAIN;
542 goto opcont;
543 }
544 if (data == PS_DMAOK(PS_RDPHY))
545 goto opdone;
546 goto bad;
547 }
6fcffbdd 548bad:
93d65f53
SL
549 sc->is_error = data;
550 bp->b_flags |= B_ERROR;
6fcffbdd 551opdone:
93d65f53
SL
552 dp->b_actf = bp->av_forw; /* remove from queue */
553 biodone(bp);
6fcffbdd 554opcont:
93d65f53 555 ikstart(dp);
6fcffbdd 556enable:
93d65f53 557 ik->ik_pulse = IKPULSE_SIENA; /* explicitly reenable */
6fcffbdd
SL
558}
559
560/*
561 * Watchdog timer.
562 */
563iktimer(unit)
93d65f53 564 int unit;
6fcffbdd 565{
93d65f53
SL
566 register struct ik_softc *sc = &ik_softc[unit];
567
568 if (sc->is_timeout && --sc->is_timeout == 0) {
569 register struct buf *dp, *bp;
570 int s;
571
572 log(LOG_ERR, "ik%d: timeout\n", unit);
573 s = splik();
574 /* should abort current command */
575 dp = &iktab[unit];
576 if (bp = dp->b_actf) {
577 sc->is_error = PSERROR_CMDTIMO;
578 bp->b_flags |= B_ERROR;
579 dp->b_actf = bp->av_forw; /* remove from queue */
580 biodone(bp);
581 ikstart(dp);
582 }
583 splx(s);
584 }
9d61b7ff 585 timeout(iktimer, (caddr_t)unit, hz);
6fcffbdd
SL
586}
587
588/*
589 * Handshake read from DR300.
590 */
591dioread(ik)
93d65f53 592 register struct ikdevice *ik;
6fcffbdd 593{
9d61b7ff 594 register int t;
93d65f53
SL
595 u_short data;
596
9d61b7ff 597 for (t = ikdiotimo; t > 0; t--)
93d65f53
SL
598 if ((ik->ik_csr&(IKCSR_ATTF|IKCSR_STATC)) == IKCSR_ATTF) {
599 data = ik->ik_data;
600 ik->ik_csr = IKCSR_RATTF|IKCSR_RDMAF|IKCSR_FNC1;
601 ik->ik_pulse = IKPULSE_FNC2;
602 return (data);
603 }
604 return (-1);
6fcffbdd
SL
605}
606
607/*
608 * Handshake write to DR300.
609 *
610 * Interrupts are enabled before completing the work
611 * so the caller should either be at splik or be
612 * prepared to take the interrupt immediately.
613 */
614diowrite(ik, v)
93d65f53
SL
615 register struct ikdevice *ik;
616 u_short v;
6fcffbdd 617{
9d61b7ff 618 register int t;
93d65f53 619 register u_short csr;
6fcffbdd
SL
620
621top:
93d65f53
SL
622 /*
623 * Deposit data and generate dr300 attention
624 */
625 ik->ik_data = v;
626 ik->ik_csr = IKCSR_RDMAF|IKCSR_RATTF;
627 ik->ik_pulse = IKPULSE_FNC2;
9d61b7ff 628 for (t = ikdiotimo; t > 0; t--) {
93d65f53
SL
629 csr = ik->ik_csr;
630#define IKCSR_DONE (IKCSR_STATA|IKCSR_STATC)
631 if ((csr&IKCSR_DONE) == IKCSR_DONE) {
632 /*
633 * Done, complete handshake by notifying dr300.
634 */
635 ik->ik_csr = IKCSR_IENA; /* ~IKCSR_FNC1 */
636 ik->ik_pulse = IKPULSE_FNC2;
637 return (0);
638 }
639 /* beware of potential deadlock with dioread */
640 if ((csr&(IKCSR_ATTF|IKCSR_STATC)) == IKCSR_ATTF)
641 goto top;
642 }
643 ik->ik_csr = IKCSR_IENA;
644 return (PSERROR_DIOTIMO);
6fcffbdd
SL
645}
646
647/*ARGSUSED*/
648ikioctl(dev, cmd, data, flag)
93d65f53
SL
649 dev_t dev;
650 int cmd;
651 caddr_t data;
652 int flag;
6fcffbdd 653{
93d65f53
SL
654 int error = 0, unit = IKUNIT(dev), s;
655 register struct ik_softc *sc = &ik_softc[unit];
656
657 switch (cmd) {
658
659 case PSIOGETERROR: /* get error code for last operation */
660 *(int *)data = sc->is_error;
661 break;
662
663 case PSIOLOOKUP: { /* PS300 name lookup */
664 register struct pslookup *lp = (struct pslookup *)data;
665 register struct buf *bp;
666
667 if (lp->pl_len > PS_MAXNAMELEN)
668 return (EINVAL);
669 bp = &rikbuf[unit];
670 s = splbio();
671 while (bp->b_flags&B_BUSY) {
672 bp->b_flags |= B_WANTED;
673 sleep((caddr_t)bp, PRIBIO+1);
674 }
675 splx(s);
676 bp->b_flags = B_BUSY | B_WRITE;
5db86c85
MK
677 error = copyin(lp->pl_name, (caddr_t)sc->is_buf,
678 (unsigned)lp->pl_len);
93d65f53
SL
679 if (error == 0) {
680 if (lp->pl_len&1)
681 sc->is_buf[lp->pl_len] = '\0';
682 error = ikcommand(dev, PS_LOOKUP, lp->pl_len);
683 }
684 s = splbio();
685 if (bp->b_flags&B_WANTED)
686 wakeup((caddr_t)bp);
687 splx(s);
688 bp->b_flags &= ~(B_BUSY|B_WANTED);
689 lp->pl_addr = sc->is_nameaddr.l;
690 break;
691 }
692 default:
693 return (ENOTTY);
694 }
695 return (error);
6fcffbdd
SL
696}
697#endif