ofrom.c revision 1.5
11.5Sgehenna/* $NetBSD: ofrom.c,v 1.5 2002/09/06 13:18:43 gehenna Exp $ */ 21.1Sthorpej 31.1Sthorpej/* 41.1Sthorpej * Copyright 1998 51.1Sthorpej * Digital Equipment Corporation. All rights reserved. 61.1Sthorpej * 71.1Sthorpej * This software is furnished under license and may be used and 81.1Sthorpej * copied only in accordance with the following terms and conditions. 91.1Sthorpej * Subject to these conditions, you may download, copy, install, 101.1Sthorpej * use, modify and distribute this software in source and/or binary 111.1Sthorpej * form. No title or ownership is transferred hereby. 121.1Sthorpej * 131.1Sthorpej * 1) Any source code used, modified or distributed must reproduce 141.1Sthorpej * and retain this copyright notice and list of conditions as 151.1Sthorpej * they appear in the source file. 161.1Sthorpej * 171.1Sthorpej * 2) No right is granted to use any trade name, trademark, or logo of 181.1Sthorpej * Digital Equipment Corporation. Neither the "Digital Equipment 191.1Sthorpej * Corporation" name nor any trademark or logo of Digital Equipment 201.1Sthorpej * Corporation may be used to endorse or promote products derived 211.1Sthorpej * from this software without the prior written permission of 221.1Sthorpej * Digital Equipment Corporation. 231.1Sthorpej * 241.1Sthorpej * 3) This software is provided "AS-IS" and any express or implied 251.1Sthorpej * warranties, including but not limited to, any implied warranties 261.1Sthorpej * of merchantability, fitness for a particular purpose, or 271.1Sthorpej * non-infringement are disclaimed. In no event shall DIGITAL be 281.1Sthorpej * liable for any damages whatsoever, and in particular, DIGITAL 291.1Sthorpej * shall not be liable for special, indirect, consequential, or 301.1Sthorpej * incidental damages or damages for lost profits, loss of 311.1Sthorpej * revenue or loss of use, whether such damages arise in contract, 321.1Sthorpej * negligence, tort, under statute, in equity, at law or otherwise, 331.1Sthorpej * even if advised of the possibility of such damage. 341.1Sthorpej */ 351.1Sthorpej 361.1Sthorpej/* 371.1Sthorpej * XXX open for writing (for user programs to mmap, and write contents) 381.1Sthorpej */ 391.1Sthorpej 401.1Sthorpej#include <sys/param.h> 411.1Sthorpej#include <sys/device.h> 421.1Sthorpej#include <sys/systm.h> 431.1Sthorpej#include <sys/conf.h> 441.1Sthorpej#include <sys/fcntl.h> 451.1Sthorpej 461.1Sthorpej#include <uvm/uvm_extern.h> 471.1Sthorpej 481.1Sthorpej#include <machine/bus.h> 491.1Sthorpej#include <dev/ofw/openfirm.h> 501.1Sthorpej 511.1Sthorpejstruct ofrom_softc { 521.1Sthorpej struct device sc_dev; 531.1Sthorpej int enabled; 541.1Sthorpej vm_offset_t base; 551.1Sthorpej vm_size_t size; 561.1Sthorpej}; 571.1Sthorpej 581.1Sthorpejint ofromprobe __P((struct device *, struct cfdata *, void *)); 591.1Sthorpejvoid ofromattach __P((struct device *, struct device *, void *)); 601.1Sthorpej 611.1Sthorpejstruct cfattach ofrom_ca = { 621.1Sthorpej sizeof(struct ofrom_softc), ofromprobe, ofromattach 631.1Sthorpej}; 641.1Sthorpej 651.1Sthorpejextern struct cfdriver ofrom_cd; 661.1Sthorpej 671.5Sgehennadev_type_open(ofromopen); 681.5Sgehennadev_type_read(ofromrw); 691.5Sgehennadev_type_mmap(ofrommmap); 701.5Sgehenna 711.5Sgehennaconst struct cdevsw ofrom_cdevsw = { 721.5Sgehenna ofromopen, nullclose, ofromrw, ofromrw, noioctl, 731.5Sgehenna nostop, notty, nopoll, ofrommmap, 741.5Sgehenna}; 751.1Sthorpej 761.1Sthorpejint 771.1Sthorpejofromprobe(parent, cf, aux) 781.1Sthorpej struct device *parent; 791.1Sthorpej struct cfdata *cf; 801.1Sthorpej void *aux; 811.1Sthorpej{ 821.1Sthorpej struct ofbus_attach_args *oba = aux; 831.4Syamt static const char *const compatible_strings[] = { "rom", NULL }; 841.1Sthorpej 851.1Sthorpej return (of_compatible(oba->oba_phandle, compatible_strings) == -1) ? 861.1Sthorpej 0 : 5; 871.1Sthorpej} 881.1Sthorpej 891.1Sthorpej 901.1Sthorpejvoid 911.1Sthorpejofromattach(parent, self, aux) 921.1Sthorpej struct device *parent, *self; 931.1Sthorpej void *aux; 941.1Sthorpej{ 951.1Sthorpej struct ofrom_softc *sc = (struct ofrom_softc *)self; 961.1Sthorpej struct ofbus_attach_args *oba = aux; 971.1Sthorpej char regbuf[8]; 981.1Sthorpej 991.1Sthorpej if (OF_getproplen(oba->oba_phandle, "reg") != 8) { 1001.1Sthorpej printf(": invalid reg property\n"); 1011.1Sthorpej return; 1021.1Sthorpej } 1031.1Sthorpej if (OF_getprop(oba->oba_phandle, "reg", regbuf, sizeof regbuf) != 8) { 1041.1Sthorpej printf(": couldn't read reg property\n"); 1051.1Sthorpej return; 1061.1Sthorpej } 1071.1Sthorpej sc->base = of_decode_int(®buf[0]); 1081.1Sthorpej sc->size = of_decode_int(®buf[4]); 1091.1Sthorpej sc->enabled = 1; 1101.1Sthorpej 1111.1Sthorpej printf(": %#lx-%#lx\n", sc->base, sc->base + sc->size - 1); 1121.1Sthorpej} 1131.1Sthorpej 1141.1Sthorpejint 1151.1Sthorpejofromopen(dev, oflags, devtype, p) 1161.1Sthorpej dev_t dev; 1171.1Sthorpej int oflags, devtype; 1181.1Sthorpej struct proc *p; 1191.1Sthorpej{ 1201.1Sthorpej struct ofrom_softc *sc; 1211.1Sthorpej int unit = minor(dev); 1221.1Sthorpej 1231.1Sthorpej if (unit >= ofrom_cd.cd_ndevs) 1241.1Sthorpej return (ENXIO); 1251.1Sthorpej sc = ofrom_cd.cd_devs[unit]; 1261.1Sthorpej if (!sc || !sc->enabled) 1271.1Sthorpej return (ENXIO); 1281.1Sthorpej 1291.1Sthorpej if (oflags & FWRITE) 1301.1Sthorpej return (EINVAL); 1311.1Sthorpej 1321.1Sthorpej return (0); 1331.1Sthorpej} 1341.1Sthorpej 1351.1Sthorpejint 1361.1Sthorpejofromrw(dev, uio, flags) 1371.1Sthorpej dev_t dev; 1381.1Sthorpej struct uio *uio; 1391.1Sthorpej int flags; 1401.1Sthorpej{ 1411.1Sthorpej struct ofrom_softc *sc; 1421.1Sthorpej int c, error = 0, unit = minor(dev); 1431.1Sthorpej struct iovec *iov; 1441.1Sthorpej vm_offset_t o, v; 1451.1Sthorpej extern int physlock; 1461.1Sthorpej extern char *memhook; 1471.1Sthorpej 1481.1Sthorpej if (unit >= ofrom_cd.cd_ndevs) 1491.1Sthorpej return (ENXIO); /* XXX PANIC */ 1501.1Sthorpej sc = ofrom_cd.cd_devs[unit]; 1511.1Sthorpej if (!sc || !sc->enabled) 1521.1Sthorpej return (ENXIO); /* XXX PANIC */ 1531.1Sthorpej 1541.1Sthorpej /* lock against other uses of shared vmmap */ 1551.1Sthorpej while (physlock > 0) { 1561.1Sthorpej physlock++; 1571.1Sthorpej error = tsleep((caddr_t)&physlock, PZERO | PCATCH, "ofromrw", 1581.1Sthorpej 0); 1591.1Sthorpej if (error) 1601.1Sthorpej return (error); 1611.1Sthorpej } 1621.1Sthorpej physlock = 1; 1631.1Sthorpej 1641.1Sthorpej while (uio->uio_resid > 0 && error == 0) { 1651.1Sthorpej iov = uio->uio_iov; 1661.1Sthorpej if (iov->iov_len == 0) { 1671.1Sthorpej uio->uio_iov++; 1681.1Sthorpej uio->uio_iovcnt--; 1691.1Sthorpej if (uio->uio_iovcnt < 0) 1701.1Sthorpej panic("ofromrw"); 1711.1Sthorpej continue; 1721.1Sthorpej } 1731.1Sthorpej 1741.1Sthorpej /* 1751.1Sthorpej * Since everything is page aligned and no more 1761.1Sthorpej * than the rest of a page is done at once, we 1771.1Sthorpej * can just check that the offset isn't too big. 1781.1Sthorpej */ 1791.1Sthorpej if (uio->uio_offset >= sc->size) 1801.1Sthorpej break; 1811.1Sthorpej 1821.1Sthorpej v = sc->base + uio->uio_offset; 1831.1Sthorpej pmap_enter(pmap_kernel(), (vm_offset_t)memhook, 1841.1Sthorpej trunc_page(v), uio->uio_rw == UIO_READ ? 1851.1Sthorpej VM_PROT_READ : VM_PROT_WRITE, PMAP_WIRED); 1861.1Sthorpej pmap_update(pmap_kernel()); 1871.1Sthorpej o = uio->uio_offset & PGOFSET; 1881.1Sthorpej c = min(uio->uio_resid, (int)(NBPG - o)); 1891.1Sthorpej error = uiomove((caddr_t)memhook + o, c, uio); 1901.1Sthorpej pmap_remove(pmap_kernel(), (vm_offset_t)memhook, 1911.1Sthorpej (vm_offset_t)memhook + NBPG); 1921.1Sthorpej pmap_update(pmap_kernel()); 1931.1Sthorpej } 1941.1Sthorpej 1951.1Sthorpej if (physlock > 1) 1961.1Sthorpej wakeup((caddr_t)&physlock); 1971.1Sthorpej physlock = 0; 1981.1Sthorpej 1991.1Sthorpej return (error); 2001.1Sthorpej} 2011.1Sthorpej 2021.1Sthorpejpaddr_t 2031.1Sthorpejofrommmap(dev, off, prot) 2041.1Sthorpej dev_t dev; 2051.1Sthorpej off_t off; 2061.1Sthorpej int prot; 2071.1Sthorpej{ 2081.1Sthorpej struct ofrom_softc *sc; 2091.1Sthorpej int unit = minor(dev); 2101.1Sthorpej 2111.1Sthorpej if (unit >= ofrom_cd.cd_ndevs) 2121.1Sthorpej return (-1); /* XXX PANIC */ 2131.1Sthorpej sc = ofrom_cd.cd_devs[unit]; 2141.1Sthorpej if (!sc || !sc->enabled) 2151.1Sthorpej return (-1); /* XXX PANIC */ 2161.1Sthorpej 2171.1Sthorpej if ((u_int)off >= sc->size) 2181.1Sthorpej return (-1); 2191.1Sthorpej 2201.3Sthorpej return arm_btop(sc->base + off); 2211.1Sthorpej} 222