diff --git a/sys/arch/vax/uba/uba.c b/sys/arch/vax/uba/uba.c index 88e85b932d5c..e9ac5bf5014b 100644 --- a/sys/arch/vax/uba/uba.c +++ b/sys/arch/vax/uba/uba.c @@ -1,4 +1,4 @@ -/* $NetBSD: uba.c,v 1.9 1995/11/10 19:25:49 ragge Exp $ */ +/* $NetBSD: uba.c,v 1.10 1995/12/01 19:22:56 ragge Exp $ */ /* * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -37,8 +37,6 @@ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 */ - /* All bugs are subject to removal without further notice */ - #include "sys/param.h" #include "sys/types.h" #include "sys/time.h" @@ -75,6 +73,8 @@ volatile int rbr,rcvec; int uba_match __P((struct device *, void *, void *)); void uba_attach __P((struct device *, struct device *, void *)); +void ubascan __P((struct device *, void *)); +int ubaprint __P((void *, char *)); struct cfdriver ubacd = { NULL, "uba", uba_match, uba_attach, DV_DULL, @@ -82,7 +82,7 @@ struct cfdriver ubacd = { }; - +#ifdef 0 /* * Mark addresses starting at "addr" and continuing * "size" bytes as allocated in the map "ualloc". @@ -107,7 +107,7 @@ csralloc(ualloc, addr, size) *p = 1; } } - +#endif /* * Stray interrupt vector handler, used when nowhere else to * go to. @@ -154,7 +154,7 @@ unifind(uhp0, pumem) #if DW780 || DWBUA struct uba_regs *vubp = uhp->uh_uba; #endif - +#if 0 /* * Initialize the UNIBUS, by freeing the map * registers and the buffered data path registers @@ -213,7 +213,7 @@ unifind(uhp0, pumem) * output to produce an interrupt. */ *(int *)(&uhp->uh_mr[0]) = UBAMR_MRV; - +#endif #define ubaddr(uhp, off) (u_short *)((int)(uhp)->uh_iopage + ubdevreg(off)) /* * Check each unibus mass storage controller. @@ -233,9 +233,10 @@ unifind(uhp0, pumem) * in the driver til we find it */ for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { - +#if 0 if (ualloc[ubdevreg(addr)]) continue; +#endif reg = ubaddr(uhp, addr); if (badaddr((caddr_t)reg, 2)) @@ -268,13 +269,15 @@ unifind(uhp0, pumem) continue; } printf("vec %o, ipl %x\n", rcvec << 2, rbr); +#if 0 csralloc(ualloc, addr, i); +#endif um->um_alive = 1; um->um_ubanum = uhp->uh_dev.dv_unit; um->um_hd = uhp; um->um_addr = (caddr_t)reg; udp->ud_minfo[um->um_ctlr] = um; - uhp->uh_idsp[rcvec].hoppaddr = (unsigned)um->um_intr; + uhp->uh_idsp[rcvec].hoppaddr = um->um_intr; uhp->uh_idsp[rcvec].pushlarg = um->um_ctlr; for (ui = ubdinit; ui->ui_driver; ui++) { int t; @@ -311,99 +314,9 @@ unifind(uhp0, pumem) break; } } - /* - * Now look for non-mass storage peripherals. - */ - for (ui = ubdinit; udp = ui->ui_driver; ui++) { - if (ui->ui_ubanum != uhp->uh_dev.dv_unit && ui->ui_ubanum != '?' || - ui->ui_alive || ui->ui_slave != -1) - continue; - addr = (u_short)(u_long)ui->ui_addr; - - for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { - - if (ualloc[ubdevreg(addr)]) - continue; - reg = ubaddr(uhp, addr); - if (badaddr((caddr_t)reg, 2)) - continue; -#ifdef DW780 - if (uhp->uh_type == DW780 && vubp->uba_sr) { - vubp->uba_sr = vubp->uba_sr; - continue; - } -#endif - rcvec = 0x200; - i = (*udp->ud_probe)(reg, ui); -#ifdef DW780 - if (uhp->uh_type == DW780 && vubp->uba_sr) { - vubp->uba_sr = vubp->uba_sr; - continue; - } -#endif - if (i == 0) - continue; - printf("%s%d at uba%d csr %o ", ui->ui_driver->ud_dname, - ui->ui_unit, uhp->uh_dev.dv_unit, addr); - if (rcvec == 0) { - printf("zero vector\n"); - continue; - } - if (rcvec == 0x200) { - printf("didn't interrupt\n"); - continue; - } - printf("vec %o, ipl %x\n", rcvec << 2, rbr); - csralloc(ualloc, addr, i); - ui->ui_hd = uhp; - uhp->uh_idsp[rcvec].hoppaddr = (unsigned)ui->ui_intr; - uhp->uh_idsp[rcvec].pushlarg = ui->ui_unit; - - ui->ui_alive = 1; - ui->ui_ubanum = uhp->uh_dev.dv_unit; - ui->ui_addr = (caddr_t)reg; - ui->ui_physaddr = pumem + ubdevreg(addr); - ui->ui_dk = -1; - /* ui_type comes from driver */ - udp->ud_dinfo[ui->ui_unit] = ui; - (*udp->ud_attach)(ui); - break; - } - } - -#ifdef DW780 - if (uhp->uh_type == DW780) - uhp->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | - UBACR_USEFIE | UBACR_SUEFIE | - (uhp->uh_uba->uba_cr & 0x7c000000); -#endif - -#ifdef AUTO_DEBUG - printf("Unibus allocation map"); - for (i = 0; i < 8*1024; ) { - register n, m; - - if ((i % 128) == 0) { - printf("\n%6o:", i); - for (n = 0; n < 128; n++) - if (ualloc[i+n]) - break; - if (n == 128) { - i += 128; - continue; - } - } - - for (n = m = 0; n < 16; n++) { - m <<= 1; - m |= ualloc[i++]; - } - - printf(" %4x", m); - } - printf("\n"); -#endif +#if 0 free(ualloc, M_TEMP); +#endif } @@ -513,7 +426,10 @@ ubadone(um) * Return value encodes map register plus page offset, * bdp number and number of map registers. */ -ubasetup(int uban,struct buf *bp,int flags) { +ubasetup(uban, bp, flags) + struct buf *bp; + int uban, flags; +{ struct uba_softc *uh = ubacd.cd_devs[uban]; struct pte *pte, *io; int npf; @@ -575,32 +491,33 @@ ubasetup(int uban,struct buf *bp,int flags) { temp |= UBAMR_BO; if ((bp->b_flags & B_PHYS) == 0) pte = (struct pte *)kvtopte(bp->b_un.b_addr); - else if (bp->b_flags & B_PAGET) { - panic("ubasetup: B_PAGET"); - } else { - if( bp->b_flags&B_DIRTY){ - rp=&pageproc[2]; - panic("ubasetup: B_DIRTY"); - } else { - rp =bp->b_proc; - } - v = btop((u_int)bp->b_un.b_addr&0x3fffffff); - if (bp->b_flags & B_UAREA){ - panic("ubasetup: B_UAREA"); - } else { -/* - * It may be better to use pmap_extract() here somewhere, - * but so far we do it "the hard way" :) - */ - u_int *hej; + else { + u_int *hej, i; - if(((u_int)bp->b_un.b_addr<0x40000000)|| - ((u_int)bp->b_un.b_addr>0x7fffffff)){ - hej=rp->p_vmspace->vm_pmap.pm_pcb->P0BR; - } else { - hej=rp->p_vmspace->vm_pmap.pm_pcb->P1BR; + rp = bp->b_proc; + v = btop((u_int)bp->b_un.b_addr&0x3fffffff); + + /* + * It may be better to use pmap_extract() here + * somewhere, but so far we do it "the hard way" :) + */ + if (((u_int)bp->b_un.b_addr < 0x40000000) || + ((u_int)bp->b_un.b_addr > 0x7fffffff)) + hej = rp->p_vmspace->vm_pmap.pm_pcb->P0BR; + else + hej = rp->p_vmspace->vm_pmap.pm_pcb->P1BR; + + pte = (struct pte *)&hej[v]; + for (i = 0; i < (npf - 1); i++) { + if ((pte + i)->pg_pfn == 0) { + int rv; + + rv = vm_fault(&rp->p_vmspace->vm_map, + (u_int)bp->b_un.b_addr + i * NBPG, + VM_PROT_READ, FALSE); + if (rv) + panic("DMA to nonexistent page"); } - pte=(struct pte*)&hej[v]; } } io = &uh->uh_mr[reg]; @@ -618,7 +535,10 @@ ubasetup(int uban,struct buf *bp,int flags) { /* * Non buffer setup interface... set up a buffer and call ubasetup. */ -uballoc(int uban,caddr_t addr,int bcnt,int flags) { +uballoc(uban, addr, bcnt, flags) + caddr_t addr; + int uban, bcnt, flags; +{ struct buf ubabuf; ubabuf.b_un.b_addr = addr; @@ -634,7 +554,7 @@ uballoc(int uban,caddr_t addr,int bcnt,int flags) { * against uba resets on 11/780's. */ ubarelse(uban, amr) - int *amr; + int uban, *amr; { register struct uba_softc *uh = ubacd.cd_devs[uban]; register int bdp, reg, npf, s; @@ -786,8 +706,10 @@ ubareset(uban) wakeup((caddr_t)&uh->uh_bdpwant); wakeup((caddr_t)&uh->uh_mrwant); printf("uba%d: reset", uban); - ubainit(uh->uh_uba); + ubainit(uh); +#ifdef notyet ubameminit(uban); +#endif /* XXX - ??? * Intressant, vi m}ste l|sa det h{r med ubareset() p} n}t smart * s{tt. En l{nkad lista som s{tts upp vid autoconfiggen? Kanske. @@ -795,6 +717,7 @@ ubareset(uban) * ren sm|rja den gamla koden. F}r peturba lite mer docs... * 950428/Ragge */ + udareset(0); /* XXX */ /* for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) (*cdp->d_reset)(uban); ifubareset(uban); @@ -810,39 +733,17 @@ ubareset(uban) * In these cases we really don't need the interrupts * enabled, but since we run with ipl high, we don't care * if they are, they will never happen anyways. - * SHOULD GET POINTER TO UBA_HD INSTEAD OF UBA. */ -ubainit(uba) - register struct uba_regs *uba; +void +ubainit(uhp) + struct uba_softc *uhp; { - register struct uba_softc *uhp; -#ifdef QBA - int isphys = 0; -#endif -panic("ubainit"); -#if 0 - for (uhp = uba_hd; uhp < uba_hd + numuba; uhp++) { - if (uhp->uh_uba == uba) - break; - if (uhp->uh_physuba == uba) { -#ifdef QBA - isphys++; -#endif - break; - } - } - - if (uhp >= uba_hd + numuba) { - printf("init unknown uba\n"); - return; - } -#endif switch (uhp->uh_type) { #ifdef DWBUA case DWBUA: BUA(uba)->bua_csr |= BUACSR_UPI; /* give devices time to recover from power fail */ - waitabit(500); + DELAY(500000); break; #endif #ifdef DW780 @@ -865,22 +766,18 @@ panic("ubainit"); #if DW750 || DW730 || QBA mtpr(0, PR_IUR); /* give devices time to recover from power fail */ -#if 0 + /* THIS IS PROBABLY UNNECESSARY */ - waitabit(50); + DELAY(500000); /* END PROBABLY UNNECESSARY */ -#endif + #ifdef QBA /* * Re-enable local memory access * from the Q-bus. */ - if (uhp->uh_type == QBA) { - if (isphys) - *((char *)QIOPAGE630 + QIPCR) = Q_LMEAE; - else - *(uhp->uh_iopage + QIPCR) = Q_LMEAE; - } + if (uhp->uh_type == QBA) + *((u_short *)(uhp->uh_iopage + QIPCR)) = Q_LMEAE; #endif QBA break; #endif DW750 || DW730 || QBA @@ -994,6 +891,7 @@ ubaerror(uban, uh, ipl, uvec, uba) * configured (has no csr or interrupt, so doesn't need to be probed), * and -1 on failure. */ +#ifdef notyet ubameminit(uban) { register struct uba_device *ui; @@ -1039,6 +937,7 @@ jdhfgsjdkfhgsdjkfghak } #endif } +#endif rmget(){ showstate(curproc); @@ -1168,6 +1067,9 @@ uba_attach(parent, self, aux) struct uba_regs *ubar = (struct uba_regs *)sa->nexaddr; struct uba_softc *sc = (struct uba_softc *)self; vm_offset_t min, max, ubaphys, ubaiophys; +#if DW780 || DWBUA + struct uba_regs *vubp = sc->uh_uba; +#endif void ubascan(); printf("\n"); @@ -1200,7 +1102,7 @@ uba_attach(parent, self, aux) bcopy(&idsptch, &sc->uh_idsp[i], sizeof(struct ivec_dsp)); sc->uh_idsp[i].pushlarg = sa->nexinfo; - sc->uh_idsp[i].hoppaddr = (unsigned int)ubastray; + sc->uh_idsp[i].hoppaddr = ubastray; sc->uh_iarea[i] = (unsigned int)&sc->uh_idsp[i]; } } @@ -1243,11 +1145,125 @@ uba_attach(parent, self, aux) if (cpu_type == VAX_630) *((u_short *)(sc->uh_iopage + QIPCR)) = Q_LMEAE; #endif + /* + * 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); -#ifdef notyet - config_scan(ubascan,self); -#else - unifind(sc, ubaiophys); + /* + * Set last free interrupt vector for devices with + * programmable interrupt vectors. Use is to decrement + * this number and use result as interrupt vector. + */ + sc->uh_lastiv = 0x200; + +#ifdef DWBUA + if (uhp->uh_type == DWBUA) + BUA(vubp)->bua_offset = (int)uhp->uh_vec - (int)&scb[0]; #endif + +#ifdef DW780 + if (uhp->uh_type == DW780) { + vubp->uba_sr = vubp->uba_sr; + vubp->uba_cr = UBACR_IFS|UBACR_BRIE; + } +#endif +#ifdef notyet + /* + * First configure devices that have unibus memory, + * allowing them to allocate the correct map registers. + */ + ubameminit(uhp->uh_dev.dv_unit); +#endif + /* + * Map the first page of UNIBUS i/o space to the first page of memory + * for devices which will need to dma output to produce an interrupt. + * ??? - Why? This is rpb page... /ragge + */ + *(int *)(&sc->uh_mr[0]) = UBAMR_MRV; + + /* + * Now start searching for devices. + */ + unifind(sc, ubaiophys); /* Some devices are not yet converted */ + config_scan(ubascan,self); + +#ifdef DW780 + if (uhp->uh_type == DW780) + uhp->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | + UBACR_USEFIE | UBACR_SUEFIE | + (uhp->uh_uba->uba_cr & 0x7c000000); +#endif + } +void +ubascan(parent, match) + struct device *parent; + void *match; +{ + struct device *dev = match; + struct cfdata *cf = dev->dv_cfdata; + struct uba_softc *sc = (struct uba_softc *)parent; + struct uba_attach_args ua; + int i; + + ua.ua_addr = (caddr_t)ubaddr(sc, cf->cf_loc[0]); + + if (badaddr(ua.ua_addr, 2)) + goto forgetit; + +#ifdef DW780 + if (uhp->uh_type == DW780 && vubp->uba_sr) { + vubp->uba_sr = vubp->uba_sr; + continue; + } +#endif + rcvec = 0x200; + i = (*cf->cf_driver->cd_match) (parent, dev, &ua); + +#ifdef DW780 + if (uhp->uh_type == DW780 && vubp->uba_sr) { + vubp->uba_sr = vubp->uba_sr; + continue; + } +#endif + if (i == 0) + goto forgetit; + + if (rcvec == 0 || rcvec == 0x200) + goto fail; + + sc->uh_idsp[rcvec].hoppaddr = ua.ua_ivec; + sc->uh_idsp[rcvec].pushlarg = ua.ua_iarg; + ua.ua_br = rbr; + ua.ua_cvec = rcvec; + ua.ua_iaddr = dev->dv_cfdata->cf_loc[0]; + + config_attach(parent, dev, &ua, ubaprint); + return; + +fail: + printf("%s at %s csr %o %s\n", dev->dv_cfdata->cf_driver->cd_name, + parent->dv_xname, dev->dv_cfdata->cf_loc[0] << 2, + rcvec ? "didn't interrupt\n" : "zero vector\n"); + +forgetit: + free(dev, M_DEVBUF); +} + +int +ubaprint(aux, uba) + void *aux; + char *uba; +{ + struct uba_attach_args *ua = aux; + + printf(" csr %o vec %o ipl %x", ua->ua_iaddr, + ua->ua_cvec << 2, ua->ua_br); + return UNCONF; +} diff --git a/sys/arch/vax/uba/ubavar.h b/sys/arch/vax/uba/ubavar.h index fdd8d7b3d099..23d190ebcc63 100644 --- a/sys/arch/vax/uba/ubavar.h +++ b/sys/arch/vax/uba/ubavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ubavar.h,v 1.7 1995/11/10 19:25:51 ragge Exp $ */ +/* $NetBSD: ubavar.h,v 1.8 1995/12/01 19:23:01 ragge Exp $ */ /* * Copyright (c) 1982, 1986 Regents of the University of California. @@ -44,8 +44,6 @@ * Each unibus device has a uba_device structure. */ -#ifndef LOCORE - #include "sys/buf.h" #include "sys/device.h" /* @@ -186,7 +184,19 @@ struct uba_driver { short ud_keepbdp; /* hang on to bdp's once allocated */ int (*ud_ubamem)(); /* see if dedicated memory is present */ }; -#endif + +/* + * uba_attach_args is used during autoconfiguration. It is sent + * from ubascan() to each (possible) device. + */ +struct uba_attach_args { + caddr_t ua_addr; + void (*ua_ivec)(); + int ua_iarg; + int ua_iaddr; + int ua_br; + int ua_cvec; +}; /* * Flags to UBA map/bdp allocation routines @@ -234,5 +244,7 @@ extern struct uba_device ubdinit[]; extern struct cfdriver ubacd; +void ubainit __P((struct uba_softc *)); + #endif /* _KERNEL */ #endif !LOCORE diff --git a/sys/dev/dec/qbus/uba.c b/sys/dev/dec/qbus/uba.c index 88e85b932d5c..e9ac5bf5014b 100644 --- a/sys/dev/dec/qbus/uba.c +++ b/sys/dev/dec/qbus/uba.c @@ -1,4 +1,4 @@ -/* $NetBSD: uba.c,v 1.9 1995/11/10 19:25:49 ragge Exp $ */ +/* $NetBSD: uba.c,v 1.10 1995/12/01 19:22:56 ragge Exp $ */ /* * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -37,8 +37,6 @@ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 */ - /* All bugs are subject to removal without further notice */ - #include "sys/param.h" #include "sys/types.h" #include "sys/time.h" @@ -75,6 +73,8 @@ volatile int rbr,rcvec; int uba_match __P((struct device *, void *, void *)); void uba_attach __P((struct device *, struct device *, void *)); +void ubascan __P((struct device *, void *)); +int ubaprint __P((void *, char *)); struct cfdriver ubacd = { NULL, "uba", uba_match, uba_attach, DV_DULL, @@ -82,7 +82,7 @@ struct cfdriver ubacd = { }; - +#ifdef 0 /* * Mark addresses starting at "addr" and continuing * "size" bytes as allocated in the map "ualloc". @@ -107,7 +107,7 @@ csralloc(ualloc, addr, size) *p = 1; } } - +#endif /* * Stray interrupt vector handler, used when nowhere else to * go to. @@ -154,7 +154,7 @@ unifind(uhp0, pumem) #if DW780 || DWBUA struct uba_regs *vubp = uhp->uh_uba; #endif - +#if 0 /* * Initialize the UNIBUS, by freeing the map * registers and the buffered data path registers @@ -213,7 +213,7 @@ unifind(uhp0, pumem) * output to produce an interrupt. */ *(int *)(&uhp->uh_mr[0]) = UBAMR_MRV; - +#endif #define ubaddr(uhp, off) (u_short *)((int)(uhp)->uh_iopage + ubdevreg(off)) /* * Check each unibus mass storage controller. @@ -233,9 +233,10 @@ unifind(uhp0, pumem) * in the driver til we find it */ for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { - +#if 0 if (ualloc[ubdevreg(addr)]) continue; +#endif reg = ubaddr(uhp, addr); if (badaddr((caddr_t)reg, 2)) @@ -268,13 +269,15 @@ unifind(uhp0, pumem) continue; } printf("vec %o, ipl %x\n", rcvec << 2, rbr); +#if 0 csralloc(ualloc, addr, i); +#endif um->um_alive = 1; um->um_ubanum = uhp->uh_dev.dv_unit; um->um_hd = uhp; um->um_addr = (caddr_t)reg; udp->ud_minfo[um->um_ctlr] = um; - uhp->uh_idsp[rcvec].hoppaddr = (unsigned)um->um_intr; + uhp->uh_idsp[rcvec].hoppaddr = um->um_intr; uhp->uh_idsp[rcvec].pushlarg = um->um_ctlr; for (ui = ubdinit; ui->ui_driver; ui++) { int t; @@ -311,99 +314,9 @@ unifind(uhp0, pumem) break; } } - /* - * Now look for non-mass storage peripherals. - */ - for (ui = ubdinit; udp = ui->ui_driver; ui++) { - if (ui->ui_ubanum != uhp->uh_dev.dv_unit && ui->ui_ubanum != '?' || - ui->ui_alive || ui->ui_slave != -1) - continue; - addr = (u_short)(u_long)ui->ui_addr; - - for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { - - if (ualloc[ubdevreg(addr)]) - continue; - reg = ubaddr(uhp, addr); - if (badaddr((caddr_t)reg, 2)) - continue; -#ifdef DW780 - if (uhp->uh_type == DW780 && vubp->uba_sr) { - vubp->uba_sr = vubp->uba_sr; - continue; - } -#endif - rcvec = 0x200; - i = (*udp->ud_probe)(reg, ui); -#ifdef DW780 - if (uhp->uh_type == DW780 && vubp->uba_sr) { - vubp->uba_sr = vubp->uba_sr; - continue; - } -#endif - if (i == 0) - continue; - printf("%s%d at uba%d csr %o ", ui->ui_driver->ud_dname, - ui->ui_unit, uhp->uh_dev.dv_unit, addr); - if (rcvec == 0) { - printf("zero vector\n"); - continue; - } - if (rcvec == 0x200) { - printf("didn't interrupt\n"); - continue; - } - printf("vec %o, ipl %x\n", rcvec << 2, rbr); - csralloc(ualloc, addr, i); - ui->ui_hd = uhp; - uhp->uh_idsp[rcvec].hoppaddr = (unsigned)ui->ui_intr; - uhp->uh_idsp[rcvec].pushlarg = ui->ui_unit; - - ui->ui_alive = 1; - ui->ui_ubanum = uhp->uh_dev.dv_unit; - ui->ui_addr = (caddr_t)reg; - ui->ui_physaddr = pumem + ubdevreg(addr); - ui->ui_dk = -1; - /* ui_type comes from driver */ - udp->ud_dinfo[ui->ui_unit] = ui; - (*udp->ud_attach)(ui); - break; - } - } - -#ifdef DW780 - if (uhp->uh_type == DW780) - uhp->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | - UBACR_USEFIE | UBACR_SUEFIE | - (uhp->uh_uba->uba_cr & 0x7c000000); -#endif - -#ifdef AUTO_DEBUG - printf("Unibus allocation map"); - for (i = 0; i < 8*1024; ) { - register n, m; - - if ((i % 128) == 0) { - printf("\n%6o:", i); - for (n = 0; n < 128; n++) - if (ualloc[i+n]) - break; - if (n == 128) { - i += 128; - continue; - } - } - - for (n = m = 0; n < 16; n++) { - m <<= 1; - m |= ualloc[i++]; - } - - printf(" %4x", m); - } - printf("\n"); -#endif +#if 0 free(ualloc, M_TEMP); +#endif } @@ -513,7 +426,10 @@ ubadone(um) * Return value encodes map register plus page offset, * bdp number and number of map registers. */ -ubasetup(int uban,struct buf *bp,int flags) { +ubasetup(uban, bp, flags) + struct buf *bp; + int uban, flags; +{ struct uba_softc *uh = ubacd.cd_devs[uban]; struct pte *pte, *io; int npf; @@ -575,32 +491,33 @@ ubasetup(int uban,struct buf *bp,int flags) { temp |= UBAMR_BO; if ((bp->b_flags & B_PHYS) == 0) pte = (struct pte *)kvtopte(bp->b_un.b_addr); - else if (bp->b_flags & B_PAGET) { - panic("ubasetup: B_PAGET"); - } else { - if( bp->b_flags&B_DIRTY){ - rp=&pageproc[2]; - panic("ubasetup: B_DIRTY"); - } else { - rp =bp->b_proc; - } - v = btop((u_int)bp->b_un.b_addr&0x3fffffff); - if (bp->b_flags & B_UAREA){ - panic("ubasetup: B_UAREA"); - } else { -/* - * It may be better to use pmap_extract() here somewhere, - * but so far we do it "the hard way" :) - */ - u_int *hej; + else { + u_int *hej, i; - if(((u_int)bp->b_un.b_addr<0x40000000)|| - ((u_int)bp->b_un.b_addr>0x7fffffff)){ - hej=rp->p_vmspace->vm_pmap.pm_pcb->P0BR; - } else { - hej=rp->p_vmspace->vm_pmap.pm_pcb->P1BR; + rp = bp->b_proc; + v = btop((u_int)bp->b_un.b_addr&0x3fffffff); + + /* + * It may be better to use pmap_extract() here + * somewhere, but so far we do it "the hard way" :) + */ + if (((u_int)bp->b_un.b_addr < 0x40000000) || + ((u_int)bp->b_un.b_addr > 0x7fffffff)) + hej = rp->p_vmspace->vm_pmap.pm_pcb->P0BR; + else + hej = rp->p_vmspace->vm_pmap.pm_pcb->P1BR; + + pte = (struct pte *)&hej[v]; + for (i = 0; i < (npf - 1); i++) { + if ((pte + i)->pg_pfn == 0) { + int rv; + + rv = vm_fault(&rp->p_vmspace->vm_map, + (u_int)bp->b_un.b_addr + i * NBPG, + VM_PROT_READ, FALSE); + if (rv) + panic("DMA to nonexistent page"); } - pte=(struct pte*)&hej[v]; } } io = &uh->uh_mr[reg]; @@ -618,7 +535,10 @@ ubasetup(int uban,struct buf *bp,int flags) { /* * Non buffer setup interface... set up a buffer and call ubasetup. */ -uballoc(int uban,caddr_t addr,int bcnt,int flags) { +uballoc(uban, addr, bcnt, flags) + caddr_t addr; + int uban, bcnt, flags; +{ struct buf ubabuf; ubabuf.b_un.b_addr = addr; @@ -634,7 +554,7 @@ uballoc(int uban,caddr_t addr,int bcnt,int flags) { * against uba resets on 11/780's. */ ubarelse(uban, amr) - int *amr; + int uban, *amr; { register struct uba_softc *uh = ubacd.cd_devs[uban]; register int bdp, reg, npf, s; @@ -786,8 +706,10 @@ ubareset(uban) wakeup((caddr_t)&uh->uh_bdpwant); wakeup((caddr_t)&uh->uh_mrwant); printf("uba%d: reset", uban); - ubainit(uh->uh_uba); + ubainit(uh); +#ifdef notyet ubameminit(uban); +#endif /* XXX - ??? * Intressant, vi m}ste l|sa det h{r med ubareset() p} n}t smart * s{tt. En l{nkad lista som s{tts upp vid autoconfiggen? Kanske. @@ -795,6 +717,7 @@ ubareset(uban) * ren sm|rja den gamla koden. F}r peturba lite mer docs... * 950428/Ragge */ + udareset(0); /* XXX */ /* for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) (*cdp->d_reset)(uban); ifubareset(uban); @@ -810,39 +733,17 @@ ubareset(uban) * In these cases we really don't need the interrupts * enabled, but since we run with ipl high, we don't care * if they are, they will never happen anyways. - * SHOULD GET POINTER TO UBA_HD INSTEAD OF UBA. */ -ubainit(uba) - register struct uba_regs *uba; +void +ubainit(uhp) + struct uba_softc *uhp; { - register struct uba_softc *uhp; -#ifdef QBA - int isphys = 0; -#endif -panic("ubainit"); -#if 0 - for (uhp = uba_hd; uhp < uba_hd + numuba; uhp++) { - if (uhp->uh_uba == uba) - break; - if (uhp->uh_physuba == uba) { -#ifdef QBA - isphys++; -#endif - break; - } - } - - if (uhp >= uba_hd + numuba) { - printf("init unknown uba\n"); - return; - } -#endif switch (uhp->uh_type) { #ifdef DWBUA case DWBUA: BUA(uba)->bua_csr |= BUACSR_UPI; /* give devices time to recover from power fail */ - waitabit(500); + DELAY(500000); break; #endif #ifdef DW780 @@ -865,22 +766,18 @@ panic("ubainit"); #if DW750 || DW730 || QBA mtpr(0, PR_IUR); /* give devices time to recover from power fail */ -#if 0 + /* THIS IS PROBABLY UNNECESSARY */ - waitabit(50); + DELAY(500000); /* END PROBABLY UNNECESSARY */ -#endif + #ifdef QBA /* * Re-enable local memory access * from the Q-bus. */ - if (uhp->uh_type == QBA) { - if (isphys) - *((char *)QIOPAGE630 + QIPCR) = Q_LMEAE; - else - *(uhp->uh_iopage + QIPCR) = Q_LMEAE; - } + if (uhp->uh_type == QBA) + *((u_short *)(uhp->uh_iopage + QIPCR)) = Q_LMEAE; #endif QBA break; #endif DW750 || DW730 || QBA @@ -994,6 +891,7 @@ ubaerror(uban, uh, ipl, uvec, uba) * configured (has no csr or interrupt, so doesn't need to be probed), * and -1 on failure. */ +#ifdef notyet ubameminit(uban) { register struct uba_device *ui; @@ -1039,6 +937,7 @@ jdhfgsjdkfhgsdjkfghak } #endif } +#endif rmget(){ showstate(curproc); @@ -1168,6 +1067,9 @@ uba_attach(parent, self, aux) struct uba_regs *ubar = (struct uba_regs *)sa->nexaddr; struct uba_softc *sc = (struct uba_softc *)self; vm_offset_t min, max, ubaphys, ubaiophys; +#if DW780 || DWBUA + struct uba_regs *vubp = sc->uh_uba; +#endif void ubascan(); printf("\n"); @@ -1200,7 +1102,7 @@ uba_attach(parent, self, aux) bcopy(&idsptch, &sc->uh_idsp[i], sizeof(struct ivec_dsp)); sc->uh_idsp[i].pushlarg = sa->nexinfo; - sc->uh_idsp[i].hoppaddr = (unsigned int)ubastray; + sc->uh_idsp[i].hoppaddr = ubastray; sc->uh_iarea[i] = (unsigned int)&sc->uh_idsp[i]; } } @@ -1243,11 +1145,125 @@ uba_attach(parent, self, aux) if (cpu_type == VAX_630) *((u_short *)(sc->uh_iopage + QIPCR)) = Q_LMEAE; #endif + /* + * 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); -#ifdef notyet - config_scan(ubascan,self); -#else - unifind(sc, ubaiophys); + /* + * Set last free interrupt vector for devices with + * programmable interrupt vectors. Use is to decrement + * this number and use result as interrupt vector. + */ + sc->uh_lastiv = 0x200; + +#ifdef DWBUA + if (uhp->uh_type == DWBUA) + BUA(vubp)->bua_offset = (int)uhp->uh_vec - (int)&scb[0]; #endif + +#ifdef DW780 + if (uhp->uh_type == DW780) { + vubp->uba_sr = vubp->uba_sr; + vubp->uba_cr = UBACR_IFS|UBACR_BRIE; + } +#endif +#ifdef notyet + /* + * First configure devices that have unibus memory, + * allowing them to allocate the correct map registers. + */ + ubameminit(uhp->uh_dev.dv_unit); +#endif + /* + * Map the first page of UNIBUS i/o space to the first page of memory + * for devices which will need to dma output to produce an interrupt. + * ??? - Why? This is rpb page... /ragge + */ + *(int *)(&sc->uh_mr[0]) = UBAMR_MRV; + + /* + * Now start searching for devices. + */ + unifind(sc, ubaiophys); /* Some devices are not yet converted */ + config_scan(ubascan,self); + +#ifdef DW780 + if (uhp->uh_type == DW780) + uhp->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | + UBACR_USEFIE | UBACR_SUEFIE | + (uhp->uh_uba->uba_cr & 0x7c000000); +#endif + } +void +ubascan(parent, match) + struct device *parent; + void *match; +{ + struct device *dev = match; + struct cfdata *cf = dev->dv_cfdata; + struct uba_softc *sc = (struct uba_softc *)parent; + struct uba_attach_args ua; + int i; + + ua.ua_addr = (caddr_t)ubaddr(sc, cf->cf_loc[0]); + + if (badaddr(ua.ua_addr, 2)) + goto forgetit; + +#ifdef DW780 + if (uhp->uh_type == DW780 && vubp->uba_sr) { + vubp->uba_sr = vubp->uba_sr; + continue; + } +#endif + rcvec = 0x200; + i = (*cf->cf_driver->cd_match) (parent, dev, &ua); + +#ifdef DW780 + if (uhp->uh_type == DW780 && vubp->uba_sr) { + vubp->uba_sr = vubp->uba_sr; + continue; + } +#endif + if (i == 0) + goto forgetit; + + if (rcvec == 0 || rcvec == 0x200) + goto fail; + + sc->uh_idsp[rcvec].hoppaddr = ua.ua_ivec; + sc->uh_idsp[rcvec].pushlarg = ua.ua_iarg; + ua.ua_br = rbr; + ua.ua_cvec = rcvec; + ua.ua_iaddr = dev->dv_cfdata->cf_loc[0]; + + config_attach(parent, dev, &ua, ubaprint); + return; + +fail: + printf("%s at %s csr %o %s\n", dev->dv_cfdata->cf_driver->cd_name, + parent->dv_xname, dev->dv_cfdata->cf_loc[0] << 2, + rcvec ? "didn't interrupt\n" : "zero vector\n"); + +forgetit: + free(dev, M_DEVBUF); +} + +int +ubaprint(aux, uba) + void *aux; + char *uba; +{ + struct uba_attach_args *ua = aux; + + printf(" csr %o vec %o ipl %x", ua->ua_iaddr, + ua->ua_cvec << 2, ua->ua_br); + return UNCONF; +} diff --git a/sys/dev/dec/qbus/ubavar.h b/sys/dev/dec/qbus/ubavar.h index fdd8d7b3d099..23d190ebcc63 100644 --- a/sys/dev/dec/qbus/ubavar.h +++ b/sys/dev/dec/qbus/ubavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ubavar.h,v 1.7 1995/11/10 19:25:51 ragge Exp $ */ +/* $NetBSD: ubavar.h,v 1.8 1995/12/01 19:23:01 ragge Exp $ */ /* * Copyright (c) 1982, 1986 Regents of the University of California. @@ -44,8 +44,6 @@ * Each unibus device has a uba_device structure. */ -#ifndef LOCORE - #include "sys/buf.h" #include "sys/device.h" /* @@ -186,7 +184,19 @@ struct uba_driver { short ud_keepbdp; /* hang on to bdp's once allocated */ int (*ud_ubamem)(); /* see if dedicated memory is present */ }; -#endif + +/* + * uba_attach_args is used during autoconfiguration. It is sent + * from ubascan() to each (possible) device. + */ +struct uba_attach_args { + caddr_t ua_addr; + void (*ua_ivec)(); + int ua_iarg; + int ua_iaddr; + int ua_br; + int ua_cvec; +}; /* * Flags to UBA map/bdp allocation routines @@ -234,5 +244,7 @@ extern struct uba_device ubdinit[]; extern struct cfdriver ubacd; +void ubainit __P((struct uba_softc *)); + #endif /* _KERNEL */ #endif !LOCORE