123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- #include <sys/param.h>
- #include <sys/ioctl.h>
- #include <sys/systm.h>
- #include <sys/kernel.h>
- #include <sys/errno.h>
- #include <sys/device.h>
- #include <sys/malloc.h>
- #include <sys/proc.h>
- #include <sys/vnode.h>
- #include <sys/conf.h>
- #include <machine/autoconf.h>
- #include <machine/bus.h>
- #include <machine/conf.h>
- #include <machine/intr.h>
- #include <dev/ic/lsi64854reg.h>
- #include <dev/ic/lsi64854var.h>
- #include <dev/sbus/sbusvar.h>
- #include <dev/sbus/bppreg.h>
- #define splbpp() spltty()
- #ifdef DEBUG
- #define DPRINTF(x) do { if (bppdebug) printf x ; } while (0)
- int bppdebug = 1;
- #else
- #define DPRINTF(x)
- #endif
- #if 0
- struct bpp_param {
- int bpp_dss;
- int bpp_dsw;
- int bpp_outputpins;
- int bpp_inputpins;
- };
- #endif
- struct hwstate {
- u_int16_t hw_hcr;
- u_int16_t hw_ocr;
- u_int8_t hw_tcr;
- u_int8_t hw_or;
- u_int16_t hw_irq;
- };
- struct bpp_softc {
- struct lsi64854_softc sc_lsi64854;
- size_t sc_bufsz;
- caddr_t sc_buf;
- int sc_error;
- int sc_flags;
- #define BPP_LOCKED 0x01
- #define BPP_WANT 0x02
-
- struct hwstate sc_hwstate;
- };
- int bppmatch(struct device *, void *, void *);
- void bppattach(struct device *, struct device *, void *);
- int bppintr (void *);
- void bpp_setparams(struct bpp_softc *, struct hwstate *);
- const struct cfattach bpp_ca = {
- sizeof(struct bpp_softc), bppmatch, bppattach
- };
- struct cfdriver bpp_cd = {
- NULL, "bpp", DV_DULL
- };
- #define BPPUNIT(dev) (minor(dev))
- int
- bppmatch(struct device *parent, void *vcf, void *aux)
- {
- struct sbus_attach_args *sa = aux;
- return (strcmp("SUNW,bpp", sa->sa_name) == 0);
- }
- void
- bppattach(struct device *parent, struct device *self, void *aux)
- {
- struct sbus_attach_args *sa = aux;
- struct bpp_softc *dsc = (void *)self;
- struct lsi64854_softc *sc = &dsc->sc_lsi64854;
- int burst, sbusburst;
- int node;
- node = sa->sa_node;
- sc->sc_bustag = sa->sa_bustag;
- sc->sc_dmatag = sa->sa_dmatag;
-
- if (sa->sa_npromvaddrs != 0) {
- if (sbus_bus_map(sa->sa_bustag, 0, sa->sa_promvaddrs[0],
- sa->sa_size,
- BUS_SPACE_MAP_PROMADDRESS, 0, &sc->sc_regs) != 0) {
- printf(": cannot map registers\n");
- return;
- }
- } else if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
- sa->sa_size, 0, 0, &sc->sc_regs) != 0) {
- printf(": cannot map registers\n");
- return;
- }
-
- if (sa->sa_nintr == 0) {
- printf(": no interrupt property\n");
- return;
- }
-
- sbusburst = ((struct sbus_softc *)parent)->sc_burst;
- if (sbusburst == 0)
- sbusburst = SBUS_BURST_32 - 1;
- burst = getpropint(node, "burst-sizes", -1);
- if (burst == -1)
-
- burst = sbusburst;
-
- burst &= sbusburst;
- sc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
- (burst & SBUS_BURST_16) ? 16 : 0;
-
- sc->sc_channel = L64854_CHANNEL_PP;
- if (lsi64854_attach(sc) != 0)
- return;
-
- sc->sc_intrchain = bppintr;
- sc->sc_intrchainarg = dsc;
- (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0,
- bppintr, sc, self->dv_xname);
-
- dsc->sc_bufsz = 1024;
- dsc->sc_buf = malloc(dsc->sc_bufsz, M_DEVBUF, M_NOWAIT);
-
- {
- bus_space_handle_t h = sc->sc_regs;
- struct hwstate *hw = &dsc->sc_hwstate;
- int ack_rate = sa->sa_frequency/1000000;
- hw->hw_hcr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_HCR);
- hw->hw_ocr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_OCR);
- hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR);
- hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR);
- DPRINTF(("bpp: hcr %x ocr %x tcr %x or %x\n",
- hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or));
-
- hw->hw_hcr = ((ack_rate<<BPP_HCR_DSS_SHFT)&BPP_HCR_DSS_MASK)
- | ((ack_rate<<BPP_HCR_DSW_SHFT)&BPP_HCR_DSW_MASK);
- hw->hw_ocr |= BPP_OCR_ACK_OP;
- }
- }
- void
- bpp_setparams(struct bpp_softc *sc, struct hwstate *hw)
- {
- u_int16_t irq;
- bus_space_tag_t t = sc->sc_lsi64854.sc_bustag;
- bus_space_handle_t h = sc->sc_lsi64854.sc_regs;
- bus_space_write_2(t, h, L64854_REG_HCR, hw->hw_hcr);
- bus_space_write_2(t, h, L64854_REG_OCR, hw->hw_ocr);
- bus_space_write_1(t, h, L64854_REG_TCR, hw->hw_tcr);
- bus_space_write_1(t, h, L64854_REG_OR, hw->hw_or);
-
- irq = bus_space_read_2(t, h, L64854_REG_ICR);
- irq &= ~BPP_ALLIRP;
- irq |= (hw->hw_irq & BPP_ALLIRP);
- bus_space_write_2(t, h, L64854_REG_ICR, irq);
- DPRINTF(("bpp_setparams: hcr %x ocr %x tcr %x or %x, irq %x\n",
- hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or, irq));
- }
- int
- bppopen(dev_t dev, int flags, int mode, struct proc *p)
- {
- int unit = BPPUNIT(dev);
- struct bpp_softc *sc;
- struct lsi64854_softc *lsi;
- u_int16_t irq;
- int s;
- if (unit >= bpp_cd.cd_ndevs)
- return (ENXIO);
- if ((sc = bpp_cd.cd_devs[unit]) == NULL)
- return (ENXIO);
- lsi = &sc->sc_lsi64854;
-
- s = splbpp();
- bpp_setparams(sc, &sc->sc_hwstate);
- splx(s);
-
- irq = BPP_ERR_IRQ_EN;
- irq |= sc->sc_hwstate.hw_irq;
- bus_space_write_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_ICR, irq);
- return (0);
- }
- int
- bppclose(dev_t dev, int flags, int mode, struct proc *p)
- {
- struct bpp_softc *sc = bpp_cd.cd_devs[BPPUNIT(dev)];
- struct lsi64854_softc *lsi = &sc->sc_lsi64854;
- u_int16_t irq;
-
- irq = sc->sc_hwstate.hw_irq | BPP_ALLIRQ;
- irq &= ~BPP_ALLEN;
- bus_space_write_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_ICR, irq);
- sc->sc_flags = 0;
- return (0);
- }
- int
- bppwrite(dev_t dev, struct uio *uio, int flags)
- {
- struct bpp_softc *sc = bpp_cd.cd_devs[BPPUNIT(dev)];
- struct lsi64854_softc *lsi = &sc->sc_lsi64854;
- int error = 0;
- int s;
-
- s = splbpp();
- while ((sc->sc_flags & BPP_LOCKED) != 0) {
- if ((flags & IO_NDELAY) != 0) {
- splx(s);
- return (EWOULDBLOCK);
- }
- sc->sc_flags |= BPP_WANT;
- error = tsleep(sc->sc_buf, PZERO | PCATCH, "bppwrite", 0);
- if (error != 0) {
- splx(s);
- return (error);
- }
- }
- sc->sc_flags |= BPP_LOCKED;
- splx(s);
-
- while (uio->uio_resid > 0) {
- caddr_t bp = sc->sc_buf;
- size_t len = min(sc->sc_bufsz, uio->uio_resid);
- if ((error = uiomovei(bp, len, uio)) != 0)
- break;
- while (len > 0) {
- u_int8_t tcr;
- size_t size = len;
- DMA_SETUP(lsi, &bp, &len, 0, &size);
- #ifdef DEBUG
- if (bppdebug) {
- int i;
- printf("bpp: writing %ld : ", len);
- for (i=0; i<len; i++) printf("%c(0x%x)", bp[i], bp[i]);
- printf("\n");
- }
- #endif
-
- tcr = bus_space_read_1(lsi->sc_bustag, lsi->sc_regs,
- L64854_REG_TCR);
- tcr &= ~BPP_TCR_DIR;
- bus_space_write_1(lsi->sc_bustag, lsi->sc_regs,
- L64854_REG_TCR, tcr);
-
- s = splbpp();
- DMA_GO(lsi);
- error = tsleep(sc, PZERO | PCATCH, "bppdma", 0);
- splx(s);
- if (error != 0)
- goto out;
-
- if ((error = sc->sc_error) != 0)
- goto out;
-
- }
- }
- out:
- DPRINTF(("bpp done %x\n", error));
- s = splbpp();
- sc->sc_flags &= ~BPP_LOCKED;
- if ((sc->sc_flags & BPP_WANT) != 0) {
- sc->sc_flags &= ~BPP_WANT;
- wakeup(sc->sc_buf);
- }
- splx(s);
- return (error);
- }
- int
- bppioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
- {
- int error = 0;
- switch(cmd) {
- default:
- error = ENODEV;
- break;
- }
- return (error);
- }
- int
- bppintr(void *arg)
- {
- struct bpp_softc *sc = arg;
- struct lsi64854_softc *lsi = &sc->sc_lsi64854;
- u_int16_t irq;
-
- if (DMA_INTR(lsi) == -1)
- sc->sc_error = 1;
- irq = bus_space_read_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_ICR);
-
- bus_space_write_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_ICR,
- irq | BPP_ALLIRQ);
- DPRINTF(("bpp_intr: %x\n", irq));
-
- if ((irq & BPP_ALLIRQ) == 0)
- return (0);
- if ((sc->sc_flags & BPP_LOCKED) != 0)
- wakeup(sc);
- else if ((sc->sc_flags & BPP_WANT) != 0) {
- sc->sc_flags &= ~BPP_WANT;
- wakeup(sc->sc_buf);
- }
- return (1);
- }
|