summaryrefslogtreecommitdiff
path: root/sys/arch/hp300/dev/hpib.c
diff options
context:
space:
mode:
authorJason Downs <downsj@cvs.openbsd.org>1997-02-03 04:48:09 +0000
committerJason Downs <downsj@cvs.openbsd.org>1997-02-03 04:48:09 +0000
commit3dc2bab62b31e6caa1a00fece6004504f8e08033 (patch)
treec3a44aeae3938880a95422164280589feafe53aa /sys/arch/hp300/dev/hpib.c
parent08e8d869ff1f7248522b236f25044d2744c972dd (diff)
Merge new config(8) support from NetBSD, by Jason Thorpe.
Also add siginfo glue, BOOT_CONFIG, and various other changes.
Diffstat (limited to 'sys/arch/hp300/dev/hpib.c')
-rw-r--r--sys/arch/hp300/dev/hpib.c405
1 files changed, 278 insertions, 127 deletions
diff --git a/sys/arch/hp300/dev/hpib.c b/sys/arch/hp300/dev/hpib.c
index fd8f0b969c8..a55c7f44ca9 100644
--- a/sys/arch/hp300/dev/hpib.c
+++ b/sys/arch/hp300/dev/hpib.c
@@ -1,7 +1,8 @@
-/* $OpenBSD: hpib.c,v 1.5 1997/01/12 15:12:45 downsj Exp $ */
-/* $NetBSD: hpib.c,v 1.12 1996/12/09 03:16:27 thorpej Exp $ */
+/* $OpenBSD: hpib.c,v 1.6 1997/02/03 04:47:33 downsj Exp $ */
+/* $NetBSD: hpib.c,v 1.13 1997/01/30 09:06:51 thorpej Exp $ */
/*
+ * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
* Copyright (c) 1982, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -37,144 +38,254 @@
*/
/*
- * HPIB driver
+ * HP-IB bus driver
*/
-#include "hpib.h"
-#if NHPIB > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
-#include <hp300/dev/device.h>
-#include <hp300/dev/hpibvar.h>
#include <hp300/dev/dmavar.h>
+#include <hp300/dev/hpibvar.h>
+
#include <machine/cpu.h>
#include <hp300/hp300/isr.h>
-int hpibmatch __P((struct hp_ctlr *));
-void hpibattach __P((struct hp_ctlr *));
-void hpibstart __P((int));
-void hpibgo __P((int, int, int, void *, int, int, int));
-void hpibdone __P((int));
-int hpibintr __P((void *));
-
-struct driver hpibdriver = {
- hpibmatch,
- hpibattach,
- "hpib",
- (int(*)())hpibstart, /* XXX */
- (int(*)())hpibgo, /* XXX */
- hpibintr,
- (int(*)())hpibdone, /* XXX */
+int hpibbusmatch __P((struct device *, void *, void *));
+void hpibbusattach __P((struct device *, struct device *, void *));
+
+struct cfattach hpibbus_ca = {
+ sizeof(struct hpibbus_softc), hpibbusmatch, hpibbusattach
};
-struct hpib_softc hpib_softc[NHPIB];
+struct cfdriver hpibbus_cd = {
+ NULL, "hpibbus", DV_DULL
+};
-extern int nhpibtype __P((struct hp_ctlr *)); /* XXX */
-extern int fhpibtype __P((struct hp_ctlr *)); /* XXX */
-extern void nhpibattach __P((struct hp_ctlr *)); /* XXX */
-extern void fhpibattach __P((struct hp_ctlr *)); /* XXX */
+void hpibbus_attach_children __P((struct hpibbus_softc *));
+int hpibbussearch __P((struct device *, void *, void *));
+int hpibbusprint __P((void *, const char *));
+
+int hpibbus_alloc __P((struct hpibbus_softc *, int, int));
+void hpibbus_free __P((struct hpibbus_softc *, int, int));
+
+void hpibstart __P((void *));
+void hpibdone __P((void *));
int hpibtimeout = 100000; /* # of status tests before we give up */
int hpibidtimeout = 10000; /* # of status tests for hpibid() calls */
int hpibdmathresh = 3; /* byte count beyond which to attempt dma */
+/*
+ * HP-IB is essentially an IEEE 488 bus, with an HP command
+ * set (CS/80 on `newer' devices, Amigo on before-you-were-born
+ * devices) thrown on top. Devices that respond to CS/80 (and
+ * probably Amigo, too) are tagged with a 16-bit ID.
+ *
+ * HP-IB has a 2-level addressing scheme; slave, the analog
+ * of a SCSI ID, and punit, the analog of a SCSI LUN. Unforunately,
+ * IDs are on a per-slave basis; punits are often used for disk
+ * drives that have an accompanying tape drive on the second punit.
+ *
+ * In addition, not all HP-IB devices speak CS/80 or Amigo.
+ * Examples of such devices are HP-IB plotters, which simply
+ * take raw plotter commands over 488. These devices do not
+ * have ID tags, and often the host cannot even tell if such
+ * a device is attached to the system!
+ *
+ * These two nasty bits mean that we have to treat HP-IB as
+ * an indirect bus. However, since we are given some ID
+ * information, it is unreasonable to disallow cloning of
+ * CS/80 devices.
+ *
+ * To deal with all of this, we use the semi-twisted scheme
+ * in hpibbus_attach_children(). For each HP-IB slave, we loop
+ * through all of the possibly-configured children, allowing
+ * them to modify the punit parameter (but NOT the slave!).
+ *
+ * This is evil, but what can you do?
+ */
+
int
-hpibmatch(hc)
- register struct hp_ctlr *hc;
+hpibbusmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
{
- struct hp_hw *hw = hc->hp_args;
- extern caddr_t internalhpib;
-
- /* Special case for internal HP-IB. */
- if ((hw->hw_sc == 7) && internalhpib)
- goto hwid_ok;
-
- switch (hw->hw_id) {
- case 8: /* 98625B */
- case 128: /* 98624A */
- hwid_ok:
- if (nhpibtype(hc) || fhpibtype(hc))
- return (1);
- }
- return (0);
+ return (1);
}
void
-hpibattach(hc)
- struct hp_ctlr *hc;
+hpibbusattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
{
- struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
+ struct hpibbus_softc *sc = (struct hpibbus_softc *)self;
+ struct hpibdev_attach_args *ha = aux;
+
+ printf("\n");
+
+ /* Get the operations vector for the controller. */
+ sc->sc_ops = ha->ha_ops;
+ sc->sc_type = ha->ha_type; /* XXX */
+ sc->sc_ba = ha->ha_ba;
+ *(ha->ha_softcpp) = sc; /* XXX */
+
+ hpibreset(self->dv_unit); /* XXX souldn't be here */
/*
- * Call the appropriate "attach" routine for this controller.
- * The type is set in the "type" routine.
- *
- * XXX This is, by the way, exactly backwards.
+ * Initialize the DMA queue entry.
*/
- switch (hs->sc_type) {
- case HPIBA:
- case HPIBB:
- nhpibattach(hc);
- break;
-
- case HPIBC:
- fhpibattach(hc);
- break;
-
- default:
- panic("hpibattach: unknown type 0x%x", hs->sc_type);
- /* NOTREACHED */
+ sc->sc_dq = (struct dmaqueue *)malloc(sizeof(struct dmaqueue),
+ M_DEVBUF, M_NOWAIT);
+ if (sc->sc_dq == NULL) {
+ printf("%s: can't allocate DMA queue entry\n", self->dv_xname);
+ return;
}
+ sc->sc_dq->dq_softc = sc;
+ sc->sc_dq->dq_start = hpibstart;
+ sc->sc_dq->dq_done = hpibdone;
+
+ /* Initialize the slave request queue. */
+ TAILQ_INIT(&sc->sc_queue);
+
+ /* Attach any devices on the bus. */
+ hpibbus_attach_children(sc);
+}
+
+void
+hpibbus_attach_children(sc)
+ struct hpibbus_softc *sc;
+{
+ struct hpibbus_attach_args ha;
+ int slave;
+
+ for (slave = 0; slave < 8; slave++) {
+ /*
+ * Get the ID tag for the device, if any.
+ * Plotters won't identify themselves, and
+ * get the same value as non-existent devices.
+ */
+ ha.ha_id = hpibid(sc->sc_dev.dv_unit, slave);
+
+ ha.ha_slave = slave; /* not to be modified by children */
+ ha.ha_punit = 0; /* children modify this */
+
+ /*
+ * Search though all configured children for this bus.
+ */
+ (void)config_search(hpibbussearch, &sc->sc_dev, &ha);
+ }
+}
+
+int
+hpibbussearch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct cfdata *cf = match;
+ struct hpibbus_softc *sc = (struct hpibbus_softc *)parent;
+ struct hpibbus_attach_args *ha = aux;
+
+ /* Make sure this is in a consistent state. */
+ ha->ha_punit = 0;
+
+ if ((*cf->cf_attach->ca_match)(parent, cf, ha) > 0) {
+ /*
+ * The device probe has succeeded, and filled in
+ * the punit information. Make sure the configuration
+ * allows for this slave/punit combination.
+ */
+ if (cf->hpibbuscf_slave != HPIBBUS_SLAVE_UNK &&
+ cf->hpibbuscf_slave != ha->ha_slave)
+ goto out;
+ if (cf->hpibbuscf_punit != HPIBBUS_PUNIT_UNK &&
+ cf->hpibbuscf_punit != ha->ha_punit)
+ goto out;
+
+ /*
+ * Allocate the device's address from the bus's
+ * resource map.
+ */
+ if (hpibbus_alloc(sc, ha->ha_slave, ha->ha_punit))
+ goto out;
+
+ /*
+ * This device is allowed; attach it.
+ */
+ config_attach(parent, cf, ha, hpibbusprint);
+ }
+ out:
+ return (0);
+}
- hs->sc_hc = hc;
- hs->sc_dq.dq_unit = hc->hp_unit;
- hs->sc_dq.dq_driver = &hpibdriver;
- hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq;
+int
+hpibbusprint(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ struct hpibbus_attach_args *ha = aux;
- /* Establish the interrupt handler. */
- (void) isrlink(hpibintr, hs, hc->hp_ipl, ISRPRI_BIO);
- dmacomputeipl();
+ printf(" slave %d punit %d", ha->ha_slave, ha->ha_punit);
+ return (UNCONF);
+}
- /* Reset the controller, display what we've seen, and we're done. */
- hpibreset(hc->hp_unit);
- printf(": %s\n", hs->sc_descrip);
+int
+hpibdevprint(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+
+ /* only hpibbus's can attach to hpibdev's -- easy. */
+ if (pnp != NULL)
+ printf("hpibbus at %s", pnp);
+ return (UNCONF);
}
void
hpibreset(unit)
register int unit;
{
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
- (hpib_softc[unit].sc_controller->hpib_reset)(unit);
+ (*sc->sc_ops->hpib_reset)(sc);
}
int
-hpibreq(dq)
- register struct devqueue *dq;
+hpibreq(pdev, hq)
+ struct device *pdev;
+ struct hpibqueue *hq;
{
- register struct devqueue *hq;
+ struct hpibbus_softc *sc = (struct hpibbus_softc *)pdev;
+ int s;
- hq = &hpib_softc[dq->dq_ctlr].sc_sq;
- insque(dq, hq->dq_back);
- if (dq->dq_back == hq)
- return(1);
- return(0);
+ s = splhigh(); /* XXXthorpej */
+ TAILQ_INSERT_TAIL(&sc->sc_queue, hq, hq_list);
+ splx(s);
+
+ if (sc->sc_queue.tqh_first == hq)
+ return (1);
+
+ return (0);
}
void
-hpibfree(dq)
- register struct devqueue *dq;
+hpibfree(pdev, hq)
+ struct device *pdev;
+ struct hpibqueue *hq;
{
- register struct devqueue *hq;
+ struct hpibbus_softc *sc = (struct hpibbus_softc *)pdev;
+ int s;
- hq = &hpib_softc[dq->dq_ctlr].sc_sq;
- remque(dq);
- if ((dq = hq->dq_forw) != hq)
- (dq->dq_driver->d_start)(dq->dq_unit);
+ s = splhigh(); /* XXXthorpej */
+ TAILQ_REMOVE(&sc->sc_queue, hq, hq_list);
+ splx(s);
+
+ if ((hq = sc->sc_queue.tqh_first) != NULL)
+ (*hq->hq_start)(hq->hq_softc);
}
int
@@ -201,9 +312,9 @@ hpibsend(unit, slave, sec, addr, cnt)
int unit, slave, sec, cnt;
void *addr;
{
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
- return ((hpib_softc[unit].sc_controller->hpib_send)(unit, slave,
- sec, addr, cnt));
+ return ((*sc->sc_ops->hpib_send)(sc, slave, sec, addr, cnt));
}
int
@@ -211,9 +322,9 @@ hpibrecv(unit, slave, sec, addr, cnt)
int unit, slave, sec, cnt;
void *addr;
{
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
- return ((hpib_softc[unit].sc_controller->hpib_recv)(unit, slave,
- sec, addr, cnt));
+ return ((*sc->sc_ops->hpib_recv)(sc, slave, sec, addr, cnt));
}
int
@@ -221,25 +332,27 @@ hpibpptest(unit, slave)
register int unit;
int slave;
{
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
- return ((hpib_softc[unit].sc_controller->hpib_ppoll)(unit) &
- (0x80 >> slave));
+ return ((*sc->sc_ops->hpib_ppoll)(sc) & (0x80 >> slave));
}
void
hpibppclear(unit)
int unit;
{
- hpib_softc[unit].sc_flags &= ~HPIBF_PPOLL;
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
+
+ sc->sc_flags &= ~HPIBF_PPOLL;
}
hpibawait(unit)
int unit;
{
- register struct hpib_softc *hs = &hpib_softc[unit];
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
- hs->sc_flags |= HPIBF_PPOLL;
- (hs->sc_controller->hpib_ppwatch)((void *)unit);
+ sc->sc_flags |= HPIBF_PPOLL;
+ (*sc->sc_ops->hpib_ppwatch)(sc);
}
int
@@ -247,17 +360,18 @@ hpibswait(unit, slave)
register int unit;
int slave;
{
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
register int timo = hpibtimeout;
- register int mask, (*ppoll) __P((int));
+ register int mask, (*ppoll) __P((struct hpibbus_softc *));
- ppoll = hpib_softc[unit].sc_controller->hpib_ppoll;
+ ppoll = sc->sc_ops->hpib_ppoll;
mask = 0x80 >> slave;
- while (((ppoll)(unit) & mask) == 0)
+ while (((*ppoll)(sc) & mask) == 0) {
if (--timo == 0) {
- printf("%s: swait timeout\n",
- hpib_softc[unit].sc_hc->hp_xname);
+ printf("%s: swait timeout\n", sc->sc_dev.dv_xname);
return(-1);
}
+ }
return(0);
}
@@ -265,51 +379,88 @@ int
hpibustart(unit)
int unit;
{
- register struct hpib_softc *hs = &hpib_softc[unit];
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
- if (hs->sc_type == HPIBA)
- hs->sc_dq.dq_ctlr = DMA0;
+ if (sc->sc_type == HPIBA)
+ sc->sc_dq->dq_chan = DMA0;
else
- hs->sc_dq.dq_ctlr = DMA0 | DMA1;
- if (dmareq(&hs->sc_dq))
+ sc->sc_dq->dq_chan = DMA0 | DMA1;
+ if (dmareq(sc->sc_dq))
return(1);
return(0);
}
void
-hpibstart(unit)
- int unit;
+hpibstart(arg)
+ void *arg;
{
- register struct devqueue *dq;
-
- dq = hpib_softc[unit].sc_sq.dq_forw;
- (dq->dq_driver->d_go)(dq->dq_unit);
+ struct hpibbus_softc *sc = arg;
+ register struct hpibqueue *hq;
+
+ hq = sc->sc_queue.tqh_first;
+ (*hq->hq_go)(hq->hq_softc);
}
void
-hpibgo(unit, slave, sec, addr, count, rw, timo)
- int unit, slave, sec, count, rw, timo;
- void *addr;
+hpibgo(unit, slave, sec, vbuf, count, rw, timo)
+ int unit, slave, sec;
+ void *vbuf;
+ int count, rw, timo;
{
+ struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
- (hpib_softc[unit].sc_controller->hpib_go)(unit, slave, sec,
- addr, count, rw, timo);
+ (*sc->sc_ops->hpib_go)(sc, slave, sec, vbuf, count, rw, timo);
}
void
-hpibdone(unit)
- register int unit;
+hpibdone(arg)
+ void *arg;
{
+ struct hpibbus_softc *sc = arg;
- (hpib_softc[unit].sc_controller->hpib_done)(unit);
+ (*sc->sc_ops->hpib_done)(sc);
}
int
hpibintr(arg)
void *arg;
{
- struct hpib_softc *hs = arg;
+ struct hpibbus_softc *sc = arg;
+
+ return ((sc->sc_ops->hpib_intr)(arg));
+}
+
+int
+hpibbus_alloc(sc, slave, punit)
+ struct hpibbus_softc *sc;
+ int slave, punit;
+{
+
+ if (slave >= HPIB_NSLAVES ||
+ punit >= HPIB_NPUNITS)
+ panic("hpibbus_alloc: device address out of range");
+
+ if (sc->sc_rmap[slave][punit] == 0) {
+ sc->sc_rmap[slave][punit] = 1;
+ return (0);
+ }
+ return (1);
+}
+
+void
+hpibbus_free(sc, slave, punit)
+ struct hpibbus_softc *sc;
+ int slave, punit;
+{
+
+ if (slave >= HPIB_NSLAVES ||
+ punit >= HPIB_NPUNITS)
+ panic("hpibbus_free: device address out of range");
+
+#ifdef DIAGNOSTIC
+ if (sc->sc_rmap[slave][punit] == 0)
+ panic("hpibbus_free: not allocated");
+#endif
- return ((hs->sc_controller->hpib_intr)(arg));
+ sc->sc_rmap[slave][punit] = 0;
}
-#endif /* NHPIB > 0 */