Annotation of sys/arch/mvme88k/dev/nvram.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: nvram.c,v 1.29 2006/06/19 15:13:35 deraadt Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1995 Theo de Raadt
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
! 16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
! 19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 25: * SUCH DAMAGE.
! 26: */
! 27:
! 28: #include <sys/param.h>
! 29: #include <sys/kernel.h>
! 30: #include <sys/device.h>
! 31: #include <sys/malloc.h>
! 32: #include <sys/systm.h>
! 33: #include <sys/proc.h>
! 34: #include <sys/ioctl.h>
! 35: #include <sys/uio.h>
! 36:
! 37: #include <machine/autoconf.h>
! 38: #include <machine/bugio.h>
! 39: #include <machine/conf.h>
! 40: #include <machine/cpu.h>
! 41: #include <machine/mioctl.h>
! 42: #include <machine/psl.h>
! 43: #include <machine/vmparam.h>
! 44:
! 45: #include <uvm/uvm_param.h>
! 46:
! 47: #include <mvme88k/dev/memdevs.h>
! 48: #include <mvme88k/dev/nvramreg.h>
! 49: #include <mvme88k/dev/pcctworeg.h>
! 50:
! 51: struct nvramsoftc {
! 52: struct device sc_dev;
! 53: paddr_t sc_base;
! 54: bus_space_tag_t sc_iot;
! 55: bus_space_handle_t sc_ioh;
! 56: bus_addr_t sc_regs;
! 57: size_t sc_len;
! 58:
! 59: #ifdef MVME188
! 60: u_int8_t *sc_nvram;
! 61: #endif
! 62: };
! 63:
! 64: void nvramattach(struct device *, struct device *, void *);
! 65: int nvrammatch(struct device *, void *, void *);
! 66:
! 67: struct cfattach nvram_ca = {
! 68: sizeof(struct nvramsoftc), nvrammatch, nvramattach
! 69: };
! 70:
! 71: struct cfdriver nvram_cd = {
! 72: NULL, "nvram", DV_DULL
! 73: };
! 74:
! 75: u_long chiptotime(int, int, int, int, int, int);
! 76: int nvram188read(struct nvramsoftc *, struct uio *, int);
! 77: int nvram188write(struct nvramsoftc *, struct uio *, int);
! 78:
! 79: int
! 80: nvrammatch(parent, vcf, args)
! 81: struct device *parent;
! 82: void *vcf, *args;
! 83: {
! 84: struct confargs *ca = args;
! 85: bus_space_handle_t ioh;
! 86: int rc;
! 87:
! 88: if (bus_space_map(ca->ca_iot, ca->ca_paddr, PAGE_SIZE, 0, &ioh) != 0)
! 89: return (0);
! 90: rc = badaddr((vaddr_t)bus_space_vaddr(ca->ca_iot, ioh), 1) == 0;
! 91: bus_space_unmap(ca->ca_iot, ioh, PAGE_SIZE);
! 92: return (rc);
! 93: }
! 94:
! 95: void
! 96: nvramattach(parent, self, args)
! 97: struct device *parent, *self;
! 98: void *args;
! 99: {
! 100: struct confargs *ca = args;
! 101: struct nvramsoftc *sc = (struct nvramsoftc *)self;
! 102: bus_space_handle_t ioh;
! 103: vsize_t maplen;
! 104:
! 105: switch (brdtyp) {
! 106: #ifdef MVME188
! 107: case BRD_188:
! 108: sc->sc_len = MK48T02_SIZE;
! 109: maplen = sc->sc_len * 4;
! 110: sc->sc_regs = M188_NVRAM_TOD_OFF;
! 111: break;
! 112: #endif
! 113: default:
! 114: sc->sc_len = MK48T08_SIZE;
! 115: maplen = sc->sc_len;
! 116: sc->sc_regs = SBC_NVRAM_TOD_OFF;
! 117: break;
! 118: }
! 119:
! 120: sc->sc_iot = ca->ca_iot;
! 121: sc->sc_base = ca->ca_paddr;
! 122:
! 123: if (bus_space_map(sc->sc_iot, sc->sc_base, round_page(maplen),
! 124: BUS_SPACE_MAP_LINEAR, &ioh) != 0) {
! 125: printf(": can't map memory!\n");
! 126: return;
! 127: }
! 128:
! 129: sc->sc_ioh = ioh;
! 130:
! 131: printf(": MK48T0%d\n", sc->sc_len / 1024);
! 132: }
! 133:
! 134: /*
! 135: * Return the best possible estimate of the time in the timeval
! 136: * to which tvp points. We do this by returning the current time
! 137: * plus the amount of time since the last clock interrupt (clock.c:clkread).
! 138: *
! 139: * Check that this time is no less than any previously-reported time,
! 140: * which could happen around the time of a clock adjustment. Just for fun,
! 141: * we guarantee that the time will be greater than the value obtained by a
! 142: * previous call.
! 143: */
! 144: void
! 145: microtime(tvp)
! 146: struct timeval *tvp;
! 147: {
! 148: int s = splhigh();
! 149: static struct timeval lasttime;
! 150:
! 151: *tvp = time;
! 152: while (tvp->tv_usec >= 1000000) {
! 153: tvp->tv_sec++;
! 154: tvp->tv_usec -= 1000000;
! 155: }
! 156: if (tvp->tv_sec == lasttime.tv_sec &&
! 157: tvp->tv_usec <= lasttime.tv_usec &&
! 158: (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
! 159: tvp->tv_sec++;
! 160: tvp->tv_usec -= 1000000;
! 161: }
! 162: lasttime = *tvp;
! 163: splx(s);
! 164: }
! 165:
! 166: /*
! 167: * BCD to decimal and decimal to BCD.
! 168: */
! 169: #define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf))
! 170: #define TOBCD(x) (((x) / 10 * 16) + ((x) % 10))
! 171:
! 172: #define SECYR (SECDAY * 365)
! 173: #define LEAPYEAR(y) (((y) & 3) == 0)
! 174:
! 175: /*
! 176: * This code is defunct after 2068.
! 177: * Will Unix still be here then??
! 178: */
! 179: const int dayyr[12] =
! 180: { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
! 181:
! 182: u_long
! 183: chiptotime(sec, min, hour, day, mon, year)
! 184: int sec, min, hour, day, mon, year;
! 185: {
! 186: int days, yr;
! 187:
! 188: sec = FROMBCD(sec);
! 189: min = FROMBCD(min);
! 190: hour = FROMBCD(hour);
! 191: day = FROMBCD(day);
! 192: mon = FROMBCD(mon);
! 193: year = FROMBCD(year) + YEAR0;
! 194:
! 195: /* simple sanity checks */
! 196: if (year>164 || mon<1 || mon>12 || day<1 || day>31)
! 197: return (0);
! 198: yr = 70;
! 199: days = 0;
! 200:
! 201: if (year < 70) { /* 2000 <= year */
! 202: for (; yr < 100; yr++) /* deal with first 30 years */
! 203: days += LEAPYEAR(yr) ? 366 : 365;
! 204: yr = 0;
! 205: }
! 206:
! 207: for (; yr < year; yr++) /* deal with years left */
! 208: days += LEAPYEAR(yr) ? 366 : 365;
! 209:
! 210: days += dayyr[mon - 1] + day - 1;
! 211:
! 212: if (LEAPYEAR(yr) && mon > 2)
! 213: days++;
! 214:
! 215: /* now have days since Jan 1, 1970; the rest is easy... */
! 216: return (days * SECDAY + hour * 3600 + min * 60 + sec);
! 217: }
! 218:
! 219: struct chiptime {
! 220: int sec;
! 221: int min;
! 222: int hour;
! 223: int wday;
! 224: int day;
! 225: int mon;
! 226: int year;
! 227: };
! 228:
! 229: void timetochip(struct chiptime *c);
! 230:
! 231: void
! 232: timetochip(c)
! 233: struct chiptime *c;
! 234: {
! 235: int t, t2, t3, now = time.tv_sec;
! 236:
! 237: /* January 1 1970 was a Thursday (4 in unix wdays) */
! 238: /* compute the days since the epoch */
! 239: t2 = now / SECDAY;
! 240:
! 241: t3 = (t2 + 4) % 7; /* day of week */
! 242: c->wday = TOBCD(t3 + 1);
! 243:
! 244: /* compute the year */
! 245: t = 69;
! 246: while (t2 >= 0) { /* whittle off years */
! 247: t3 = t2;
! 248: t++;
! 249: t2 -= LEAPYEAR(t) ? 366 : 365;
! 250: }
! 251: c->year = t;
! 252:
! 253: /* t3 = month + day; separate */
! 254: t = LEAPYEAR(t);
! 255: for (t2 = 1; t2 < 12; t2++)
! 256: if (t3 < (dayyr[t2] + ((t && (t2 > 1)) ? 1:0)))
! 257: break;
! 258:
! 259: /* t2 is month */
! 260: c->mon = t2;
! 261: c->day = t3 - dayyr[t2 - 1] + 1;
! 262: if (t && t2 > 2)
! 263: c->day--;
! 264:
! 265: /* the rest is easy */
! 266: t = now % SECDAY;
! 267: c->hour = t / 3600;
! 268: t %= 3600;
! 269: c->min = t / 60;
! 270: c->sec = t % 60;
! 271:
! 272: c->sec = TOBCD(c->sec);
! 273: c->min = TOBCD(c->min);
! 274: c->hour = TOBCD(c->hour);
! 275: c->day = TOBCD(c->day);
! 276: c->mon = TOBCD(c->mon);
! 277: c->year = TOBCD((c->year - YEAR0) % 100);
! 278: }
! 279:
! 280: /*
! 281: * Set up the system's time, given a `reasonable' time value.
! 282: */
! 283:
! 284: void
! 285: inittodr(base)
! 286: time_t base;
! 287: {
! 288: struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0];
! 289: int sec, min, hour, day, mon, year;
! 290: int badbase = 0, waszero = base == 0;
! 291:
! 292: if (base < 35 * SECYR) {
! 293: /*
! 294: * If base is 0, assume filesystem time is just unknown
! 295: * in stead of preposterous. Don't bark.
! 296: */
! 297: if (base != 0)
! 298: printf("WARNING: preposterous time in file system\n");
! 299: /* not going to use it anyway, if the chip is readable */
! 300: base = 36 * SECYR + 109 * SECDAY + 22 * 3600;
! 301: badbase = 1;
! 302: }
! 303:
! 304: if (brdtyp == BRD_188) {
! 305: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 306: sc->sc_regs + (CLK_CSR << 2), CLK_READ |
! 307: bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 308: sc->sc_regs + (CLK_CSR << 2)));
! 309: sec = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 310: sc->sc_regs + (CLK_SEC << 2)) & 0xff;
! 311: min = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 312: sc->sc_regs + (CLK_MIN << 2)) & 0xff;
! 313: hour = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 314: sc->sc_regs + (CLK_HOUR << 2)) & 0xff;
! 315: day = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 316: sc->sc_regs + (CLK_DAY << 2)) & 0xff;
! 317: mon = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 318: sc->sc_regs + (CLK_MONTH << 2)) & 0xff;
! 319: year = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 320: sc->sc_regs + (CLK_YEAR << 2)) & 0xff;
! 321: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 322: sc->sc_regs + (CLK_CSR << 2),
! 323: bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 324: sc->sc_regs + (CLK_CSR << 2)) & ~CLK_READ);
! 325: } else {
! 326: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 327: sc->sc_regs + CLK_CSR, CLK_READ |
! 328: bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 329: sc->sc_regs + CLK_CSR));
! 330: sec = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 331: sc->sc_regs + CLK_SEC);
! 332: min = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 333: sc->sc_regs + CLK_MIN);
! 334: hour = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 335: sc->sc_regs + CLK_HOUR);
! 336: day = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 337: sc->sc_regs + CLK_DAY);
! 338: mon = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 339: sc->sc_regs + CLK_MONTH);
! 340: year = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 341: sc->sc_regs + CLK_YEAR);
! 342: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 343: sc->sc_regs + CLK_CSR,
! 344: bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 345: sc->sc_regs + CLK_CSR) & ~CLK_READ);
! 346: }
! 347:
! 348: if ((time.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) {
! 349: printf("WARNING: bad date in nvram");
! 350: #ifdef DEBUG
! 351: printf("\nday = %d, mon = %d, year = %d, hour = %d, min = %d, sec = %d",
! 352: FROMBCD(day), FROMBCD(mon), FROMBCD(year) + YEAR0,
! 353: FROMBCD(hour), FROMBCD(min), FROMBCD(sec));
! 354: #endif
! 355: /*
! 356: * Believe the time in the file system for lack of
! 357: * anything better, resetting the clock.
! 358: */
! 359: time.tv_sec = base;
! 360: if (!badbase)
! 361: resettodr();
! 362: } else {
! 363: int deltat = time.tv_sec - base;
! 364:
! 365: if (deltat < 0)
! 366: deltat = -deltat;
! 367: if (waszero || deltat < 2 * SECDAY)
! 368: return;
! 369: printf("WARNING: clock %s %d days",
! 370: time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
! 371: }
! 372: printf(" -- CHECK AND RESET THE DATE!\n");
! 373: }
! 374:
! 375: /*
! 376: * Reset the clock based on the current time.
! 377: * Used when the current clock is preposterous, when the time is changed,
! 378: * and when rebooting. Do nothing if the time is not yet known, e.g.,
! 379: * when crashing during autoconfig.
! 380: */
! 381: void
! 382: resettodr()
! 383: {
! 384: struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0];
! 385: struct chiptime c;
! 386:
! 387: if (!time.tv_sec || sc == NULL)
! 388: return;
! 389: timetochip(&c);
! 390:
! 391: if (brdtyp == BRD_188) {
! 392: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 393: sc->sc_regs + (CLK_CSR << 2), CLK_WRITE |
! 394: bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 395: sc->sc_regs + (CLK_CSR << 2)));
! 396: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 397: sc->sc_regs + (CLK_SEC << 2), c.sec);
! 398: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 399: sc->sc_regs + (CLK_MIN << 2), c.min);
! 400: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 401: sc->sc_regs + (CLK_HOUR << 2), c.hour);
! 402: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 403: sc->sc_regs + (CLK_WDAY << 2), c.wday);
! 404: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 405: sc->sc_regs + (CLK_DAY << 2), c.day);
! 406: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 407: sc->sc_regs + (CLK_MONTH << 2), c.mon);
! 408: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 409: sc->sc_regs + (CLK_YEAR << 2), c.year);
! 410: bus_space_write_4(sc->sc_iot, sc->sc_ioh,
! 411: sc->sc_regs + (CLK_CSR << 2),
! 412: bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 413: sc->sc_regs + (CLK_CSR << 2)) & ~CLK_WRITE);
! 414: } else {
! 415: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 416: sc->sc_regs + CLK_CSR, CLK_WRITE |
! 417: bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 418: sc->sc_regs + CLK_CSR));
! 419: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 420: sc->sc_regs + CLK_SEC, c.sec);
! 421: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 422: sc->sc_regs + CLK_MIN, c.min);
! 423: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 424: sc->sc_regs + CLK_HOUR, c.hour);
! 425: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 426: sc->sc_regs + CLK_WDAY, c.wday);
! 427: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 428: sc->sc_regs + CLK_DAY, c.day);
! 429: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 430: sc->sc_regs + CLK_MONTH, c.mon);
! 431: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 432: sc->sc_regs + CLK_YEAR, c.year);
! 433: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
! 434: sc->sc_regs + CLK_CSR,
! 435: bus_space_read_1(sc->sc_iot, sc->sc_ioh,
! 436: sc->sc_regs + CLK_CSR) & ~CLK_WRITE);
! 437: }
! 438: }
! 439:
! 440: /*ARGSUSED*/
! 441: int
! 442: nvramopen(dev, flag, mode, p)
! 443: dev_t dev;
! 444: int flag, mode;
! 445: struct proc *p;
! 446: {
! 447: if (minor(dev) >= nvram_cd.cd_ndevs ||
! 448: nvram_cd.cd_devs[minor(dev)] == NULL)
! 449: return (ENODEV);
! 450:
! 451: return (0);
! 452: }
! 453:
! 454: /*ARGSUSED*/
! 455: int
! 456: nvramclose(dev, flag, mode, p)
! 457: dev_t dev;
! 458: int flag, mode;
! 459: struct proc *p;
! 460: {
! 461: /*
! 462: * On MVME188, it might be worth free()ing the NVRAM copy here.
! 463: */
! 464: return (0);
! 465: }
! 466:
! 467: /*ARGSUSED*/
! 468: int
! 469: nvramioctl(dev, cmd, data, flag, p)
! 470: dev_t dev;
! 471: u_long cmd;
! 472: caddr_t data;
! 473: int flag;
! 474: struct proc *p;
! 475: {
! 476: int unit = minor(dev);
! 477: struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[unit];
! 478: int error = 0;
! 479:
! 480: switch (cmd) {
! 481: case MIOCGSIZ:
! 482: *(int *)data = sc->sc_len;
! 483: break;
! 484: default:
! 485: error = ENOTTY;
! 486: break;
! 487: }
! 488: return (error);
! 489: }
! 490:
! 491: /*ARGSUSED*/
! 492: int
! 493: nvramread(dev_t dev, struct uio *uio, int flags)
! 494: {
! 495: int unit = minor(dev);
! 496: struct nvramsoftc *sc = (struct nvramsoftc *)nvram_cd.cd_devs[unit];
! 497:
! 498: #ifdef MVME188
! 499: if (brdtyp == BRD_188)
! 500: return (nvram188read(sc, uio, flags));
! 501: #endif
! 502:
! 503: return (memdevrw(bus_space_vaddr(sc->sc_iot, sc->sc_ioh),
! 504: sc->sc_len, uio, flags));
! 505: }
! 506:
! 507: /*ARGSUSED*/
! 508: int
! 509: nvramwrite(dev_t dev, struct uio *uio, int flags)
! 510: {
! 511: int unit = minor(dev);
! 512: struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[unit];
! 513:
! 514: #ifdef MVME188
! 515: if (brdtyp == BRD_188)
! 516: return (nvram188write(sc, uio, flags));
! 517: #endif
! 518:
! 519: return (memdevrw(bus_space_vaddr(sc->sc_iot, sc->sc_ioh),
! 520: sc->sc_len, uio, flags));
! 521: }
! 522:
! 523: paddr_t
! 524: nvrammmap(dev, off, prot)
! 525: dev_t dev;
! 526: off_t off;
! 527: int prot;
! 528: {
! 529: int unit = minor(dev);
! 530: struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[unit];
! 531:
! 532: if (minor(dev) != 0)
! 533: return (-1);
! 534:
! 535: #ifdef MVME188
! 536: /* disallow mmap on MVME188 due to non-linear layout */
! 537: if (brdtyp == BRD_188)
! 538: return (-1);
! 539: #endif
! 540:
! 541: /* allow access only in RAM */
! 542: if (off < 0 || off > sc->sc_len)
! 543: return (-1);
! 544: return (atop(sc->sc_base + off));
! 545: }
! 546:
! 547: #ifdef MVME188
! 548:
! 549: int read_nvram(struct nvramsoftc *);
! 550:
! 551: /*
! 552: * Build a local copy of the NVRAM contents.
! 553: */
! 554: int
! 555: read_nvram(struct nvramsoftc *sc)
! 556: {
! 557: u_int cnt;
! 558: u_int8_t *dest;
! 559: u_int32_t *src;
! 560:
! 561: if (sc->sc_nvram == NULL) {
! 562: sc->sc_nvram = (u_int8_t *)malloc(sc->sc_len, M_DEVBUF,
! 563: M_WAITOK | M_CANFAIL);
! 564: if (sc->sc_nvram == NULL)
! 565: return (EAGAIN);
! 566: }
! 567:
! 568: dest = sc->sc_nvram;
! 569: src = (u_int32_t *)bus_space_vaddr(sc->sc_iot, sc->sc_ioh);
! 570: cnt = sc->sc_len;
! 571: while (cnt-- != 0)
! 572: *dest++ = (u_int8_t)*src++;
! 573:
! 574: return (0);
! 575: }
! 576:
! 577: /*
! 578: * Specific memdevrw wrappers to cope with the 188 design.
! 579: */
! 580:
! 581: int
! 582: nvram188read(struct nvramsoftc *sc, struct uio *uio, int flags)
! 583: {
! 584: int rc;
! 585:
! 586: /*
! 587: * Get a copy of the NVRAM contents.
! 588: */
! 589: rc = read_nvram(sc);
! 590: if (rc != 0)
! 591: return (rc);
! 592:
! 593: /*
! 594: * Move data from our NVRAM copy to the user.
! 595: */
! 596: return (memdevrw(sc->sc_nvram, sc->sc_len, uio, flags));
! 597: }
! 598:
! 599: int
! 600: nvram188write(struct nvramsoftc *sc, struct uio *uio, int flags)
! 601: {
! 602: u_int cnt;
! 603: u_int8_t *src;
! 604: u_int32_t *dest;
! 605: int rc;
! 606:
! 607: /*
! 608: * Get a copy of the NVRAM contents.
! 609: */
! 610: rc = read_nvram(sc);
! 611: if (rc != 0)
! 612: return (rc);
! 613:
! 614: /*
! 615: * Move data from the user to our NVRAM copy.
! 616: */
! 617: rc = memdevrw(sc->sc_nvram, sc->sc_len, uio, flags);
! 618: if (rc != 0) {
! 619: /* reset NVRAM copy contents */
! 620: read_nvram(sc);
! 621: return (rc);
! 622: }
! 623:
! 624: /*
! 625: * Update the NVRAM. This could be optimized by only working on
! 626: * the areas which have been modified by the user.
! 627: */
! 628: src = sc->sc_nvram;
! 629: dest = (u_int32_t *)bus_space_vaddr(sc->sc_iot, sc->sc_ioh);
! 630: cnt = sc->sc_len;
! 631: while (cnt-- != 0) {
! 632: if ((*dest & 0xff) != *src)
! 633: *dest = (u_int32_t)*src;
! 634: dest++;
! 635: src++;
! 636: }
! 637:
! 638: return (0);
! 639: }
! 640: #endif
CVSweb