Annotation of sys/arch/hppa/hppa/autoconf.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: autoconf.c,v 1.50 2007/06/01 22:40:33 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1998-2003 Michael Shalayeff
! 5: * Copyright (c) 1992, 1993
! 6: * The Regents of the University of California. All rights reserved.
! 7: *
! 8: * This software was developed by the Computer Systems Engineering group
! 9: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
! 10: * contributed to Berkeley.
! 11: *
! 12: * All advertising materials mentioning features or use of this software
! 13: * must display the following acknowledgement:
! 14: * This product includes software developed by the University of
! 15: * California, Lawrence Berkeley Laboratory.
! 16: *
! 17: * Redistribution and use in source and binary forms, with or without
! 18: * modification, are permitted provided that the following conditions
! 19: * are met:
! 20: * 1. Redistributions of source code must retain the above copyright
! 21: * notice, this list of conditions and the following disclaimer.
! 22: * 2. Redistributions in binary form must reproduce the above copyright
! 23: * notice, this list of conditions and the following disclaimer in the
! 24: * documentation and/or other materials provided with the distribution.
! 25: * 3. Neither the name of the University nor the names of its contributors
! 26: * may be used to endorse or promote products derived from this software
! 27: * without specific prior written permission.
! 28: *
! 29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 39: * SUCH DAMAGE.
! 40: *
! 41: * @(#)autoconf.c 8.4 (Berkeley) 10/1/93
! 42: */
! 43:
! 44: #include "pci.h"
! 45:
! 46: #include <sys/param.h>
! 47: #include <sys/systm.h>
! 48: #include <sys/buf.h>
! 49: #include <sys/disklabel.h>
! 50: #include <sys/conf.h>
! 51: #include <sys/reboot.h>
! 52: #include <sys/device.h>
! 53: #include <sys/timeout.h>
! 54:
! 55: #include <uvm/uvm_extern.h>
! 56:
! 57: #include <machine/iomod.h>
! 58: #include <machine/autoconf.h>
! 59:
! 60: #include <dev/cons.h>
! 61:
! 62: #include <hppa/dev/cpudevs.h>
! 63:
! 64: #if NPCI > 0
! 65: #include <dev/pci/pcivar.h>
! 66: #include <dev/pci/pcireg.h>
! 67: #endif
! 68:
! 69: /* device we booted from */
! 70: struct device *bootdv;
! 71: void dumpconf(void);
! 72:
! 73: void (*cold_hook)(int); /* see below */
! 74:
! 75: /*
! 76: * LED blinking thing
! 77: */
! 78: #ifdef USELEDS
! 79: #include <sys/dkstat.h>
! 80: #include <sys/kernel.h>
! 81:
! 82: struct timeout heartbeat_tmo;
! 83: void heartbeat(void *);
! 84: #endif
! 85:
! 86: #include "cd.h"
! 87: #include "sd.h"
! 88: #include "st.h"
! 89: #if NCD > 0 || NSD > 0 || NST > 0
! 90: #include <scsi/scsi_all.h>
! 91: #include <scsi/scsiconf.h>
! 92: #endif
! 93:
! 94: #ifdef USELEDS
! 95: /*
! 96: * turn the heartbeat alive.
! 97: * right thing would be to pass counter to each subsequent timeout
! 98: * as an argument to heartbeat() incrementing every turn,
! 99: * i.e. avoiding the static hbcnt, but doing timeout_set() on each
! 100: * timeout_add() sounds ugly, guts of struct timeout looks ugly
! 101: * to ponder in even more.
! 102: */
! 103: void
! 104: heartbeat(v)
! 105: void *v;
! 106: {
! 107: static u_int hbcnt = 0, ocp_total, ocp_idle;
! 108: int toggle, cp_mask, cp_total, cp_idle;
! 109:
! 110: timeout_add(&heartbeat_tmo, hz / 16);
! 111:
! 112: cp_idle = cp_time[CP_IDLE];
! 113: cp_total = cp_time[CP_USER] + cp_time[CP_NICE] + cp_time[CP_SYS] +
! 114: cp_time[CP_INTR] + cp_time[CP_IDLE];
! 115: if (cp_total == ocp_total)
! 116: cp_total = ocp_total + 1;
! 117: if (cp_idle == ocp_idle)
! 118: cp_idle = ocp_idle + 1;
! 119: cp_mask = 0xf0 >> (cp_idle - ocp_idle) * 4 / (cp_total - ocp_total);
! 120: cp_mask &= 0xf0;
! 121: ocp_total = cp_total;
! 122: ocp_idle = cp_idle;
! 123: /*
! 124: * do this:
! 125: *
! 126: * |~| |~|
! 127: * _| |_| |_,_,_,_
! 128: * 0 1 2 3 4 6 7
! 129: */
! 130: toggle = 0;
! 131: if (hbcnt++ < 8 && hbcnt & 1)
! 132: toggle = PALED_HEARTBEAT;
! 133: hbcnt &= 15;
! 134: ledctl(cp_mask,
! 135: (~cp_mask & 0xf0) | PALED_NETRCV | PALED_NETSND | PALED_DISK,
! 136: toggle);
! 137: }
! 138: #endif
! 139:
! 140: /*
! 141: * This is called by configure to set dumplo and dumpsize.
! 142: * Dumps always skip the first CLBYTES of disk space
! 143: * in case there might be a disk label stored there.
! 144: * If there is extra space, put dump at the end to
! 145: * reduce the chance that swapping trashes it.
! 146: */
! 147: void
! 148: dumpconf(void)
! 149: {
! 150: extern int dumpsize;
! 151: int nblks, dumpblks; /* size of dump area */
! 152:
! 153: if (dumpdev == NODEV ||
! 154: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 155: return;
! 156: if (nblks <= ctod(1))
! 157: return;
! 158:
! 159: dumpblks = cpu_dumpsize();
! 160: if (dumpblks < 0)
! 161: return;
! 162: dumpblks += ctod(physmem);
! 163:
! 164: /* If dump won't fit (incl. room for possible label), punt. */
! 165: if (dumpblks > (nblks - ctod(1)))
! 166: return;
! 167:
! 168: /* Put dump at end of partition */
! 169: dumplo = nblks - dumpblks;
! 170:
! 171: /* dumpsize is in page units, and doesn't include headers. */
! 172: dumpsize = physmem;
! 173: }
! 174:
! 175: void
! 176: print_devpath(const char *label, struct pz_device *pz)
! 177: {
! 178: int i;
! 179:
! 180: printf("%s: ", label);
! 181:
! 182: for (i = 0; i < 6; i++)
! 183: if (pz->pz_bc[i] >= 0)
! 184: printf("%d/", pz->pz_bc[i]);
! 185:
! 186: printf("%d.%x", pz->pz_mod, pz->pz_layers[0]);
! 187: for (i = 1; i < 6 && pz->pz_layers[i]; i++)
! 188: printf(".%x", pz->pz_layers[i]);
! 189:
! 190: printf(" class=%d flags=%b hpa=%p spa=%p io=%p\n", pz->pz_class,
! 191: pz->pz_flags, PZF_BITS, pz->pz_hpa, pz->pz_spa, pz->pz_iodc_io);
! 192: }
! 193:
! 194: struct pdc_memmap pdc_memmap PDC_ALIGNMENT;
! 195: struct pdc_sysmap_find pdc_find PDC_ALIGNMENT;
! 196: struct pdc_sysmap_addrs pdc_addr PDC_ALIGNMENT;
! 197: struct pdc_iodc_read pdc_iodc_read PDC_ALIGNMENT;
! 198:
! 199: void
! 200: pdc_scanbus(self, ca, maxmod, hpa)
! 201: struct device *self;
! 202: struct confargs *ca;
! 203: int maxmod;
! 204: hppa_hpa_t hpa;
! 205: {
! 206: int i;
! 207:
! 208: for (i = maxmod; i--; ) {
! 209: struct confargs nca;
! 210: int error;
! 211:
! 212: bzero(&nca, sizeof(nca));
! 213: nca.ca_iot = ca->ca_iot;
! 214: nca.ca_dmatag = ca->ca_dmatag;
! 215: nca.ca_dp.dp_bc[0] = ca->ca_dp.dp_bc[1];
! 216: nca.ca_dp.dp_bc[1] = ca->ca_dp.dp_bc[2];
! 217: nca.ca_dp.dp_bc[2] = ca->ca_dp.dp_bc[3];
! 218: nca.ca_dp.dp_bc[3] = ca->ca_dp.dp_bc[4];
! 219: nca.ca_dp.dp_bc[4] = ca->ca_dp.dp_bc[5];
! 220: nca.ca_dp.dp_bc[5] = ca->ca_dp.dp_mod;
! 221: nca.ca_dp.dp_mod = i;
! 222: nca.ca_hpamask = ca->ca_hpamask;
! 223: nca.ca_naddrs = 0;
! 224: nca.ca_hpa = 0;
! 225:
! 226: if (hpa) {
! 227: nca.ca_hpa = hpa + IOMOD_HPASIZE * i;
! 228: nca.ca_dp.dp_mod = i;
! 229: } else if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MEMMAP,
! 230: PDC_MEMMAP_HPA, &pdc_memmap, &nca.ca_dp)) == 0)
! 231: nca.ca_hpa = pdc_memmap.hpa;
! 232: else if ((error = pdc_call((iodcio_t)pdc, 0, PDC_SYSMAP,
! 233: PDC_SYSMAP_HPA, &pdc_memmap, &nca.ca_dp)) == 0) {
! 234: struct device_path path;
! 235: int im, ia;
! 236:
! 237: nca.ca_hpa = pdc_memmap.hpa;
! 238:
! 239: for (im = 0; !(error = pdc_call((iodcio_t)pdc, 0,
! 240: PDC_SYSMAP, PDC_SYSMAP_FIND,
! 241: &pdc_find, &path, im)) &&
! 242: pdc_find.hpa != nca.ca_hpa; im++)
! 243: ;
! 244:
! 245: if (!error)
! 246: nca.ca_hpasz = pdc_find.size << PGSHIFT;
! 247:
! 248: if (!error && pdc_find.naddrs) {
! 249: nca.ca_naddrs = pdc_find.naddrs;
! 250: if (nca.ca_naddrs > 16) {
! 251: nca.ca_naddrs = 16;
! 252: printf("WARNING: too many (%d) addrs\n",
! 253: pdc_find.naddrs);
! 254: }
! 255:
! 256: if (autoconf_verbose)
! 257: printf(">> ADDRS:");
! 258:
! 259: for (ia = 0; !(error = pdc_call((iodcio_t)pdc,
! 260: 0, PDC_SYSMAP, PDC_SYSMAP_ADDR, &pdc_addr,
! 261: im, ia)) && ia < nca.ca_naddrs; ia++) {
! 262: nca.ca_addrs[ia].addr = pdc_addr.hpa;
! 263: nca.ca_addrs[ia].size =
! 264: pdc_addr.size << PGSHIFT;
! 265:
! 266: if (autoconf_verbose)
! 267: printf(" 0x%lx[0x%x]",
! 268: nca.ca_addrs[ia].addr,
! 269: nca.ca_addrs[ia].size);
! 270: }
! 271: if (autoconf_verbose)
! 272: printf("\n");
! 273: }
! 274: }
! 275:
! 276: if (!nca.ca_hpa)
! 277: continue;
! 278:
! 279: if (autoconf_verbose)
! 280: printf(">> HPA 0x%lx[0x%x]\n",
! 281: nca.ca_hpa, nca.ca_hpasz);
! 282:
! 283: if ((error = pdc_call((iodcio_t)pdc, 0, PDC_IODC,
! 284: PDC_IODC_READ, &pdc_iodc_read, nca.ca_hpa, IODC_DATA,
! 285: &nca.ca_type, sizeof(nca.ca_type))) < 0) {
! 286: if (autoconf_verbose)
! 287: printf(">> iodc_data error %d\n", error);
! 288: continue;
! 289: }
! 290:
! 291: nca.ca_pdc_iodc_read = &pdc_iodc_read;
! 292: nca.ca_name = hppa_mod_info(nca.ca_type.iodc_type,
! 293: nca.ca_type.iodc_sv_model);
! 294:
! 295: if (autoconf_verbose) {
! 296: printf(">> probing: flags %b bc %d/%d/%d/%d/%d/%d ",
! 297: nca.ca_dp.dp_flags, PZF_BITS,
! 298: nca.ca_dp.dp_bc[0], nca.ca_dp.dp_bc[1],
! 299: nca.ca_dp.dp_bc[2], nca.ca_dp.dp_bc[3],
! 300: nca.ca_dp.dp_bc[4], nca.ca_dp.dp_bc[5]);
! 301: printf("mod %x hpa %lx type %x sv %x\n",
! 302: nca.ca_dp.dp_mod, nca.ca_hpa,
! 303: nca.ca_type.iodc_type, nca.ca_type.iodc_sv_model);
! 304: }
! 305:
! 306: config_found_sm(self, &nca, mbprint, mbsubmatch);
! 307: }
! 308: }
! 309:
! 310: const struct hppa_mod_info hppa_knownmods[] = {
! 311: #include <hppa/dev/cpudevs_data.h>
! 312: };
! 313:
! 314: const char *
! 315: hppa_mod_info(type, sv)
! 316: int type, sv;
! 317: {
! 318: const struct hppa_mod_info *mi;
! 319: static char fakeid[32];
! 320:
! 321: for (mi = hppa_knownmods; mi->mi_type >= 0 &&
! 322: (mi->mi_type != type || mi->mi_sv != sv); mi++);
! 323:
! 324: if (mi->mi_type < 0) {
! 325: snprintf(fakeid, sizeof fakeid, "type %x, sv %x", type, sv);
! 326: return fakeid;
! 327: } else
! 328: return mi->mi_name;
! 329: }
! 330:
! 331: void
! 332: device_register(struct device *dev, void *aux)
! 333: {
! 334: #if NPCI > 0
! 335: extern struct cfdriver pci_cd;
! 336: #endif
! 337: struct confargs *ca = aux;
! 338: char *basename;
! 339: static struct device *elder = NULL;
! 340:
! 341: if (bootdv != NULL)
! 342: return; /* We already have a winner */
! 343:
! 344: #if NPCI > 0
! 345: if (dev->dv_parent &&
! 346: dev->dv_parent->dv_cfdata->cf_driver == &pci_cd) {
! 347: struct pci_attach_args *pa = aux;
! 348: pcireg_t addr;
! 349: int reg;
! 350:
! 351: for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {
! 352: addr = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
! 353: if (PCI_MAPREG_TYPE(addr) == PCI_MAPREG_TYPE_IO)
! 354: addr = PCI_MAPREG_IO_ADDR(addr);
! 355: else
! 356: addr = PCI_MAPREG_MEM_ADDR(addr);
! 357:
! 358: if (addr == (pcireg_t)PAGE0->mem_boot.pz_hpa) {
! 359: elder = dev;
! 360: break;
! 361: }
! 362: }
! 363: } else
! 364: #endif
! 365: if (ca->ca_hpa == (hppa_hpa_t)PAGE0->mem_boot.pz_hpa) {
! 366: /*
! 367: * If hpa matches, the only thing we know is that the
! 368: * booted device is either this one or one of its children.
! 369: * And the children will not necessarily have the correct
! 370: * hpa value.
! 371: * Save this elder for now.
! 372: */
! 373: elder = dev;
! 374: } else if (elder == NULL) {
! 375: return; /* not the device we booted from */
! 376: }
! 377:
! 378: /*
! 379: * Unfortunately, we can not match on pz_class vs dv_class on
! 380: * older snakes netbooting using the rbootd protocol.
! 381: * In this case, we'll end up with pz_class == PCL_RANDOM...
! 382: * Instead, trust the device class from what the kernel attached
! 383: * now...
! 384: */
! 385: switch (dev->dv_class) {
! 386: case DV_IFNET:
! 387: /*
! 388: * Netboot is the top elder
! 389: */
! 390: if (elder == dev) {
! 391: bootdv = dev;
! 392: }
! 393: return;
! 394: case DV_DISK:
! 395: if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_RANDOM)
! 396: return;
! 397: break;
! 398: case DV_TAPE:
! 399: if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_SEQU)
! 400: return;
! 401: break;
! 402: default:
! 403: /* No idea what we were booted from, but better ask the user */
! 404: return;
! 405: }
! 406:
! 407: /*
! 408: * If control goes here, we are booted from a block device and we
! 409: * matched a block device.
! 410: */
! 411: basename = dev->dv_cfdata->cf_driver->cd_name;
! 412:
! 413: /*
! 414: * We only grok SCSI boot currently. Match on proper device hierarchy,
! 415: * name and unit/lun values.
! 416: */
! 417: #if NCD > 0 || NSD > 0 || NST > 0
! 418: if (strcmp(basename, "sd") == 0 || strcmp(basename, "cd") == 0 ||
! 419: strcmp(basename, "st") == 0) {
! 420: struct scsi_attach_args *sa = aux;
! 421: struct scsi_link *sl = sa->sa_sc_link;
! 422:
! 423: /*
! 424: * sd/st/cd is attached to scsibus which is attached to
! 425: * the controller. Hence the grandparent here should be
! 426: * the elder.
! 427: */
! 428: if (dev->dv_parent == NULL ||
! 429: dev->dv_parent->dv_parent != elder) {
! 430: return;
! 431: }
! 432:
! 433: /*
! 434: * And now check for proper target and lun values
! 435: */
! 436: if (sl->target == PAGE0->mem_boot.pz_layers[0] &&
! 437: sl->lun == PAGE0->mem_boot.pz_layers[1]) {
! 438: bootdv = dev;
! 439: }
! 440: }
! 441: #endif
! 442: }
! 443:
! 444: /*
! 445: * cpu_configure:
! 446: * called at boot time, configure all devices on system
! 447: */
! 448: void
! 449: cpu_configure(void)
! 450: {
! 451: splhigh();
! 452: if (config_rootfound("mainbus", "mainbus") == NULL)
! 453: panic("no mainbus found");
! 454:
! 455: cpu_intr_init();
! 456: spl0();
! 457:
! 458: print_devpath("bootpath", &PAGE0->mem_boot);
! 459:
! 460: if (cold_hook)
! 461: (*cold_hook)(HPPA_COLD_HOT);
! 462:
! 463: #ifdef USELEDS
! 464: timeout_set(&heartbeat_tmo, heartbeat, NULL);
! 465: heartbeat(NULL);
! 466: #endif
! 467: cold = 0;
! 468: }
! 469:
! 470: void
! 471: diskconf(void)
! 472: {
! 473: setroot(bootdv, 0, RB_USERREQ);
! 474: dumpconf();
! 475: }
! 476:
! 477: struct nam2blk nam2blk[] = {
! 478: { "rd", 3 },
! 479: { "sd", 4 },
! 480: { "st", 5 },
! 481: { "cd", 6 },
! 482: { "fd", 7 },
! 483: { "wd", 8 },
! 484: { NULL, -1 }
! 485: };
CVSweb