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