/* $NetBSD: bus_subr.c,v 1.4 1997/03/13 17:40:38 gwr Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Adam Glass and Gordon W. Ross. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * bus_xxx support functions */ #include #include #include #include #include #include #include #include #include #include #include #include #include label_t *nofault; /* This is defined in _startup.c */ extern vm_offset_t tmp_vpages[]; static const int bustype_to_patype[4] = { 0, /* OBMEM */ 0, /* OBIO */ PMAP_VME16, /* VMED16 */ PMAP_VME32, /* VMED32 */ }; /* * Read addr with size len (1,2,4) into val. * If this generates a bus error, return -1 * * Create a temporary mapping, * Try the access using peek_* * Clean up temp. mapping */ int bus_peek(bustype, paddr, sz) int bustype, paddr, sz; { int offset, rtn; vm_offset_t va_page; caddr_t va; /* XXX - Must fix for VME support... */ if (bustype != OBIO && bustype != OBMEM) return -1; offset = paddr & ~(MMU_PAGE_MASK); paddr = _trunc_page(paddr); paddr |= bustype_to_patype[bustype]; paddr |= PMAP_NC; va_page = tmp_vpages[0]; va = (caddr_t) va_page + offset; pmap_enter(pmap_kernel(), va_page, paddr, (VM_PROT_READ|VM_PROT_WRITE), TRUE); switch (sz) { case 1: rtn = peek_byte(va); break; case 2: rtn = peek_word(va); break; case 4: rtn = peek_long(va); break; default: printf(" bus_peek: invalid size=%d\n", sz); rtn = -1; } pmap_remove(pmap_kernel(), va_page, va_page + NBPG); return rtn; } void * bus_mapin(bustype, paddr, sz) int bustype, paddr, sz; { int off, pa, pmt; vm_offset_t va, retval; if (bustype & ~3) return (NULL); off = paddr & PGOFSET; pa = paddr - off; sz += off; sz = round_page(sz); pmt = PMAP_NC; /* non-cached */ /* Get some kernel virtual address space. */ va = kmem_alloc_wait(kernel_map, sz); if (va == 0) panic("bus_mapin"); retval = va + off; /* Map it to the specified bus. */ #if 0 /* XXX */ /* This has a problem with wrap-around... */ pmap_map((int)va, pa | pmt, pa + sz, VM_PROT_ALL); #else do { pmap_enter(pmap_kernel(), va, pa | pmt, VM_PROT_ALL, FALSE); va += NBPG; pa += NBPG; } while ((sz -= NBPG) > 0); #endif return ((void*)retval); } /* from hp300: badbaddr() */ int peek_byte(addr) register caddr_t addr; { label_t faultbuf; register int x; nofault = &faultbuf; if (setjmp(&faultbuf)) { nofault = NULL; return(-1); } x = *(volatile u_char *)addr; nofault = NULL; return(x); } int peek_word(addr) register caddr_t addr; { label_t faultbuf; register int x; nofault = &faultbuf; if (setjmp(&faultbuf)) { nofault = NULL; return(-1); } x = *(volatile u_short *)addr; nofault = NULL; return(x); } int peek_long(addr) register caddr_t addr; { label_t faultbuf; register int x; nofault = &faultbuf; if (setjmp(&faultbuf)) { nofault = NULL; return(-1); } x = *(volatile int *)addr; nofault = NULL; return(x); }