Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/qbus Moved from ../dec/qbus/uba.c,v



details:   https://anonhg.NetBSD.org/src/rev/b1befda09cb8
branches:  trunk
changeset: 473287:b1befda09cb8
user:      ragge <ragge%NetBSD.org@localhost>
date:      Thu May 27 16:04:13 1999 +0000

description:
Moved from ../dec/qbus/uba.c,v

diffstat:

 sys/dev/qbus/uba.c |  472 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 472 insertions(+), 0 deletions(-)

diffs (truncated from 476 to 300 lines):

diff -r 59507acd2380 -r b1befda09cb8 sys/dev/qbus/uba.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/qbus/uba.c        Thu May 27 16:04:13 1999 +0000
@@ -0,0 +1,472 @@
+/*     $NetBSD: uba.c,v 1.46 1999/05/27 16:04:13 ragge Exp $      */
+/*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)uba.c       7.10 (Berkeley) 12/16/90
+ *     @(#)autoconf.c  7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/conf.h>
+#include <sys/dkstat.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/bus.h>
+#include <machine/scb.h>
+#include <machine/cpu.h>
+
+#ifdef __vax__
+#include <machine/pte.h>
+#endif
+
+#include <dev/dec/qbus/ubareg.h>
+#include <dev/dec/qbus/ubavar.h>
+
+static int ubasearch __P((struct device *, struct cfdata *, void *));
+static int ubaprint __P((void *, const char *));
+static void ubainitmaps __P((struct uba_softc *));
+
+extern struct cfdriver uba_cd;
+
+#define spluba spl7
+
+/*
+ * Do transfer on device argument.  The controller
+ * and uba involved are implied by the device.
+ * We queue for resource wait in the uba code if necessary.
+ * We return 1 if the transfer was started, 0 if it was not.
+ *
+ * The onq argument must be zero iff the device is not on the
+ * queue for this UBA. If onq is set, the device must be at the
+ * head of the queue.  In any case, if the transfer is started,
+ * the device will be off the queue, and if not, it will be on.
+ *
+ * Drivers that allocate one BDP and hold it for some time should
+ * set ud_keepbdp.  In this case um_bdp tells which BDP is allocated
+ * to the controller, unless it is zero, indicating that the controller
+ * does not now have a BDP.
+ */
+int
+ubaqueue(uu, bp)
+       register struct uba_unit *uu;
+       struct buf *bp;
+{
+       register struct uba_softc *uh;
+       register int s;
+
+       uh = (void *)((struct device *)(uu->uu_softc))->dv_parent;
+       s = spluba();
+       /*
+        * Honor exclusive BDP use requests.
+        */
+       if ((uu->uu_xclu && uh->uh_users > 0) || uh->uh_xclu)
+               goto rwait;
+       if (uu->uu_keepbdp) {
+               /*
+                * First get just a BDP (though in fact it comes with
+                * one map register too).
+                */
+               if (uu->uu_bdp == 0) {
+                       uu->uu_bdp = uballoc(uh, (caddr_t)0, 0,
+                           UBA_NEEDBDP|UBA_CANTWAIT);
+                       if (uu->uu_bdp == 0)
+                               goto rwait;
+               }
+               /* now share it with this transfer */
+               uu->uu_ubinfo = ubasetup(uh, bp,
+                   uu->uu_bdp|UBA_HAVEBDP|UBA_CANTWAIT);
+       } else
+               uu->uu_ubinfo = ubasetup(uh, bp, UBA_NEEDBDP|UBA_CANTWAIT);
+       if (uu->uu_ubinfo == 0)
+               goto rwait;
+       uh->uh_users++;
+       if (uu->uu_xclu)
+               uh->uh_xclu = 1;
+
+       splx(s);
+       return (1);
+
+rwait:
+       SIMPLEQ_INSERT_TAIL(&uh->uh_resq, uu, uu_resq);
+       splx(s);
+       return (0);
+}
+
+void
+ubadone(uu)
+       struct uba_unit *uu;
+{
+       struct uba_softc *uh = (void *)((struct device *)
+           (uu->uu_softc))->dv_parent;
+
+       if (uu->uu_xclu)
+               uh->uh_xclu = 0;
+       uh->uh_users--;
+       if (uu->uu_keepbdp)
+               uu->uu_ubinfo &= ~BDPMASK;      /* keep BDP for misers */
+       ubarelse(uh, &uu->uu_ubinfo);
+}
+
+/*
+ * Allocate and setup UBA map registers, and bdp's
+ * Flags says whether bdp is needed, whether the caller can't
+ * wait (e.g. if the caller is at interrupt level).
+ * Return value encodes map register plus page offset,
+ * bdp number and number of map registers.
+ */
+int
+ubasetup(uh, bp, flags)
+       struct  uba_softc *uh;
+       struct  buf *bp;
+       int     flags;
+{
+       int npf;
+       int temp;
+       int reg, bdp;
+       int a, o, ubinfo;
+
+       if (uh->uh_nbdp == 0)
+               flags &= ~UBA_NEEDBDP;
+
+       o = (int)bp->b_un.b_addr & VAX_PGOFSET;
+       npf = vax_btoc(bp->b_bcount + o) + 1;
+       if (npf > UBA_MAXNMR)
+               panic("uba xfer too big");
+       a = spluba();
+       while ((reg = rmalloc(uh->uh_map, (long)npf)) == 0) {
+               if (flags & UBA_CANTWAIT) {
+                       splx(a);
+                       return (0);
+               }
+               uh->uh_mrwant++;
+               sleep((caddr_t)&uh->uh_mrwant, PSWP);
+       }
+       if ((flags & UBA_NEED16) && reg + npf > 128) {
+               /*
+                * Could hang around and try again (if we can ever succeed).
+                * Won't help any current device...
+                */
+               rmfree(uh->uh_map, (long)npf, (long)reg);
+               splx(a);
+               return (0);
+       }
+       bdp = 0;
+       if (flags & UBA_NEEDBDP) {
+               while ((bdp = ffs((long)uh->uh_bdpfree)) == 0) {
+                       if (flags & UBA_CANTWAIT) {
+                               rmfree(uh->uh_map, (long)npf, (long)reg);
+                               splx(a);
+                               return (0);
+                       }
+                       uh->uh_bdpwant++;
+                       sleep((caddr_t)&uh->uh_bdpwant, PSWP);
+               }
+               uh->uh_bdpfree &= ~(1 << (bdp-1));
+       } else if (flags & UBA_HAVEBDP)
+               bdp = (flags >> 28) & 0xf;
+       splx(a);
+       reg--;
+       ubinfo = UBAI_INFO(o, reg, npf, bdp);
+       temp = (bdp << 21) | UBAMR_MRV;
+       if (bdp && (o & 01))
+               temp |= UBAMR_BO;
+
+       disk_reallymapin(bp, uh->uh_mr, reg, temp | PG_V);
+
+       return (ubinfo);
+}
+
+/*
+ * Non buffer setup interface... set up a buffer and call ubasetup.
+ */
+int
+uballoc(uh, addr, bcnt, flags)
+       struct  uba_softc *uh;
+       caddr_t addr;
+       int     bcnt, flags;
+{
+       struct buf ubabuf;
+
+       ubabuf.b_un.b_addr = addr;
+       ubabuf.b_flags = B_BUSY;
+       ubabuf.b_bcount = bcnt;
+       /* that's all the fields ubasetup() needs */
+       return (ubasetup(uh, &ubabuf, flags));
+}
+ 
+/*
+ * Release resources on uba uban, and then unblock resource waiters.
+ * The map register parameter is by value since we need to block
+ * against uba resets on 11/780's.
+ */
+void
+ubarelse(uh, amr)
+       struct  uba_softc *uh;
+       int     *amr;
+{
+       struct uba_unit *uu;
+       register int bdp, reg, npf, s;
+       int mr;
+ 
+       /*
+        * Carefully see if we should release the space, since
+        * it may be released asynchronously at uba reset time.
+        */
+       s = spluba();
+       mr = *amr;
+       if (mr == 0) {
+               /*
+                * A ubareset() occurred before we got around
+                * to releasing the space... no need to bother.
+                */
+               splx(s);
+               return;
+       }
+       *amr = 0;
+       bdp = UBAI_BDP(mr);
+       if (bdp) {
+               if (uh->uh_ubapurge)
+                       (*uh->uh_ubapurge)(uh, bdp);
+
+               uh->uh_bdpfree |= 1 << (bdp-1);         /* atomic */
+               if (uh->uh_bdpwant) {
+                       uh->uh_bdpwant = 0;
+                       wakeup((caddr_t)&uh->uh_bdpwant);
+               }
+       }
+       /*
+        * Put back the registers in the resource map.
+        * The map code must not be reentered,
+        * nor can the registers be freed twice.
+        * Unblock interrupts once this is done.
+        */
+       npf = UBAI_NMR(mr);
+       reg = UBAI_MR(mr) + 1;
+       rmfree(uh->uh_map, (long)npf, (long)reg);
+       splx(s);
+
+       /*
+        * Wakeup sleepers for map registers,
+        * and also, if there are processes blocked in dgo(),
+        * give them a chance at the UNIBUS.
+        */
+       if (uh->uh_mrwant) {



Home | Main Index | Thread Index | Old Index