From a2692d780bc75b81e9b302395ecae97263fea7fe Mon Sep 17 00:00:00 2001 From: ragge Date: Sun, 6 Jun 1999 19:14:48 +0000 Subject: [PATCH] Fix map register/DMA wait queues. Still to do: BDP handling. Currently missing. Ubareset's won't work at all. --- sys/dev/qbus/dhu.c | 44 +++---- sys/dev/qbus/dl.c | 7 +- sys/dev/qbus/dz.c | 9 +- sys/dev/qbus/dz_uba.c | 9 +- sys/dev/qbus/files.uba | 21 +++- sys/dev/qbus/uba.c | 278 ++++------------------------------------- sys/dev/qbus/ubavar.h | 66 ++-------- sys/dev/qbus/uda.c | 202 ++++++++++++++++-------------- 8 files changed, 194 insertions(+), 442 deletions(-) diff --git a/sys/dev/qbus/dhu.c b/sys/dev/qbus/dhu.c index d7a45592a4cf..6b2c4e8ce44b 100644 --- a/sys/dev/qbus/dhu.c +++ b/sys/dev/qbus/dhu.c @@ -1,4 +1,4 @@ -/* $NetBSD: dhu.c,v 1.15 1999/05/28 20:17:29 ragge Exp $ */ +/* $NetBSD: dhu.c,v 1.16 1999/06/06 19:14:48 ragge Exp $ */ /* * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. * Copyright (c) 1992, 1993 @@ -71,10 +71,11 @@ struct dhu_softc { int sc_type; /* controller type, DHU or DHV */ bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; + bus_dma_tag_t sc_dmat; struct { struct tty *dhu_tty; /* what we work on */ + bus_dmamap_t dhu_dmah; int dhu_state; /* to manage TX output status */ - int dhu_txaddr; /* UBA map address to TX buf */ short dhu_cc; /* character count on TX */ short dhu_modem; /* modem bits state */ } sc_dhu[NDHULINE]; @@ -207,10 +208,11 @@ dhu_attach(parent, self, aux) register struct dhu_softc *sc = (void *)self; register struct uba_attach_args *ua = aux; register unsigned c; - register int n; + register int n, i; sc->sc_iot = ua->ua_iot; sc->sc_ioh = ua->ua_ioh; + sc->sc_dmat = ua->ua_dmat; /* Process the 8 bytes of diagnostic info put into */ /* the FIFO following the master reset operation. */ @@ -233,6 +235,18 @@ dhu_attach(parent, self, aux) sc->sc_type = (c & DHU_STAT_DHU)? IS_DHU: IS_DHV; printf("\n%s: DH%s-11\n", self->dv_xname, (c & DHU_STAT_DHU)?"U":"V"); + for (i = 0; i < sc->sc_type; i++) { + struct tty *tp; + tp = sc->sc_dhu[i].dhu_tty = ttymalloc(); + sc->sc_dhu[i].dhu_state = STATE_IDLE; + bus_dmamap_create(sc->sc_dmat, tp->t_outq.c_cn, 1, + tp->t_outq.c_cn, 0, BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT, + &sc->sc_dhu[i].dhu_dmah); + bus_dmamap_load(sc->sc_dmat, sc->sc_dhu[i].dhu_dmah, + tp->t_outq.c_cs, tp->t_outq.c_cn, 0, BUS_DMA_NOWAIT); + + } + /* Now stuff TX interrupt handler in place */ scb_vecalloc(ua->ua_cvec + 4, dhuxint, self->dv_unit, SCB_ISTACK); } @@ -365,24 +379,12 @@ dhuopen(dev, flag, mode, p) if (line >= sc->sc_type) return ENXIO; + s = spltty(); + DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); + sc->sc_dhu[line].dhu_modem = DHU_READ_WORD(DHU_UBA_STAT); + (void) splx(s); + tp = sc->sc_dhu[line].dhu_tty; - if (tp == NULL) { - - tp = sc->sc_dhu[line].dhu_tty = ttymalloc(); - if (tp == NULL) - return ENXIO; - - sc->sc_dhu[line].dhu_state = STATE_IDLE; - - sc->sc_dhu[line].dhu_txaddr = - uballoc((struct uba_softc *)sc->sc_dev.dv_parent, - tp->t_outq.c_cs, tp->t_outq.c_cn, 0); - - s = spltty(); - DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); - sc->sc_dhu[line].dhu_modem = DHU_READ_WORD(DHU_UBA_STAT); - (void) splx(s); - } tp->t_oproc = dhustart; tp->t_param = dhuparam; @@ -634,7 +636,7 @@ dhustart(tp) sc->sc_dhu[line].dhu_state = STATE_DMA_RUNNING; - addr = UBAI_ADDR(sc->sc_dhu[line].dhu_txaddr) + + addr = sc->sc_dhu[line].dhu_dmah->dm_segs[0].ds_addr + (tp->t_outq.c_cf - tp->t_outq.c_cs); DHU_WRITE_WORD(DHU_UBA_TBUFCNT, cc); diff --git a/sys/dev/qbus/dl.c b/sys/dev/qbus/dl.c index 1f3e927a8a66..0021e6f6c78b 100644 --- a/sys/dev/qbus/dl.c +++ b/sys/dev/qbus/dl.c @@ -1,4 +1,4 @@ -/* $NetBSD: dl.c,v 1.9 1999/05/27 16:00:45 ragge Exp $ */ +/* $NetBSD: dl.c,v 1.10 1999/06/06 19:14:49 ragge Exp $ */ /*- * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. @@ -97,10 +97,9 @@ #include #include -#include -#include +#include -#include +#include #include "ioconf.h" diff --git a/sys/dev/qbus/dz.c b/sys/dev/qbus/dz.c index ef2e6dafecf8..735e41cfe251 100644 --- a/sys/dev/qbus/dz.c +++ b/sys/dev/qbus/dz.c @@ -1,4 +1,4 @@ -/* $NetBSD: dz.c,v 1.17 1999/05/27 16:02:32 ragge Exp $ */ +/* $NetBSD: dz.c,v 1.18 1999/06/06 19:14:49 ragge Exp $ */ /* * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. * Copyright (c) 1992, 1993 @@ -61,11 +61,8 @@ #include #include -#include -#include - -#include -#include +#include +#include #define DZ_READ_BYTE(adr) \ bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr) diff --git a/sys/dev/qbus/dz_uba.c b/sys/dev/qbus/dz_uba.c index ca4d2cd44893..2bdeede6b0e2 100644 --- a/sys/dev/qbus/dz_uba.c +++ b/sys/dev/qbus/dz_uba.c @@ -1,4 +1,4 @@ -/* $NetBSD: dz_uba.c,v 1.6 1999/05/27 16:02:50 ragge Exp $ */ +/* $NetBSD: dz_uba.c,v 1.7 1999/06/06 19:14:49 ragge Exp $ */ /* * Copyright (c) 1998 Ludd, University of Lule}, Sweden. All rights reserved. * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. @@ -49,11 +49,10 @@ #include #include -#include -#include +#include -#include -#include +#include +#include #include "ioconf.h" diff --git a/sys/dev/qbus/files.uba b/sys/dev/qbus/files.uba index 638c9d510983..b695e6c26336 100644 --- a/sys/dev/qbus/files.uba +++ b/sys/dev/qbus/files.uba @@ -1,19 +1,30 @@ -# $NetBSD: files.uba,v 1.4 1999/05/27 16:03:57 ragge Exp $ +# $NetBSD: files.uba,v 1.5 1999/06/06 19:14:49 ragge Exp $ # # Config file and device description for machine-independent # code for devices Digital Equipment Corp. Unibus and Q22 bus. # Included by ports that need it. device uba { csr } -file dev/dec/uba/uba.c uba & new_uba +file dev/qbus/uba.c uba & new_uba # DZ-11 (-compatible) tty device driver. device dz { }: tty attach dz at uba with dz_uba -file dev/dec/qbus/dz.c dz needs-flag -file dev/dec/qbus/dz_uba.c dz_uba & new_uba +file dev/qbus/dz.c dz needs-flag +file dev/qbus/dz_uba.c dz_uba & new_uba # DL-11 at UBA device dl: tty attach dl at uba -file dev/dec/qbus/dl.c dl needs-flag +file dev/qbus/dl.c dl needs-flag + +# DHU-11 at UBA +device dhu: tty +attach dhu at uba +file dev/qbus/dhu.c dhu needs-flag + +device mtc: mscp +attach mtc at uba +device uda: mscp +attach uda at uba +file dev/qbus/uda.c uda | mtc diff --git a/sys/dev/qbus/uba.c b/sys/dev/qbus/uba.c index 6a9a907cf898..68357b0a51d8 100644 --- a/sys/dev/qbus/uba.c +++ b/sys/dev/qbus/uba.c @@ -1,4 +1,4 @@ -/* $NetBSD: uba.c,v 1.46 1999/05/27 16:04:13 ragge Exp $ */ +/* $NetBSD: uba.c,v 1.47 1999/06/06 19:14:49 ragge Exp $ */ /* * Copyright (c) 1996 Jonathan Stone. * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. @@ -58,263 +58,54 @@ #include #include -#ifdef __vax__ -#include -#endif +#include -#include -#include +#include "ioconf.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. + * If we failed to allocate uba resources, put us on a queue to wait + * until there is available resources. Resources to compete about + * are map registers and BDPs. This is normally only a problem on + * Unibus systems, Qbus systems have more map registers than usable. */ -int -ubaqueue(uu, bp) - register struct uba_unit *uu; - struct buf *bp; +void +uba_enqueue(uu) + struct uba_unit *uu; { - register struct uba_softc *uh; - register int s; + struct uba_softc *uh; + 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: + s = splimp(); 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. + * When a routine that uses resources is finished, the next device + * in queue for map registers etc is called. If it succeeds to get + * resources, call next, and next, and next... + * This routine must be called at splimp. */ void -ubarelse(uh, amr) - struct uba_softc *uh; - int *amr; +uba_done(uh) + struct uba_softc *uh; { 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) { - uh->uh_mrwant = 0; - wakeup((caddr_t)&uh->uh_mrwant); - } - while ((uu = uh->uh_resq.sqh_first)) { + while ((uu = SIMPLEQ_FIRST(&uh->uh_resq))) { SIMPLEQ_REMOVE_HEAD(&uh->uh_resq, uu, uu_resq); - if ((*uu->uu_ready)(uu) == 0) + if ((*uu->uu_ready)(uu) == 0) { + SIMPLEQ_INSERT_HEAD(&uh->uh_resq, uu, uu_resq); break; + } } } -void -ubainitmaps(uhp) - register struct uba_softc *uhp; -{ - - if (uhp->uh_memsize > UBA_MAXMR) - uhp->uh_memsize = UBA_MAXMR; - rminit(uhp->uh_map, (long)uhp->uh_memsize, (long)1, "uba", UAMSIZ); - uhp->uh_bdpfree = (1 << uhp->uh_nbdp) - 1; -} - /* * Generate a reset on uba number uban. Then * call each device that asked to be called during attach, @@ -327,16 +118,8 @@ ubareset(uban) register struct uba_softc *uh = uba_cd.cd_devs[uban]; int s, i; - s = spluba(); - uh->uh_users = 0; - uh->uh_zvcnt = 0; - uh->uh_xclu = 0; + s = splimp(); SIMPLEQ_INIT(&uh->uh_resq); - uh->uh_bdpwant = 0; - uh->uh_mrwant = 0; - ubainitmaps(uh); - wakeup((caddr_t)&uh->uh_bdpwant); - wakeup((caddr_t)&uh->uh_mrwant); printf("%s: reset", uh->uh_dev.dv_xname); (*uh->uh_ubainit)(uh); @@ -347,9 +130,7 @@ ubareset(uban) } /* - * The common attach routines: - * Allocates interrupt vectors. - * Puts correct values in uba_softc. + * The common attach routine: * Calls the scan routine to search for uba devices. */ void @@ -371,14 +152,6 @@ uba_attach(sc, iopagephys) */ if (bus_space_map(sc->uh_iot, iopagephys, UBAIOSIZE, 0, &sc->uh_ioh)) return; - /* - * Initialize the UNIBUS, by freeing the map - * registers and the buffered data path registers - */ - sc->uh_map = (struct map *)malloc((u_long) - (UAMSIZ * sizeof(struct map)), M_DEVBUF, M_NOWAIT); - bzero((caddr_t)sc->uh_map, (unsigned)(UAMSIZ * sizeof (struct map))); - ubainitmaps(sc); if (sc->uh_beforescan) (*sc->uh_beforescan)(sc); @@ -403,6 +176,7 @@ ubasearch(parent, cf, aux) ua.ua_ioh = ubdevreg(cf->cf_loc[0]) + sc->uh_ioh; ua.ua_iot = sc->uh_iot; + ua.ua_dmat = sc->uh_dmat; ua.ua_reset = NULL; if (badaddr((caddr_t)ua.ua_ioh, 2) || diff --git a/sys/dev/qbus/ubavar.h b/sys/dev/qbus/ubavar.h index be7ddc6ada55..5632e06dc99a 100644 --- a/sys/dev/qbus/ubavar.h +++ b/sys/dev/qbus/ubavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ubavar.h,v 1.24 1999/05/27 16:04:48 ragge Exp $ */ +/* $NetBSD: ubavar.h,v 1.25 1999/06/06 19:14:49 ragge Exp $ */ /* * Copyright (c) 1982, 1986 Regents of the University of California. @@ -44,10 +44,6 @@ * Each unibus device has a uba_device structure. */ -#include -#include - -#include /* For struct ivec_dsp */ /* * Per-uba structure. * @@ -72,39 +68,21 @@ struct uba_softc { struct device uh_dev; /* Device struct, autoconfig */ SIMPLEQ_HEAD(, uba_unit) uh_resq; /* resource wait chain */ - int uh_type; /* type of adaptor */ - struct uba_regs *uh_uba; /* virt addr of uba adaptor regs */ - struct pte *uh_mr; /* start of page map */ - int uh_memsize; /* size of uba memory, pages */ - caddr_t uh_iopage; /* start of uba io page */ void (**uh_reset) __P((int));/* UBA reset function array */ int *uh_resarg; /* array of ubareset args */ int uh_resno; /* Number of devices to reset */ - short uh_mrwant; /* someone is waiting for map reg */ - short uh_bdpwant; /* someone awaits bdp's */ - int uh_bdpfree; /* free bdp's */ - int uh_zvcnt; /* number of recent 0 vectors */ - long uh_zvtime; /* time over which zvcnt accumulated */ - int uh_zvtotal; /* total number of 0 vectors */ int uh_lastiv; /* last free interrupt vector */ - short uh_users; /* transient bdp use count */ - short uh_xclu; /* an rk07 is using this uba! */ - int uh_lastmem; /* limit of any unibus memory */ - struct map *uh_map; /* register free map */ int (*uh_errchk) __P((struct uba_softc *)); void (*uh_beforescan) __P((struct uba_softc *)); void (*uh_afterscan) __P((struct uba_softc *)); void (*uh_ubainit) __P((struct uba_softc *)); void (*uh_ubapurge) __P((struct uba_softc *, int)); short uh_nr; /* Unibus sequential number */ - short uh_nbdp; /* # of BDP's */ - int uh_ibase; /* Base address for vectors */ bus_space_tag_t uh_iot; /* Tag for this Unibus */ bus_space_handle_t uh_ioh; /* Handle for I/O space */ + bus_dma_tag_t uh_dmat; }; -#define UAMSIZ 100 - /* * Per-controller structure. * The unit struct is common to both the adapter and the controller @@ -114,9 +92,9 @@ struct uba_softc { struct uba_unit { SIMPLEQ_ENTRY(uba_unit) uu_resq;/* Queue while waiting for resources */ void *uu_softc; /* Pointer to units softc */ - int uu_ubinfo; /* save unibus registers, etc */ int uu_bdp; /* for controllers that hang on to bdp's */ int (*uu_ready) __P((struct uba_unit *)); + void *uu_ref; /* Buffer this is related to */ short uu_xclu; /* want exclusive use of bdp's */ short uu_keepbdp; /* hang on to bdp's once allocated */ }; @@ -128,6 +106,7 @@ struct uba_unit { struct uba_attach_args { bus_space_tag_t ua_iot; /* Tag for this bus I/O-space */ bus_addr_t ua_ioh; /* I/O regs addr */ + bus_dma_tag_t ua_dmat; /* Pointer to int routine, filled in by probe*/ void (*ua_ivec) __P((int)); /* UBA reset routine, filled in by probe */ @@ -144,44 +123,21 @@ struct uba_attach_args { #define UBA_CANTWAIT 0x02 /* don't block me */ #define UBA_NEED16 0x04 /* need 16 bit addresses only */ #define UBA_HAVEBDP 0x08 /* use bdp specified in high bits */ +#define UBA_DONTQUE 0x10 /* Do not enqueue xfer */ /* - * Macros to bust return word from map allocation routines. - * SHOULD USE STRUCTURE TO STORE UBA RESOURCE ALLOCATION: + * Some common defines for all subtypes of U/Q-buses/adapters. */ -#ifdef notyet -struct ubinfo { - long ub_addr; /* unibus address: mr + boff */ - int ub_nmr; /* number of registers, 0 if empty */ - int ub_bdp; /* bdp number, 0 if none */ -}; -#define UBAI_MR(i) (((i) >> 9) & 0x7ff) /* starting map register */ -#define UBAI_BOFF(i) ((i)&0x1ff) /* page offset */ -#else -#define UBAI_BDP(i) ((int)(((unsigned)(i)) >> 28)) -#define BDPMASK 0xf0000000 -#define UBAI_NMR(i) ((int)((i) >> 20) & 0xff) /* max 255 (=127.5K) */ -#define UBA_MAXNMR 255 -#define UBAI_MR(i) ((int)((i) >> 9) & 0x7ff) /* max 2047 */ -#define UBA_MAXMR 2047 -#define UBAI_BOFF(i) ((int)((i) & 0x1ff)) -#define UBAI_ADDR(i) ((int)((i) & 0xfffff)) /* uba addr (boff+mr) */ -#define UBAI_INFO(off, mr, nmr, bdp) \ - (((bdp) << 28) | ((nmr) << 20) | ((mr) << 9) | (off)) -#endif +#define MAXUBAXFER (63*1024) /* Max transfer size in bytes */ +#define UBAIOSIZE (8*1024) /* 8K I/O space */ +#define ubdevreg(addr) ((addr) & 017777) -#ifndef _LOCORE #ifdef _KERNEL -#define ubago(ui) ubaqueue(ui) #define b_forw b_hash.le_next /* Nice to have when handling uba queues */ void uba_attach __P((struct uba_softc *, unsigned long)); -int uballoc __P((struct uba_softc *, caddr_t, int, int)); -void ubarelse __P((struct uba_softc *, int *)); -int ubaqueue __P((struct uba_unit *, struct buf *)); -void ubadone __P((struct uba_unit *)); +void uba_enqueue __P((struct uba_unit *)); +void uba_done __P((struct uba_softc *)); void ubareset __P((int)); -int ubasetup __P((struct uba_softc *, struct buf *, int)); #endif /* _KERNEL */ -#endif !_LOCORE diff --git a/sys/dev/qbus/uda.c b/sys/dev/qbus/uda.c index 08b4bb8a0f5c..a20613870d32 100644 --- a/sys/dev/qbus/uda.c +++ b/sys/dev/qbus/uda.c @@ -1,4 +1,4 @@ -/* $NetBSD: uda.c,v 1.29 1999/05/29 17:03:17 ragge Exp $ */ +/* $NetBSD: uda.c,v 1.30 1999/06/06 19:14:49 ragge Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * Copyright (c) 1988 Regents of the University of California. @@ -45,18 +45,20 @@ #include #include #include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include +#include -#include -#include -#include +#include +#include +#include + +#include "ioconf.h" /* * Variants of SIMPLEQ macros for use with buf structs. @@ -81,11 +83,15 @@ struct uda_softc { SIMPLEQ_HEAD(, buf) sc_bufq; /* bufs awaiting for resources */ struct mscp_pack *sc_uuda; /* Unibus address of uda struct */ struct mscp_pack sc_uda; /* Struct for uda communication */ - struct udadevice *sc_udadev; /* pointer to ip/sa regs */ + bus_dma_tag_t sc_dmat; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_iph; + bus_space_handle_t sc_sah; + bus_dmamap_t sc_cmap;/* Control structures */ struct mscp *sc_mscp; /* Keep pointer to active mscp */ - short sc_ipl; /* interrupt priority, Q-bus */ struct mscp_softc *sc_softc; /* MSCP info (per mscpvar.h) */ int sc_wticks; /* watchdog timer ticks */ + int sc_inq; }; static int udamatch __P((struct device *, struct cfdata *, void *)); @@ -97,19 +103,15 @@ static void udaintr __P((int)); static void mtcintr __P((int)); static void intr __P((struct uda_softc *)); int udaready __P((struct uba_unit *)); -void udactlrdone __P((struct device *, int)); +void udactlrdone __P((struct device *)); int udaprint __P((void *, const char *)); void udasaerror __P((struct device *, int)); -int udago __P((struct device *, struct buf *)); - -extern struct cfdriver mtc_cd; +void udago __P((struct device *, struct mscp_xi *)); struct cfattach mtc_ca = { sizeof(struct uda_softc), udamatch, udaattach }; -extern struct cfdriver uda_cd; - struct cfattach uda_ca = { sizeof(struct uda_softc), udamatch, udaattach }; @@ -151,17 +153,15 @@ udamatch(parent, cf, aux) struct mscp_softc mi; /* Nice hack */ struct uba_softc *ubasc; int tries; -#if QBA && notyet - extern volatile int rbr; - int s; -#endif /* Get an interrupt vector. */ ubasc = (void *)parent; ivec_no = ubasc->uh_lastiv - 4; - mi.mi_sa = &((struct udadevice *)ua->ua_addr)->udasa; - mi.mi_ip = &((struct udadevice *)ua->ua_addr)->udaip; + mi.mi_iot = ua->ua_iot; + mi.mi_iph = ua->ua_ioh; + mi.mi_sah = ua->ua_ioh + 2; + mi.mi_swh = ua->ua_ioh + 2; /* * Initialise the controller (partially). The UDA50 programmer's @@ -171,28 +171,23 @@ udamatch(parent, cf, aux) * initialise within ten seconds. Or so I hear; I have not seen * this manual myself. */ -#if 0 - s = spl6(); -#endif tries = 0; again: - *mi.mi_ip = 0; + bus_space_write_2(mi.mi_iot, mi.mi_iph, 0, 0); /* Start init */ if (mscp_waitstep(&mi, MP_STEP1, MP_STEP1) == 0) return 0; /* Nothing here... */ - *mi.mi_sa = MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | MP_IE | - (ivec_no >> 2); + bus_space_write_2(mi.mi_iot, mi.mi_sah, 0, + MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | MP_IE | (ivec_no >> 2)); if (mscp_waitstep(&mi, MP_STEP2, MP_STEP2) == 0) { - printf("udaprobe: init step2 no change. sa=%x\n", *mi.mi_sa); + printf("udaprobe: init step2 no change. sa=%x\n", + bus_space_read_2(mi.mi_iot, mi.mi_sah, 0)); goto bad; } /* should have interrupted by now */ -#if 0 - rbr = qbgetpri(); -#endif if (strcmp(cf->cf_driver->cd_name, mtc_cd.cd_name)) { ua->ua_ivec = udaintr; ua->ua_reset = udareset; @@ -205,9 +200,6 @@ again: bad: if (++tries < 2) goto again; -#if 0 - splx(s); -#endif return 0; } @@ -220,17 +212,18 @@ udaattach(parent, self, aux) struct uba_attach_args *ua = aux; struct uba_softc *uh = (void *)parent; struct mscp_attach_args ma; - int ctlr, ubinfo; + int ctlr, error, rseg; + bus_dma_segment_t seg; printf("\n"); uh->uh_lastiv -= 4; /* remove dynamic interrupt vector */ -#ifdef QBA - sc->sc_ipl = ua->ua_br; -#endif + sc->sc_iot = ua->ua_iot; + sc->sc_iph = ua->ua_ioh; + sc->sc_sah = ua->ua_ioh + 2; + sc->sc_dmat = ua->ua_dmat; ctlr = sc->sc_dev.dv_unit; - sc->sc_udadev = (struct udadevice *)ua->ua_addr; SIMPLEQ_INIT(&sc->sc_bufq); /* @@ -244,16 +237,31 @@ udaattach(parent, self, aux) * Map the communication area and command and * response packets into Unibus space. */ - ubinfo = uballoc((struct uba_softc *)sc->sc_dev.dv_parent, - (caddr_t) &sc->sc_uda, sizeof (struct mscp_pack), UBA_CANTWAIT); - -#ifdef DIAGNOSTIC - if (ubinfo == 0) { - printf("%s: uballoc map failed\n", sc->sc_dev.dv_xname); + if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct mscp_pack), + NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { + printf("Alloc ctrl area %d\n", error); return; } -#endif - sc->sc_uuda = (struct mscp_pack *) UBAI_ADDR(ubinfo); + if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, + sizeof(struct mscp_pack), (caddr_t *) &sc->sc_uda, + BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { + printf("Map ctrl area %d\n", error); +err: bus_dmamem_free(sc->sc_dmat, &seg, rseg); + return; + } + if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct mscp_pack), + 1, sizeof(struct mscp_pack), 0, BUS_DMA_NOWAIT, &sc->sc_cmap))) { + printf("Create DMA map %d\n", error); +err2: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)&sc->sc_uda, + sizeof(struct mscp_pack)); + goto err; + } + if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap, + &sc->sc_uda, sizeof(struct mscp_pack), 0, BUS_DMA_NOWAIT))) { + printf("Load ctrl map %d\n", error); + bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap); + goto err2; + } bzero(&sc->sc_uda, sizeof (struct mscp_pack)); @@ -268,11 +276,14 @@ udaattach(parent, self, aux) ma.ma_mc = &uda_mscp_ctlr; ma.ma_type |= MSCPBUS_UDA; - ma.ma_uuda = sc->sc_uuda; ma.ma_uda = &sc->sc_uda; ma.ma_softc = &sc->sc_softc; - ma.ma_ip = &sc->sc_udadev->udaip; - ma.ma_sa = ma.ma_sw = &sc->sc_udadev->udasa; + ma.ma_iot = sc->sc_iot; + ma.ma_iph = sc->sc_iph; + ma.ma_sah = sc->sc_sah; + ma.ma_swh = sc->sc_sah; + ma.ma_dmat = sc->sc_dmat; + ma.ma_dmam = sc->sc_cmap; ma.ma_ivec = ivec_no; ma.ma_ctlrnr = (ua->ua_iaddr == 0172150 ? 0 : 1); /* XXX */ ma.ma_adapnr = uh->uh_nr; @@ -282,53 +293,63 @@ udaattach(parent, self, aux) /* * Start a transfer if there are free resources available, otherwise * let it go in udaready, forget it for now. + * Called from mscp routines. */ -int -udago(usc, bp) +void +udago(usc, mxi) struct device *usc; - struct buf *bp; + struct mscp_xi *mxi; { struct uda_softc *sc = (void *)usc; - struct uba_unit *uu = &sc->sc_unit; + struct uba_unit *uu; + struct buf *bp = mxi->mxi_bp; + int err; /* - * If we already are queued for resources, don't call ubaqueue - * again. (Then we would trash the wait queue). Just queue the - * buf and let the rest be done in udaready. + * If we already have transfers queued, don't try to load + * the map again. */ - if (sc->sc_bufq.sqh_first) - BUFQ_INSERT_TAIL(&sc->sc_bufq, bp) - else { - if (ubaqueue(uu, bp)) - mscp_dgo(sc->sc_softc, (UBAI_ADDR(uu->uu_ubinfo) | - (UBAI_BDP(uu->uu_ubinfo) << 24)),uu->uu_ubinfo,bp); - else - BUFQ_INSERT_TAIL(&sc->sc_bufq, bp) + if (sc->sc_inq == 0) { + err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam, + bp->b_un.b_addr, + bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT); + if (err == 0) { + mscp_dgo(sc->sc_softc, mxi); + return; + } } - - return 0; + uu = malloc(sizeof(struct uba_unit), M_DEVBUF, M_NOWAIT); + if (uu == 0) + panic("udago: no mem"); + uu->uu_ready = udaready; + uu->uu_softc = sc; + uu->uu_ref = mxi; + uba_enqueue(uu); + sc->sc_inq++; } /* * Called if we have been blocked for resources, and resources * have been freed again. Return 1 if we could start all * transfers again, 0 if we still are waiting. + * Called from uba resource free routines. */ int udaready(uu) struct uba_unit *uu; { struct uda_softc *sc = uu->uu_softc; - struct buf *bp; + struct mscp_xi *mxi = uu->uu_ref; + struct buf *bp = mxi->mxi_bp; + int err; - while ((bp = sc->sc_bufq.sqh_first)) { - if (ubaqueue(uu, bp)) { - BUFQ_REMOVE_HEAD(&sc->sc_bufq, bp); - mscp_dgo(sc->sc_softc, (UBAI_ADDR(uu->uu_ubinfo) | - (UBAI_BDP(uu->uu_ubinfo) << 24)),uu->uu_ubinfo,bp); - } else - return 0; - } + err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam, bp->b_un.b_addr, + bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT); + if (err) + return 0; + mscp_dgo(sc->sc_softc, mxi); + sc->sc_inq--; + free(uu, M_DEVBUF); return 1; } @@ -387,7 +408,7 @@ udasaerror(usc, doreset) int doreset; { struct uda_softc *sc = (void *)usc; - register int code = sc->sc_udadev->udasa; + register int code = bus_space_read_2(sc->sc_iot, sc->sc_sah, 0); register struct saerr *e; if ((code & MP_ERR) == 0) @@ -429,30 +450,28 @@ static void intr(sc) struct uda_softc *sc; { - volatile struct udadevice *udaddr = sc->sc_udadev; struct uba_softc *uh; struct mscp_pack *ud; -#ifdef QBA - if(vax_cputype == VAX_TYP_UV2) - splx(sc->sc_ipl); /* Qbus interrupt protocol is odd */ -#endif sc->sc_wticks = 0; /* reset interrupt watchdog */ - if (udaddr->udasa & MP_ERR) { /* ctlr fatal error */ + /* ctlr fatal error */ + if (bus_space_read_2(sc->sc_iot, sc->sc_sah, 0) & MP_ERR) { udasaerror(&sc->sc_dev, 1); return; } ud = &sc->sc_uda; /* * Handle buffer purge requests. + * XXX - should be done in bus_dma_sync(). */ uh = (void *)sc->sc_dev.dv_parent; if (ud->mp_ca.ca_bdp) { if (uh->uh_ubapurge) (*uh->uh_ubapurge)(uh, ud->mp_ca.ca_bdp); ud->mp_ca.ca_bdp = 0; - udaddr->udasa = 0; /* signal purge complete */ + /* signal purge complete */ + bus_space_write_2(sc->sc_iot, sc->sc_sah, 0, 0); } mscp_intr(sc->sc_softc); @@ -488,11 +507,9 @@ reset(sc) * UDA50 is not yet initialised. */ if (sc->sc_unit.uu_bdp) { - printf("<%d>", UBAI_BDP(sc->sc_unit.uu_bdp)); + /* printf("<%d>", UBAI_BDP(sc->sc_unit.uu_bdp)); */ sc->sc_unit.uu_bdp = 0; } - sc->sc_unit.uu_ubinfo = 0; -/* sc->sc_unit.uu_cmd = 0; XXX */ /* reset queues and requeue pending transfers */ mscp_requeue(sc->sc_softc); @@ -508,13 +525,10 @@ reset(sc) } void -udactlrdone(usc, info) +udactlrdone(usc) struct device *usc; - int info; { struct uda_softc *sc = (void *)usc; - /* XXX check if we shall release the BDP */ - sc->sc_unit.uu_ubinfo = info; - ubadone(&sc->sc_unit); + uba_done((struct uba_softc *)sc->sc_dev.dv_parent); }