1 1.23 thorpej /* $NetBSD: nvram_pnpbus.c,v 1.23 2025/09/07 21:27:55 thorpej Exp $ */ 2 1.1 garbled 3 1.1 garbled /*- 4 1.1 garbled * Copyright (c) 2006 The NetBSD Foundation, Inc. 5 1.1 garbled * All rights reserved. 6 1.1 garbled * 7 1.1 garbled * This code is derived from software contributed to The NetBSD Foundation 8 1.1 garbled * by Tim Rightnour 9 1.1 garbled * 10 1.1 garbled * Redistribution and use in source and binary forms, with or without 11 1.1 garbled * modification, are permitted provided that the following conditions 12 1.1 garbled * are met: 13 1.1 garbled * 1. Redistributions of source code must retain the above copyright 14 1.1 garbled * notice, this list of conditions and the following disclaimer. 15 1.1 garbled * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 garbled * notice, this list of conditions and the following disclaimer in the 17 1.1 garbled * documentation and/or other materials provided with the distribution. 18 1.1 garbled * 19 1.1 garbled * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 garbled * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 garbled * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 garbled * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 garbled * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 garbled * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 garbled * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 garbled * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 garbled * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 garbled * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 garbled * POSSIBILITY OF SUCH DAMAGE. 30 1.1 garbled */ 31 1.1 garbled 32 1.1 garbled #include <sys/cdefs.h> 33 1.23 thorpej __KERNEL_RCSID(0, "$NetBSD: nvram_pnpbus.c,v 1.23 2025/09/07 21:27:55 thorpej Exp $"); 34 1.1 garbled 35 1.1 garbled #include <sys/types.h> 36 1.1 garbled #include <sys/param.h> 37 1.1 garbled #include <sys/systm.h> 38 1.1 garbled #include <sys/ioctl.h> 39 1.1 garbled #include <sys/conf.h> 40 1.1 garbled #include <sys/kthread.h> 41 1.1 garbled #include <sys/device.h> 42 1.1 garbled #include <sys/malloc.h> 43 1.10 ad #include <sys/bus.h> 44 1.10 ad #include <sys/intr.h> 45 1.1 garbled 46 1.1 garbled #include <machine/isa_machdep.h> 47 1.3 garbled /* clock stuff for motorolla machines */ 48 1.3 garbled #include <dev/clock_subr.h> 49 1.3 garbled #include <dev/ic/mk48txxreg.h> 50 1.3 garbled 51 1.8 garbled #include <uvm/uvm_extern.h> 52 1.8 garbled 53 1.8 garbled #include <machine/residual.h> 54 1.1 garbled #include <machine/nvram.h> 55 1.1 garbled 56 1.1 garbled #include <prep/pnpbus/pnpbusvar.h> 57 1.1 garbled 58 1.1 garbled #include "opt_nvram.h" 59 1.1 garbled 60 1.1 garbled static char *nvramData; 61 1.1 garbled static NVRAM_MAP *nvram; 62 1.1 garbled static char *nvramGEAp; /* pointer to the GE area */ 63 1.1 garbled static char *nvramCAp; /* pointer to the Config area */ 64 1.1 garbled static char *nvramOSAp; /* pointer to the OSArea */ 65 1.1 garbled 66 1.3 garbled int prep_clock_mk48txx; 67 1.3 garbled 68 1.1 garbled extern char bootpath[256]; 69 1.8 garbled extern RESIDUAL resdata; 70 1.1 garbled 71 1.1 garbled #define NVRAM_STD_DEV 0 72 1.1 garbled 73 1.15 matt static int nvram_pnpbus_probe(device_t, cfdata_t, void *); 74 1.15 matt static void nvram_pnpbus_attach(device_t, device_t, void *); 75 1.1 garbled uint8_t prep_nvram_read_val(int); 76 1.1 garbled char *prep_nvram_next_var(char *); 77 1.1 garbled char *prep_nvram_find_var(const char *); 78 1.1 garbled char *prep_nvram_get_var(const char *); 79 1.1 garbled int prep_nvram_get_var_len(const char *); 80 1.1 garbled int prep_nvram_count_vars(void); 81 1.1 garbled void prep_nvram_write_val(int, uint8_t); 82 1.3 garbled uint8_t mkclock_pnpbus_nvrd(struct mk48txx_softc *, int); 83 1.3 garbled void mkclock_pnpbus_nvwr(struct mk48txx_softc *, int, uint8_t); 84 1.1 garbled 85 1.17 chs CFATTACH_DECL_NEW(nvram_pnpbus, sizeof(struct nvram_pnpbus_softc), 86 1.1 garbled nvram_pnpbus_probe, nvram_pnpbus_attach, NULL, NULL); 87 1.1 garbled 88 1.1 garbled dev_type_open(prep_nvramopen); 89 1.1 garbled dev_type_ioctl(prep_nvramioctl); 90 1.1 garbled dev_type_close(prep_nvramclose); 91 1.8 garbled dev_type_read(prep_nvramread); 92 1.1 garbled 93 1.6 garbled const struct cdevsw nvram_cdevsw = { 94 1.19 dholland .d_open = prep_nvramopen, 95 1.19 dholland .d_close = prep_nvramclose, 96 1.19 dholland .d_read = prep_nvramread, 97 1.19 dholland .d_write = nowrite, 98 1.19 dholland .d_ioctl = prep_nvramioctl, 99 1.19 dholland .d_stop = nostop, 100 1.19 dholland .d_tty = notty, 101 1.19 dholland .d_poll = nopoll, 102 1.19 dholland .d_mmap = nommap, 103 1.19 dholland .d_kqfilter = nokqfilter, 104 1.20 dholland .d_discard = nodiscard, 105 1.19 dholland .d_flag = D_OTHER, 106 1.1 garbled }; 107 1.1 garbled 108 1.1 garbled extern struct cfdriver nvram_cd; 109 1.1 garbled 110 1.1 garbled static int 111 1.15 matt nvram_pnpbus_probe(device_t parent, cfdata_t match, void *aux) 112 1.1 garbled { 113 1.1 garbled struct pnpbus_dev_attach_args *pna = aux; 114 1.1 garbled int ret = 0; 115 1.1 garbled 116 1.1 garbled if (strcmp(pna->pna_devid, "IBM0008") == 0) 117 1.1 garbled ret = 1; 118 1.1 garbled 119 1.1 garbled if (ret) 120 1.1 garbled pnpbus_scan(pna, pna->pna_ppc_dev); 121 1.1 garbled 122 1.1 garbled return ret; 123 1.1 garbled } 124 1.1 garbled 125 1.1 garbled static void 126 1.15 matt nvram_pnpbus_attach(device_t parent, device_t self, void *aux) 127 1.1 garbled { 128 1.15 matt struct nvram_pnpbus_softc *sc = device_private(self); 129 1.1 garbled struct pnpbus_dev_attach_args *pna = aux; 130 1.1 garbled int as_iobase, as_len, data_iobase, data_len, i, nvlen, cur; 131 1.1 garbled uint8_t *p; 132 1.1 garbled HEADER prep_nvram_header; 133 1.1 garbled 134 1.23 thorpej sc->sc_mksc.sc_mk48txx.sc_dev = self; 135 1.1 garbled sc->sc_iot = pna->pna_iot; 136 1.1 garbled 137 1.1 garbled pnpbus_getioport(&pna->pna_res, 0, &as_iobase, &as_len); 138 1.1 garbled pnpbus_getioport(&pna->pna_res, 1, &data_iobase, &data_len); 139 1.1 garbled 140 1.1 garbled if (pnpbus_io_map(&pna->pna_res, 0, &sc->sc_as, &sc->sc_ash) || 141 1.1 garbled pnpbus_io_map(&pna->pna_res, 1, &sc->sc_data, &sc->sc_datah)) { 142 1.3 garbled aprint_error("nvram: couldn't map registers\n"); 143 1.2 garbled return; 144 1.1 garbled } 145 1.1 garbled 146 1.1 garbled /* Initialize the nvram header */ 147 1.1 garbled p = (uint8_t *) &prep_nvram_header; 148 1.1 garbled for (i = 0; i < sizeof(HEADER); i++) 149 1.1 garbled *p++ = prep_nvram_read_val(i); 150 1.1 garbled 151 1.1 garbled /* 152 1.1 garbled * now that we have the header, we know how big the NVRAM part on 153 1.1 garbled * this machine really is. Malloc space to save a copy. 154 1.1 garbled */ 155 1.1 garbled 156 1.1 garbled nvlen = 1024 * prep_nvram_header.Size; 157 1.22 chs nvramData = malloc(nvlen, M_DEVBUF, M_WAITOK); 158 1.1 garbled p = (uint8_t *) nvramData; 159 1.1 garbled 160 1.1 garbled /* 161 1.1 garbled * now read the whole nvram in, one chunk at a time, marking down 162 1.1 garbled * the main start points as we go. 163 1.1 garbled */ 164 1.1 garbled for (i = 0; i < sizeof(HEADER) && i < nvlen; i++) 165 1.1 garbled *p++ = prep_nvram_read_val(i); 166 1.1 garbled nvramGEAp = p; 167 1.1 garbled cur = i; 168 1.1 garbled for (; i < cur + prep_nvram_header.GELength && i < nvlen; i++) 169 1.1 garbled *p++ = prep_nvram_read_val(i); 170 1.1 garbled nvramOSAp = p; 171 1.1 garbled cur = i; 172 1.1 garbled for (; i < cur + prep_nvram_header.OSAreaLength && i < nvlen; i++) 173 1.1 garbled *p++ = prep_nvram_read_val(i); 174 1.1 garbled nvramCAp = p; 175 1.1 garbled cur = i; 176 1.1 garbled for (; i < cur + prep_nvram_header.ConfigLength && i < nvlen; i++) 177 1.1 garbled *p++ = prep_nvram_read_val(i); 178 1.1 garbled 179 1.1 garbled /* we should be done here. umm.. yay? */ 180 1.1 garbled nvram = (NVRAM_MAP *)&nvramData[0]; 181 1.3 garbled aprint_normal("\n"); 182 1.3 garbled aprint_verbose("%s: Read %d bytes from nvram of size %d\n", 183 1.3 garbled device_xname(self), i, nvlen); 184 1.1 garbled 185 1.1 garbled #if defined(NVRAM_DUMP) 186 1.1 garbled printf("Boot device: %s\n", prep_nvram_get_var("fw-boot-device")); 187 1.1 garbled printf("Dumping nvram\n"); 188 1.1 garbled for (cur=0; cur < i; cur++) { 189 1.1 garbled printf("%c", nvramData[cur]); 190 1.1 garbled if (cur % 70 == 0) 191 1.1 garbled printf("\n"); 192 1.1 garbled } 193 1.1 garbled #endif 194 1.1 garbled strncpy(bootpath, prep_nvram_get_var("fw-boot-device"), 256); 195 1.3 garbled 196 1.3 garbled if (prep_clock_mk48txx == 0) 197 1.3 garbled return; 198 1.23 thorpej 199 1.3 garbled /* otherwise, we have a motorolla clock chip. Set it up. */ 200 1.23 thorpej sc->sc_mksc.sc_mk48txx.sc_model = "mk48t18"; 201 1.23 thorpej sc->sc_mksc.sc_mk48txx.sc_year0 = 1900; 202 1.23 thorpej sc->sc_mksc.sc_mk48txx.sc_nvrd = mkclock_pnpbus_nvrd; 203 1.23 thorpej sc->sc_mksc.sc_mk48txx.sc_nvwr = mkclock_pnpbus_nvwr; 204 1.3 garbled /* copy down the bus space tags */ 205 1.23 thorpej sc->sc_mksc.sc_mk48txx.sc_bst = sc->sc_as; 206 1.23 thorpej sc->sc_mksc.sc_mk48txx.sc_bsh = sc->sc_ash; 207 1.3 garbled sc->sc_mksc.sc_data = sc->sc_data; 208 1.3 garbled sc->sc_mksc.sc_datah = sc->sc_datah; 209 1.3 garbled 210 1.3 garbled aprint_normal("%s: attaching clock", device_xname(self)); 211 1.23 thorpej mk48txx_attach((struct mk48txx_softc *)&sc->sc_mksc.sc_mk48txx); 212 1.4 garbled aprint_normal("\n"); 213 1.1 garbled } 214 1.1 garbled 215 1.1 garbled /* 216 1.1 garbled * This function should be called at a high spl only, as it interfaces with 217 1.1 garbled * real hardware. 218 1.1 garbled */ 219 1.1 garbled 220 1.1 garbled uint8_t 221 1.1 garbled prep_nvram_read_val(int addr) 222 1.1 garbled { 223 1.1 garbled struct nvram_pnpbus_softc *sc; 224 1.1 garbled 225 1.13 matt sc = device_lookup_private(&nvram_cd, NVRAM_STD_DEV); 226 1.13 matt if (sc == NULL) 227 1.13 matt return 0; 228 1.1 garbled 229 1.1 garbled /* tell the NVRAM what we want */ 230 1.1 garbled bus_space_write_1(sc->sc_as, sc->sc_ash, 0, addr); 231 1.1 garbled bus_space_write_1(sc->sc_as, sc->sc_ash, 1, addr>>8); 232 1.1 garbled 233 1.1 garbled return bus_space_read_1(sc->sc_data, sc->sc_datah, 0); 234 1.1 garbled } 235 1.1 garbled 236 1.1 garbled /* 237 1.1 garbled * This function should be called at a high spl only, as it interfaces with 238 1.1 garbled * real hardware. 239 1.1 garbled */ 240 1.1 garbled 241 1.1 garbled void 242 1.1 garbled prep_nvram_write_val(int addr, uint8_t val) 243 1.1 garbled { 244 1.1 garbled struct nvram_pnpbus_softc *sc; 245 1.1 garbled 246 1.13 matt sc = device_lookup_private(&nvram_cd, NVRAM_STD_DEV); 247 1.13 matt if (sc == NULL) 248 1.13 matt return; 249 1.1 garbled 250 1.1 garbled /* tell the NVRAM what we want */ 251 1.1 garbled bus_space_write_1(sc->sc_as, sc->sc_ash, 0, addr); 252 1.1 garbled bus_space_write_1(sc->sc_as, sc->sc_ash, 1, addr>>8); 253 1.1 garbled 254 1.1 garbled bus_space_write_1(sc->sc_data, sc->sc_datah, 0, val); 255 1.1 garbled } 256 1.1 garbled 257 1.1 garbled /* the rest of these should all be called with the lock held */ 258 1.1 garbled 259 1.1 garbled char * 260 1.1 garbled prep_nvram_next_var(char *name) 261 1.1 garbled { 262 1.1 garbled char *cp; 263 1.1 garbled 264 1.6 garbled if (name == NULL) 265 1.6 garbled return NULL; 266 1.6 garbled 267 1.1 garbled cp = name; 268 1.1 garbled /* skip forward to the first null char */ 269 1.1 garbled while ((cp - nvramGEAp) < nvram->Header.GELength && (*cp != '\0')) 270 1.1 garbled cp++; 271 1.1 garbled /* skip nulls */ 272 1.1 garbled while ((cp - nvramGEAp) < nvram->Header.GELength && (*cp == '\0')) 273 1.1 garbled cp++; 274 1.1 garbled if ((cp - nvramGEAp) < nvram->Header.GELength) 275 1.1 garbled return cp; 276 1.1 garbled else 277 1.1 garbled return NULL; 278 1.1 garbled } 279 1.1 garbled 280 1.1 garbled char * 281 1.1 garbled prep_nvram_find_var(const char *name) 282 1.1 garbled { 283 1.1 garbled char *cp = nvramGEAp; 284 1.1 garbled size_t len; 285 1.1 garbled 286 1.1 garbled len = strlen(name); 287 1.1 garbled while (cp != NULL) { 288 1.1 garbled if ((strncmp(name, cp, len) == 0) && (cp[len] == '=')) 289 1.1 garbled return cp; 290 1.1 garbled cp = prep_nvram_next_var(cp); 291 1.1 garbled } 292 1.1 garbled return NULL; 293 1.1 garbled } 294 1.1 garbled 295 1.1 garbled char * 296 1.1 garbled prep_nvram_get_var(const char *name) 297 1.1 garbled { 298 1.1 garbled char *cp = nvramGEAp; 299 1.1 garbled size_t len; 300 1.1 garbled 301 1.6 garbled if (name == NULL) 302 1.6 garbled return NULL; 303 1.1 garbled len = strlen(name); 304 1.1 garbled while (cp != NULL) { 305 1.1 garbled if ((strncmp(name, cp, len) == 0) && (cp[len] == '=')) 306 1.1 garbled return cp+len+1; 307 1.1 garbled cp = prep_nvram_next_var(cp); 308 1.1 garbled } 309 1.1 garbled return NULL; 310 1.1 garbled } 311 1.1 garbled 312 1.1 garbled int 313 1.1 garbled prep_nvram_get_var_len(const char *name) 314 1.1 garbled { 315 1.1 garbled char *cp = nvramGEAp; 316 1.1 garbled char *ep; 317 1.1 garbled size_t len; 318 1.1 garbled 319 1.6 garbled if (name == NULL) 320 1.6 garbled return -1; 321 1.6 garbled 322 1.1 garbled len = strlen(name); 323 1.1 garbled while (cp != NULL) { 324 1.1 garbled if ((strncmp(name, cp, len) == 0) && (cp[len] == '=')) 325 1.1 garbled goto out; 326 1.1 garbled cp = prep_nvram_next_var(cp); 327 1.1 garbled } 328 1.1 garbled return -1; 329 1.1 garbled 330 1.1 garbled out: 331 1.1 garbled ep = cp; 332 1.1 garbled while (ep != NULL && *ep != '\0') 333 1.1 garbled ep++; 334 1.1 garbled return ep-cp; 335 1.1 garbled } 336 1.1 garbled 337 1.1 garbled int 338 1.1 garbled prep_nvram_count_vars(void) 339 1.1 garbled { 340 1.1 garbled char *cp = nvramGEAp; 341 1.1 garbled int i=0; 342 1.1 garbled 343 1.1 garbled while (cp != NULL) { 344 1.1 garbled i++; 345 1.1 garbled cp = prep_nvram_next_var(cp); 346 1.1 garbled } 347 1.1 garbled return i; 348 1.1 garbled } 349 1.1 garbled 350 1.6 garbled static int 351 1.6 garbled nvramgetstr(int len, char *user, char **cpp) 352 1.6 garbled { 353 1.6 garbled int error; 354 1.6 garbled char *cp; 355 1.6 garbled 356 1.6 garbled /* Reject obvious bogus requests */ 357 1.6 garbled if ((u_int)len > (8 * 1024) - 1) 358 1.6 garbled return ENAMETOOLONG; 359 1.6 garbled 360 1.6 garbled *cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK); 361 1.6 garbled error = copyin(user, cp, len); 362 1.6 garbled cp[len] = '\0'; 363 1.6 garbled return error; 364 1.6 garbled } 365 1.6 garbled 366 1.1 garbled int 367 1.7 christos prep_nvramioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 368 1.1 garbled { 369 1.1 garbled int len, error; 370 1.1 garbled struct pnviocdesc *pnv; 371 1.6 garbled char *np, *cp, *name; 372 1.1 garbled 373 1.1 garbled pnv = (struct pnviocdesc *)data; 374 1.1 garbled error = 0; 375 1.6 garbled cp = name = NULL; 376 1.1 garbled 377 1.1 garbled switch (cmd) { 378 1.1 garbled case PNVIOCGET: 379 1.1 garbled if (pnv->pnv_name == NULL) 380 1.1 garbled return EINVAL; 381 1.1 garbled 382 1.6 garbled error = nvramgetstr(pnv->pnv_namelen, pnv->pnv_name, &name); 383 1.6 garbled np = prep_nvram_get_var(name); 384 1.1 garbled if (np == NULL) 385 1.1 garbled return EINVAL; 386 1.6 garbled len = prep_nvram_get_var_len(name); 387 1.1 garbled 388 1.1 garbled if (len > pnv->pnv_buflen) { 389 1.1 garbled error = ENOMEM; 390 1.1 garbled break; 391 1.1 garbled } 392 1.1 garbled if (len <= 0) 393 1.1 garbled break; 394 1.1 garbled error = copyout(np, pnv->pnv_buf, len); 395 1.1 garbled pnv->pnv_buflen = len; 396 1.1 garbled break; 397 1.1 garbled 398 1.1 garbled case PNVIOCGETNEXTNAME: 399 1.1 garbled /* if the first one is null, we give them the first name */ 400 1.1 garbled if (pnv->pnv_name == NULL) { 401 1.6 garbled cp = nvramGEAp; 402 1.1 garbled } else { 403 1.6 garbled error = nvramgetstr(pnv->pnv_namelen, pnv->pnv_name, 404 1.6 garbled &name); 405 1.6 garbled if (!error) { 406 1.6 garbled np = prep_nvram_find_var(name); 407 1.6 garbled cp = prep_nvram_next_var(np); 408 1.6 garbled } 409 1.1 garbled } 410 1.6 garbled if (cp == NULL) 411 1.6 garbled error = EINVAL; 412 1.6 garbled if (error) 413 1.6 garbled break; 414 1.6 garbled 415 1.1 garbled np = cp; 416 1.1 garbled while (*np != '=') 417 1.1 garbled np++; 418 1.1 garbled len = np-cp; 419 1.1 garbled if (len > pnv->pnv_buflen) { 420 1.1 garbled error = ENOMEM; 421 1.1 garbled break; 422 1.1 garbled } 423 1.1 garbled error = copyout(cp, pnv->pnv_buf, len); 424 1.6 garbled if (error) 425 1.6 garbled break; 426 1.1 garbled pnv->pnv_buflen = len; 427 1.1 garbled break; 428 1.6 garbled 429 1.6 garbled case PNVIOCGETNUMGE: 430 1.6 garbled /* count the GE variables */ 431 1.6 garbled pnv->pnv_num = prep_nvram_count_vars(); 432 1.6 garbled break; 433 1.6 garbled case PNVIOCSET: 434 1.6 garbled /* this will require some real work. Not ready yet */ 435 1.6 garbled return ENOTSUP; 436 1.6 garbled 437 1.1 garbled default: 438 1.6 garbled return ENOTTY; 439 1.1 garbled } 440 1.6 garbled if (name) 441 1.6 garbled free(name, M_TEMP); 442 1.6 garbled return error; 443 1.1 garbled } 444 1.1 garbled 445 1.1 garbled int 446 1.8 garbled prep_nvramread(dev_t dev, struct uio *uio, int flags) 447 1.8 garbled { 448 1.8 garbled int size, resid, error; 449 1.8 garbled u_int c; 450 1.8 garbled char *rdata; 451 1.8 garbled 452 1.8 garbled error = 0; 453 1.8 garbled rdata = (char *)&resdata; 454 1.8 garbled 455 1.8 garbled if (uio->uio_rw == UIO_WRITE) { 456 1.8 garbled uio->uio_resid = 0; 457 1.8 garbled return 0; 458 1.8 garbled } 459 1.8 garbled 460 1.8 garbled switch (minor(dev)) { 461 1.8 garbled case DEV_NVRAM: 462 1.8 garbled size = nvram->Header.Size * 1024; 463 1.8 garbled break; 464 1.8 garbled case DEV_RESIDUAL: 465 1.8 garbled size = res->ResidualLength; 466 1.8 garbled break; 467 1.8 garbled default: 468 1.8 garbled return ENXIO; 469 1.8 garbled } 470 1.8 garbled resid = size; 471 1.8 garbled if (uio->uio_resid < resid) 472 1.8 garbled resid = uio->uio_resid; 473 1.8 garbled while (resid > 0 && error == 0 && uio->uio_offset < size) { 474 1.8 garbled switch (minor(dev)) { 475 1.8 garbled case DEV_NVRAM: 476 1.21 riastrad c = uimin(resid, PAGE_SIZE); 477 1.8 garbled error = uiomove(&nvramData[uio->uio_offset], c, uio); 478 1.8 garbled break; 479 1.8 garbled case DEV_RESIDUAL: 480 1.21 riastrad c = uimin(resid, PAGE_SIZE); 481 1.8 garbled error = uiomove(&rdata[uio->uio_offset], c, uio); 482 1.8 garbled break; 483 1.8 garbled default: 484 1.8 garbled return ENXIO; 485 1.8 garbled } 486 1.8 garbled } 487 1.8 garbled return error; 488 1.8 garbled } 489 1.8 garbled 490 1.8 garbled int 491 1.1 garbled prep_nvramopen(dev_t dev, int flags, int mode, struct lwp *l) 492 1.1 garbled { 493 1.1 garbled struct nvram_pnpbus_softc *sc; 494 1.1 garbled 495 1.12 matt sc = device_lookup_private(&nvram_cd, NVRAM_STD_DEV); 496 1.1 garbled if (sc == NULL) 497 1.1 garbled return ENODEV; 498 1.1 garbled 499 1.1 garbled if (sc->sc_open) 500 1.1 garbled return EBUSY; 501 1.1 garbled 502 1.1 garbled sc->sc_open = 1; 503 1.1 garbled 504 1.1 garbled return 0; 505 1.1 garbled } 506 1.1 garbled 507 1.1 garbled int 508 1.1 garbled prep_nvramclose(dev_t dev, int flags, int mode, struct lwp *l) 509 1.1 garbled { 510 1.1 garbled struct nvram_pnpbus_softc *sc; 511 1.1 garbled 512 1.12 matt sc = device_lookup_private(&nvram_cd, NVRAM_STD_DEV); 513 1.1 garbled if (sc == NULL) 514 1.1 garbled return ENODEV; 515 1.1 garbled sc->sc_open = 0; 516 1.1 garbled return 0; 517 1.1 garbled } 518 1.3 garbled 519 1.3 garbled /* Motorola mk48txx clock routines */ 520 1.3 garbled uint8_t 521 1.3 garbled mkclock_pnpbus_nvrd(struct mk48txx_softc *osc, int off) 522 1.3 garbled { 523 1.3 garbled struct prep_mk48txx_softc *sc = (struct prep_mk48txx_softc *)osc; 524 1.3 garbled uint8_t datum; 525 1.3 garbled int s; 526 1.3 garbled 527 1.3 garbled #ifdef DEBUG 528 1.9 garbled aprint_debug("mkclock_pnpbus_nvrd(%d)", off); 529 1.3 garbled #endif 530 1.3 garbled s = splclock(); 531 1.23 thorpej bus_space_write_1(osc->sc_bst, osc->sc_bsh, 0, off & 0xff); 532 1.23 thorpej bus_space_write_1(osc->sc_bst, osc->sc_bsh, 1, off >> 8); 533 1.3 garbled datum = bus_space_read_1(sc->sc_data, sc->sc_datah, 0); 534 1.3 garbled splx(s); 535 1.3 garbled #ifdef DEBUG 536 1.9 garbled aprint_debug(" -> %02x\n", datum); 537 1.3 garbled #endif 538 1.3 garbled return datum; 539 1.3 garbled } 540 1.3 garbled 541 1.3 garbled void 542 1.3 garbled mkclock_pnpbus_nvwr(struct mk48txx_softc *osc, int off, uint8_t datum) 543 1.3 garbled { 544 1.3 garbled struct prep_mk48txx_softc *sc = (struct prep_mk48txx_softc *)osc; 545 1.3 garbled int s; 546 1.3 garbled 547 1.3 garbled #ifdef DEBUG 548 1.9 garbled aprint_debug("mkclock_isa_nvwr(%d, %02x)\n", off, datum); 549 1.3 garbled #endif 550 1.3 garbled s = splclock(); 551 1.23 thorpej bus_space_write_1(osc->sc_bst, osc->sc_bsh, 0, off & 0xff); 552 1.23 thorpej bus_space_write_1(osc->sc_bst, osc->sc_bsh, 1, off >> 8); 553 1.3 garbled bus_space_write_1(sc->sc_data, sc->sc_datah, 0, datum); 554 1.3 garbled splx(s); 555 1.3 garbled } 556