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