11.29Sthorpej/* $NetBSD: ofrom.c,v 1.29 2021/01/27 03:10:21 thorpej 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.11Slukem 401.11Slukem#include <sys/cdefs.h> 411.29Sthorpej__KERNEL_RCSID(0, "$NetBSD: ofrom.c,v 1.29 2021/01/27 03:10:21 thorpej Exp $"); 421.1Sthorpej 431.1Sthorpej#include <sys/param.h> 441.1Sthorpej#include <sys/device.h> 451.1Sthorpej#include <sys/systm.h> 461.1Sthorpej#include <sys/conf.h> 471.1Sthorpej#include <sys/fcntl.h> 481.22Sdyoung#include <sys/bus.h> 491.1Sthorpej 501.1Sthorpej#include <uvm/uvm_extern.h> 511.1Sthorpej 521.1Sthorpej#include <dev/ofw/openfirm.h> 531.1Sthorpej 541.1Sthorpejstruct ofrom_softc { 551.1Sthorpej int enabled; 561.12Stsutsui paddr_t base; 571.12Stsutsui paddr_t size; 581.1Sthorpej}; 591.1Sthorpej 601.23Smrgint ofromprobe(device_t, cfdata_t, void *); 611.23Smrgvoid ofromattach(device_t, device_t, void *); 621.1Sthorpej 631.23SmrgCFATTACH_DECL_NEW(ofrom, sizeof(struct ofrom_softc), 641.8Sthorpej ofromprobe, ofromattach, NULL, NULL); 651.1Sthorpej 661.1Sthorpejextern struct cfdriver ofrom_cd; 671.1Sthorpej 681.5Sgehennadev_type_open(ofromopen); 691.5Sgehennadev_type_read(ofromrw); 701.5Sgehennadev_type_mmap(ofrommmap); 711.5Sgehenna 721.5Sgehennaconst struct cdevsw ofrom_cdevsw = { 731.25Sdholland .d_open = ofromopen, 741.25Sdholland .d_close = nullclose, 751.25Sdholland .d_read = ofromrw, 761.25Sdholland .d_write = ofromrw, 771.25Sdholland .d_ioctl = noioctl, 781.25Sdholland .d_stop = nostop, 791.25Sdholland .d_tty = notty, 801.25Sdholland .d_poll = nopoll, 811.25Sdholland .d_mmap = ofrommmap, 821.25Sdholland .d_kqfilter = nokqfilter, 831.26Sdholland .d_discard = nodiscard, 841.25Sdholland .d_flag = 0 851.5Sgehenna}; 861.1Sthorpej 871.29Sthorpejstatic const struct device_compatible_entry compat_data[] = { 881.29Sthorpej { .compat = "rom" }, 891.29Sthorpej DEVICE_COMPAT_EOL 901.29Sthorpej}; 911.29Sthorpej 921.1Sthorpejint 931.23Smrgofromprobe(device_t parent, cfdata_t cf, void *aux) 941.1Sthorpej{ 951.1Sthorpej struct ofbus_attach_args *oba = aux; 961.1Sthorpej 971.29Sthorpej return of_compatible_match(oba->oba_phandle, compat_data) * 5; 981.1Sthorpej} 991.1Sthorpej 1001.1Sthorpej 1011.1Sthorpejvoid 1021.23Smrgofromattach(device_t parent, device_t self, void *aux) 1031.1Sthorpej{ 1041.23Smrg struct ofrom_softc *sc = device_private(self); 1051.1Sthorpej struct ofbus_attach_args *oba = aux; 1061.1Sthorpej char regbuf[8]; 1071.1Sthorpej 1081.1Sthorpej if (OF_getproplen(oba->oba_phandle, "reg") != 8) { 1091.1Sthorpej printf(": invalid reg property\n"); 1101.1Sthorpej return; 1111.1Sthorpej } 1121.1Sthorpej if (OF_getprop(oba->oba_phandle, "reg", regbuf, sizeof regbuf) != 8) { 1131.1Sthorpej printf(": couldn't read reg property\n"); 1141.1Sthorpej return; 1151.1Sthorpej } 1161.1Sthorpej sc->base = of_decode_int(®buf[0]); 1171.1Sthorpej sc->size = of_decode_int(®buf[4]); 1181.1Sthorpej sc->enabled = 1; 1191.1Sthorpej 1201.1Sthorpej printf(": %#lx-%#lx\n", sc->base, sc->base + sc->size - 1); 1211.1Sthorpej} 1221.1Sthorpej 1231.1Sthorpejint 1241.16Sceggerofromopen(dev_t dev, int oflags, int devtype, struct lwp *l) 1251.1Sthorpej{ 1261.1Sthorpej struct ofrom_softc *sc; 1271.1Sthorpej 1281.16Scegger sc = device_lookup_private(&ofrom_cd, minor(dev)); 1291.1Sthorpej if (!sc || !sc->enabled) 1301.1Sthorpej return (ENXIO); 1311.1Sthorpej 1321.1Sthorpej if (oflags & FWRITE) 1331.1Sthorpej return (EINVAL); 1341.1Sthorpej 1351.1Sthorpej return (0); 1361.1Sthorpej} 1371.1Sthorpej 1381.1Sthorpejint 1391.16Sceggerofromrw(dev_t dev, struct uio *uio, int flags) 1401.1Sthorpej{ 1411.24Smatt pmap_t kpm = pmap_kernel(); 1421.1Sthorpej struct ofrom_softc *sc; 1431.16Scegger int c, error = 0; 1441.1Sthorpej struct iovec *iov; 1451.12Stsutsui paddr_t v; 1461.12Stsutsui psize_t o; 1471.17She extern kmutex_t memlock; 1481.1Sthorpej extern char *memhook; 1491.1Sthorpej 1501.16Scegger sc = device_lookup_private(&ofrom_cd, minor(dev)); 1511.1Sthorpej if (!sc || !sc->enabled) 1521.1Sthorpej return (ENXIO); /* XXX PANIC */ 1531.1Sthorpej 1541.17She mutex_enter(&memlock); 1551.1Sthorpej while (uio->uio_resid > 0 && error == 0) { 1561.1Sthorpej iov = uio->uio_iov; 1571.1Sthorpej if (iov->iov_len == 0) { 1581.1Sthorpej uio->uio_iov++; 1591.1Sthorpej uio->uio_iovcnt--; 1601.1Sthorpej if (uio->uio_iovcnt < 0) 1611.1Sthorpej panic("ofromrw"); 1621.1Sthorpej continue; 1631.1Sthorpej } 1641.1Sthorpej 1651.1Sthorpej /* 1661.1Sthorpej * Since everything is page aligned and no more 1671.1Sthorpej * than the rest of a page is done at once, we 1681.1Sthorpej * can just check that the offset isn't too big. 1691.1Sthorpej */ 1701.1Sthorpej if (uio->uio_offset >= sc->size) 1711.1Sthorpej break; 1721.1Sthorpej 1731.1Sthorpej v = sc->base + uio->uio_offset; 1741.24Smatt pmap_kenter_pa((vaddr_t)memhook, trunc_page(v), 1751.24Smatt uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE, 1761.24Smatt 0); 1771.24Smatt pmap_update(kpm); 1781.1Sthorpej o = uio->uio_offset & PGOFSET; 1791.28Sriastrad c = uimin(uio->uio_resid, (int)(PAGE_SIZE - o)); 1801.15Schristos error = uiomove((char *)memhook + o, c, uio); 1811.24Smatt pmap_kremove((vaddr_t)memhook, (vaddr_t)memhook + PAGE_SIZE); 1821.24Smatt pmap_update(kpm); 1831.1Sthorpej } 1841.17She mutex_exit(&memlock); 1851.1Sthorpej 1861.1Sthorpej return (error); 1871.1Sthorpej} 1881.1Sthorpej 1891.1Sthorpejpaddr_t 1901.16Sceggerofrommmap(dev_t dev, off_t off, int prot) 1911.1Sthorpej{ 1921.1Sthorpej struct ofrom_softc *sc; 1931.1Sthorpej 1941.16Scegger sc = device_lookup_private(&ofrom_cd, minor(dev)); 1951.1Sthorpej if (!sc || !sc->enabled) 1961.1Sthorpej return (-1); /* XXX PANIC */ 1971.1Sthorpej 1981.1Sthorpej if ((u_int)off >= sc->size) 1991.1Sthorpej return (-1); 2001.1Sthorpej 2011.3Sthorpej return arm_btop(sc->base + off); 2021.1Sthorpej} 203