diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1997-02-03 04:48:09 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1997-02-03 04:48:09 +0000 |
commit | 3dc2bab62b31e6caa1a00fece6004504f8e08033 (patch) | |
tree | c3a44aeae3938880a95422164280589feafe53aa /sys/arch/hp300/dev/hpib.c | |
parent | 08e8d869ff1f7248522b236f25044d2744c972dd (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.c | 405 |
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 */ |