Annotation of sys/arch/hppa/stand/libsa/pdc.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pdc.c,v 1.19 2005/04/07 00:21:51 mickey Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1998-2004 Michael Shalayeff
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 19: * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
! 20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 22: * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
! 25: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 26: * THE POSSIBILITY OF SUCH DAMAGE.
! 27: */
! 28: /*
! 29: * Copyright 1996 1995 by Open Software Foundation, Inc.
! 30: * All Rights Reserved
! 31: *
! 32: * Permission to use, copy, modify, and distribute this software and
! 33: * its documentation for any purpose and without fee is hereby granted,
! 34: * provided that the above copyright notice appears in all copies and
! 35: * that both the copyright notice and this permission notice appear in
! 36: * supporting documentation.
! 37: *
! 38: * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
! 39: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
! 40: * FOR A PARTICULAR PURPOSE.
! 41: *
! 42: * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
! 43: * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
! 44: * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
! 45: * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
! 46: * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 47: *
! 48: */
! 49: /*
! 50: * Copyright (c) 1990 mt Xinu, Inc. All rights reserved.
! 51: * Copyright (c) 1990 University of Utah. All rights reserved.
! 52: *
! 53: * This file may be freely distributed in any form as long as
! 54: * this copyright notice is included.
! 55: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
! 56: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
! 57: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
! 58: *
! 59: * Utah $Hdr: pdc.c 1.8 92/03/14$
! 60: */
! 61:
! 62: #include <sys/time.h>
! 63: #include "libsa.h"
! 64: #include <sys/reboot.h>
! 65: #include <sys/disklabel.h>
! 66:
! 67: #include <machine/trap.h>
! 68: #include <machine/pdc.h>
! 69: #include <machine/iomod.h>
! 70: #include <machine/nvm.h>
! 71: #include <machine/param.h>
! 72: #include <machine/cpufunc.h>
! 73:
! 74: #include "dev_hppa.h"
! 75:
! 76: /*
! 77: * Interface routines to initialize and access the PDC.
! 78: */
! 79:
! 80: pdcio_t pdc;
! 81: int pdcbuf[64] PDC_ALIGNMENT;/* PDC return buffer */
! 82: struct stable_storage sstor; /* contents of Stable Storage */
! 83: int sstorsiz; /* size of Stable Storage */
! 84: struct bootdata bd;
! 85: int bdsize = sizeof(struct bootdata);
! 86:
! 87: /*
! 88: * Initialize PDC and related variables.
! 89: */
! 90: void
! 91: pdc_init()
! 92: {
! 93: int err;
! 94:
! 95: /*
! 96: * Initialize important global variables (defined above).
! 97: */
! 98: pdc = (pdcio_t)PAGE0->mem_pdc;
! 99:
! 100: err = (*pdc)(PDC_STABLE, PDC_STABLE_SIZE, pdcbuf, 0, 0);
! 101: if (err >= 0) {
! 102: sstorsiz = min(pdcbuf[0],sizeof(sstor));
! 103: err = (*pdc)(PDC_STABLE, PDC_STABLE_READ, 0, &sstor, sstorsiz);
! 104: }
! 105:
! 106: /*
! 107: * Now that we (may) have an output device, if we encountered
! 108: * an error reading Stable Storage (above), let them know.
! 109: */
! 110: #ifdef DEBUG
! 111: if (debug && err)
! 112: printf("Stable storage PDC_STABLE Read Ret'd %d\n", err);
! 113: #endif
! 114:
! 115: /*
! 116: * Clear the FAULT light (so we know when we get a real one)
! 117: */
! 118: (*pdc)(PDC_CHASSIS, PDC_CHASSIS_DISP,
! 119: PDC_OSTAT(PDC_OSTAT_BOOT) | 0xCEC0);
! 120: }
! 121:
! 122: /*
! 123: * Generic READ/WRITE through IODC. Takes pointer to PDC device
! 124: * information, returns (positive) number of bytes actually read or
! 125: * the (negative) error condition, or zero if at "EOF".
! 126: */
! 127: int
! 128: iodcstrategy(devdata, rw, blk, size, buf, rsize)
! 129: void *devdata;
! 130: int rw;
! 131: daddr_t blk;
! 132: size_t size;
! 133: void *buf;
! 134: size_t *rsize;
! 135: {
! 136: struct hppa_dev *dp = devdata;
! 137: struct pz_device *pzdev = dp->pz_dev;
! 138: int offset, xfer, ret;
! 139:
! 140: #ifdef PDCDEBUG
! 141: if (debug)
! 142: printf("iodcstrategy(%p, %s, %u, %u, %p, %p)\n", devdata,
! 143: rw==F_READ? "READ" : "WRITE", blk, size, buf, rsize);
! 144:
! 145: if (debug > 1)
! 146: PZDEV_PRINT(pzdev);
! 147: #endif
! 148:
! 149: blk += dp->fsoff;
! 150: blk <<= DEV_BSHIFT;
! 151: if ((pzdev->pz_class & PCL_CLASS_MASK) == PCL_SEQU) {
! 152: /* rewind and re-read to seek */
! 153: if (blk < dp->last_blk) {
! 154: #ifdef PDCDEBUG
! 155: if (debug)
! 156: printf("iodc: rewind ");
! 157: #endif
! 158: if ((ret = ((iodcio_t)pzdev->pz_iodc_io)(pzdev->pz_hpa,
! 159: IODC_IO_READ, pzdev->pz_spa, pzdev->pz_layers,
! 160: pdcbuf, 0, dp->buf, 0, 0)) < 0) {
! 161: #ifdef DEBUG
! 162: if (debug)
! 163: printf("IODC_IO: %d\n", ret);
! 164: #endif
! 165: return (EIO);
! 166: } else {
! 167: dp->last_blk = 0;
! 168: dp->last_read = 0;
! 169: }
! 170: }
! 171:
! 172: #ifdef PDCDEBUG
! 173: if (debug)
! 174: printf("seek %d ", dp->last_blk);
! 175: #endif
! 176: for (; (dp->last_blk + dp->last_read) <= blk;
! 177: dp->last_read = ret) {
! 178: twiddle();
! 179: dp->last_blk += dp->last_read;
! 180: if ((ret = ((iodcio_t)pzdev->pz_iodc_io)(pzdev->pz_hpa,
! 181: IODC_IO_READ, pzdev->pz_spa, pzdev->pz_layers,
! 182: pdcbuf, dp->last_blk, dp->buf, IODC_IOSIZ,
! 183: IODC_IOSIZ)) < 0) {
! 184: #ifdef DEBUG
! 185: if (debug)
! 186: printf("IODC_IO: %d\n", ret);
! 187: #endif
! 188: return (EIO);
! 189: }
! 190: if ((ret = pdcbuf[0]) == 0)
! 191: break;
! 192: #ifdef PDCDEBUG
! 193: if (debug)
! 194: printf("-");
! 195: #endif
! 196: }
! 197: #ifdef PDCDEBUG
! 198: if (debug)
! 199: printf("> %d[%d]\n", dp->last_blk, dp->last_read);
! 200: #endif
! 201: }
! 202:
! 203: xfer = 0;
! 204: /* see if we can scratch anything from buffer */
! 205: if (dp->last_blk <= blk && (dp->last_blk + dp->last_read) > blk) {
! 206: twiddle();
! 207: offset = blk - dp->last_blk;
! 208: xfer = min(dp->last_read - offset, size);
! 209: size -= xfer;
! 210: blk += xfer;
! 211: #ifdef PDCDEBUG
! 212: if (debug)
! 213: printf("off=%d,xfer=%d,size=%d,blk=%d\n",
! 214: offset, xfer, size, blk);
! 215: #endif
! 216: bcopy(dp->buf + offset, buf, xfer);
! 217: buf += xfer;
! 218: }
! 219:
! 220: /*
! 221: * double buffer it all the time, to cache
! 222: */
! 223: for (; size; size -= ret, buf += ret, blk += ret, xfer += ret) {
! 224: offset = blk & IOPGOFSET;
! 225: if ((ret = ((iodcio_t)pzdev->pz_iodc_io)(pzdev->pz_hpa,
! 226: (rw == F_READ? IODC_IO_READ: IODC_IO_WRITE),
! 227: pzdev->pz_spa, pzdev->pz_layers, pdcbuf,
! 228: blk - offset, dp->buf, IODC_IOSIZ, IODC_IOSIZ)) < 0) {
! 229: #ifdef DEBUG
! 230: if (debug)
! 231: printf("iodc_read(%d,%d): %d\n",
! 232: blk - offset, IODC_IOSIZ, ret);
! 233: #endif
! 234: if (xfer)
! 235: break;
! 236: else
! 237: return (EIO);
! 238: }
! 239: if ((ret = pdcbuf[0]) <= 0)
! 240: break;
! 241: dp->last_blk = blk - offset;
! 242: dp->last_read = ret;
! 243: if ((ret -= offset) > size)
! 244: ret = size;
! 245: bcopy(dp->buf + offset, buf, ret);
! 246: #ifdef PDCDEBUG
! 247: if (debug)
! 248: printf("read %d(%d,%d)@%x ", ret,
! 249: dp->last_blk, dp->last_read, (u_int)buf);
! 250: #endif
! 251: }
! 252:
! 253: #ifdef PDCDEBUG
! 254: if (debug)
! 255: printf("\n");
! 256: #endif
! 257:
! 258: if (rsize)
! 259: *rsize = xfer;
! 260: return (0);
! 261: }
! 262:
! 263: /*
! 264: * Find a device with specified unit number
! 265: * (any if unit == -1), and of specified class (PCL_*).
! 266: */
! 267: struct pz_device *
! 268: pdc_findev(unit, class)
! 269: int unit, class;
! 270: {
! 271: static struct pz_device pz;
! 272: int layers[sizeof(pz.pz_layers)/sizeof(pz.pz_layers[0])];
! 273: struct iomod *io;
! 274: iodcio_t iodc;
! 275: int err = 0;
! 276:
! 277: #ifdef PDCDEBUG
! 278: if (debug)
! 279: printf("pdc_finddev(%d, %x)\n", unit, class);
! 280: #endif
! 281: iodc = (iodcio_t)(PAGE0->mem_free + IODC_MAXSIZE);
! 282: io = (struct iomod *)PAGE0->mem_boot.pz_hpa;
! 283:
! 284: /* quick hack for boot device */
! 285: if (PAGE0->mem_boot.pz_class == class &&
! 286: (unit == -1 || PAGE0->mem_boot.pz_layers[0] == unit)) {
! 287:
! 288: bcopy (&PAGE0->mem_boot.pz_dp, &pz.pz_dp, sizeof(pz.pz_dp));
! 289: bcopy (pz.pz_layers, layers, sizeof(layers));
! 290: if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, io,
! 291: IODC_INIT, iodc, IODC_MAXSIZE)) < 0) {
! 292: #ifdef DEBUG
! 293: if (debug)
! 294: printf("IODC_READ: %d\n", err);
! 295: #endif
! 296: return NULL;
! 297: }
! 298: } else {
! 299: struct pdc_memmap memmap;
! 300: struct iodc_data mptr;
! 301: int i, stp;
! 302:
! 303: for (i = 0; i < 0xf; i++) {
! 304: pz.pz_bc[0] = pz.pz_bc[1] =
! 305: pz.pz_bc[2] = pz.pz_bc[3] = -1;
! 306: pz.pz_bc[4] = 2;
! 307: pz.pz_bc[5] = 0; /* core bus */
! 308: pz.pz_mod = i;
! 309: if ((pdc)(PDC_MEMMAP, PDC_MEMMAP_HPA, &memmap,
! 310: &pz.pz_dp) < 0)
! 311: continue;
! 312: #ifdef PDCDEBUG
! 313: if (debug)
! 314: printf("memap: %d.%d.%d, hpa=%x, mpgs=%x\n",
! 315: pz.pz_bc[4], pz.pz_bc[5], pz.pz_mod,
! 316: memmap.hpa, memmap.morepages);
! 317: #endif
! 318: io = (struct iomod *) memmap.hpa;
! 319:
! 320: if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, &pdcbuf, io,
! 321: IODC_DATA, &mptr, sizeof(mptr))) < 0) {
! 322: #ifdef DEBUG
! 323: if (debug)
! 324: printf("IODC_DATA: %d\n", err);
! 325: #endif
! 326: continue;
! 327: }
! 328:
! 329: if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, io,
! 330: IODC_INIT, iodc, IODC_MAXSIZE)) < 0) {
! 331: #ifdef DEBUG
! 332: if (debug)
! 333: printf("IODC_READ: %d\n", err);
! 334: #endif
! 335: continue;
! 336: }
! 337:
! 338: stp = IODC_INIT_FIRST;
! 339: do {
! 340: if ((err = (iodc)((u_int)io, stp, io->io_spa,
! 341: layers, pdcbuf, 0, 0, 0, 0)) < 0) {
! 342: #ifdef DEBUG
! 343: if (debug && err != PDC_ERR_EOD)
! 344: printf("IODC_INIT_%s: %d\n",
! 345: stp==IODC_INIT_FIRST?
! 346: "FIRST":"NEXT", err);
! 347: #endif
! 348: break;
! 349: }
! 350: #ifdef PDCDEBUG
! 351: if (debug)
! 352: printf("[%x,%x,%x,%x,%x,%x], "
! 353: "[%x,%x,%x,%x,%x,%x]\n",
! 354: pdcbuf[0], pdcbuf[1], pdcbuf[2],
! 355: pdcbuf[3], pdcbuf[4], pdcbuf[5],
! 356: layers[0], layers[1], layers[2],
! 357: layers[3], layers[4], layers[5]);
! 358: #endif
! 359: stp = IODC_INIT_NEXT;
! 360:
! 361: } while (pdcbuf[1] != class &&
! 362: unit != -1 && unit != layers[0]);
! 363:
! 364: if (err >= 0)
! 365: break;
! 366: }
! 367: }
! 368:
! 369: if (err >= 0) {
! 370: /* init device */
! 371: if (0 && (err = (iodc)((u_int)io, IODC_INIT_DEV, io->io_spa,
! 372: layers, pdcbuf, 0, 0, 0, 0)) < 0) {
! 373: #ifdef DEBUG
! 374: if (debug)
! 375: printf("INIT_DEV: %d\n", err);
! 376: #endif
! 377: return NULL;
! 378: }
! 379:
! 380: /* read i/o entry code */
! 381: if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, io,
! 382: IODC_IO, iodc, IODC_MAXSIZE)) < 0) {
! 383: #ifdef DEBUG
! 384: if (debug)
! 385: printf("IODC_READ: %d\n", err);
! 386: #endif
! 387: return NULL;
! 388: }
! 389:
! 390: pz.pz_flags = 0;
! 391: bcopy(layers, pz.pz_layers, sizeof(pz.pz_layers));
! 392: pz.pz_hpa = (u_int)io;
! 393: /* XXX pz.pz_spa = io->io_spa; */
! 394: pz.pz_iodc_io = (u_int)iodc;
! 395: pz.pz_class = class;
! 396:
! 397: return &pz;
! 398: }
! 399:
! 400: return NULL;
! 401: }
! 402:
! 403: static __inline void
! 404: fall(int c_base, int c_count, int c_loop, int c_stride, int data)
! 405: {
! 406: int loop; /* Internal vars */
! 407:
! 408: for (; c_count--; c_base += c_stride)
! 409: for (loop = c_loop; loop--; )
! 410: if (data)
! 411: fdce(0, c_base);
! 412: else
! 413: fice(0, c_base);
! 414: }
! 415:
! 416: /*
! 417: * fcacheall - Flush all caches.
! 418: *
! 419: * This routine is just a wrapper around the real cache flush routine.
! 420: */
! 421: struct pdc_cache pdc_cacheinfo PDC_ALIGNMENT;
! 422:
! 423: void
! 424: fcacheall()
! 425: {
! 426: int err;
! 427:
! 428: if ((err = (*pdc)(PDC_CACHE, PDC_CACHE_DFLT, &pdc_cacheinfo)) < 0) {
! 429: #ifdef DEBUG
! 430: if (debug)
! 431: printf("fcacheall: PDC_CACHE failed (%d).\n", err);
! 432: #endif
! 433: return;
! 434: }
! 435: #if PDCDEBUG
! 436: if (debug)
! 437: printf("pdc_cache:\nic={%u,%x,%x,%u,%u,%u}\n"
! 438: "dc={%u,%x,%x,%u,%u,%u}\n",
! 439: pdc_cacheinfo.ic_size, *(u_int *)&pdc_cacheinfo.ic_conf,
! 440: pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_stride,
! 441: pdc_cacheinfo.ic_count, pdc_cacheinfo.ic_loop,
! 442: pdc_cacheinfo.dc_size, *(u_int *)&pdc_cacheinfo.ic_conf,
! 443: pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_stride,
! 444: pdc_cacheinfo.dc_count, pdc_cacheinfo.dc_loop);
! 445: #endif
! 446: /*
! 447: * Flush the instruction, then data cache.
! 448: */
! 449: fall(pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_count,
! 450: pdc_cacheinfo.ic_loop, pdc_cacheinfo.ic_stride, 0);
! 451: sync_caches();
! 452: fall(pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_count,
! 453: pdc_cacheinfo.dc_loop, pdc_cacheinfo.dc_stride, 1);
! 454: sync_caches();
! 455: }
CVSweb