17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5986fd29aSsetje * Common Development and Distribution License (the "License"). 6986fd29aSsetje * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*e7cbe64fSgw25295 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/cpr.h> 297c478bd9Sstevel@tonic-gate #include <sys/promimpl.h> 307c478bd9Sstevel@tonic-gate #include "cprboot.h" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate 33986fd29aSsetje static ihandle_t cb_rih; 34986fd29aSsetje static pnode_t chosen; 35986fd29aSsetje 36986fd29aSsetje static int statefile_special; 37986fd29aSsetje 387c478bd9Sstevel@tonic-gate static int reset_input = 0; 397c478bd9Sstevel@tonic-gate static char kbd_input[] = "keyboard input"; 407c478bd9Sstevel@tonic-gate static char null_input[] = "\" /nulldev\" input"; 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * Ask prom to open a disk file given either the OBP device path, or the 447c478bd9Sstevel@tonic-gate * device path representing the target drive/partition and the fs-relative 457c478bd9Sstevel@tonic-gate * path of the file. Handle file pathnames with or without leading '/'. 467c478bd9Sstevel@tonic-gate * if fs points to a null char, it indicates that we are opening a device. 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate int 49986fd29aSsetje cpr_statefile_open(char *path, char *fs_dev) 507c478bd9Sstevel@tonic-gate { 51986fd29aSsetje int plen, dlen; 527c478bd9Sstevel@tonic-gate int handle; 53986fd29aSsetje char fs_pkg[OBP_MAXPATHLEN]; 54986fd29aSsetje char fs_name[OBP_MAXDRVNAME]; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* 577c478bd9Sstevel@tonic-gate * instead of using specialstate, we use fs as the flag 587c478bd9Sstevel@tonic-gate */ 59986fd29aSsetje if (*fs_dev == '\0') { /* device open */ 60986fd29aSsetje statefile_special = 1; 617c478bd9Sstevel@tonic-gate handle = prom_open(path); 627c478bd9Sstevel@tonic-gate /* IEEE1275 prom_open returns 0 on failure; we return -1 */ 637c478bd9Sstevel@tonic-gate return (handle ? handle : -1); 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 67986fd29aSsetje * No cif for $open-package, so we have to use interpret 687c478bd9Sstevel@tonic-gate */ 69986fd29aSsetje if (prom_getprop(chosen, "fs-package", fs_pkg) == -1) { 70986fd29aSsetje prom_printf("Missing fs-package name\n"); 71986fd29aSsetje return (-1); 72986fd29aSsetje } 73986fd29aSsetje plen = prom_strlen(fs_pkg); 74986fd29aSsetje dlen = prom_strlen(fs_dev); 75986fd29aSsetje prom_interpret("$open-package swap l!", plen, (uintptr_t)fs_pkg, 76986fd29aSsetje dlen, (uintptr_t)fs_dev, (uintptr_t)&cb_rih); 77986fd29aSsetje if (cb_rih == OBP_BADNODE || cb_rih == 0) { 78986fd29aSsetje prom_printf("Can't open %s\n", fs_pkg); 79986fd29aSsetje return (-1); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate 82*e7cbe64fSgw25295 if (volname) { 83*e7cbe64fSgw25295 return (cpr_fs_volopen(volname)); 84*e7cbe64fSgw25295 } 85*e7cbe64fSgw25295 867c478bd9Sstevel@tonic-gate /* 87986fd29aSsetje * Prepend '/' if it's not there already 887c478bd9Sstevel@tonic-gate */ 89986fd29aSsetje if (*path != '/') { 90986fd29aSsetje (void) prom_sprintf(fs_name, "/%s", path); 91986fd29aSsetje return (cpr_fs_open(fs_name)); 92986fd29aSsetje } else 93986fd29aSsetje return (cpr_fs_open(path)); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 96986fd29aSsetje /* 97986fd29aSsetje * Mount root fs so we can read statefile, etc 98986fd29aSsetje * 99986fd29aSsetje * sets global 100986fd29aSsetje * cb_rih 101986fd29aSsetje */ 102986fd29aSsetje int 103986fd29aSsetje cb_mountroot() 104986fd29aSsetje { 105986fd29aSsetje 106986fd29aSsetje chosen = prom_chosennode(); 107986fd29aSsetje if (chosen == OBP_BADNODE) { 108986fd29aSsetje prom_printf("Missing chosen node\n"); 109986fd29aSsetje return (ERR); 110986fd29aSsetje } 111986fd29aSsetje if (prom_getprop(chosen, "bootfs", (caddr_t)&cb_rih) == -1) { 112986fd29aSsetje prom_printf("Missing bootfs ihandle\n"); 113986fd29aSsetje return (ERR); 114986fd29aSsetje } 115986fd29aSsetje return (0); 116986fd29aSsetje } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 119986fd29aSsetje * Unmount root 120986fd29aSsetje */ 121986fd29aSsetje int 122986fd29aSsetje cb_unmountroot() 123986fd29aSsetje { 124986fd29aSsetje (void) prom_close(cb_rih); 125986fd29aSsetje cb_rih = OBP_BADNODE; 126986fd29aSsetje return (0); 127986fd29aSsetje } 128986fd29aSsetje 129*e7cbe64fSgw25295 int 130*e7cbe64fSgw25295 cpr_fs_volopen(char *path) 131*e7cbe64fSgw25295 { 132*e7cbe64fSgw25295 133*e7cbe64fSgw25295 CB_VENTRY(cpr_fs_volopen); 134*e7cbe64fSgw25295 135*e7cbe64fSgw25295 if (cb_rih == OBP_BADNODE) 136*e7cbe64fSgw25295 return (-1); 137*e7cbe64fSgw25295 return (prom_volopen(cb_rih, path)); 138*e7cbe64fSgw25295 } 139*e7cbe64fSgw25295 140986fd29aSsetje /* 141986fd29aSsetje * Ask prom to open a disk file. 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate int 144986fd29aSsetje cpr_fs_open(char *path) 1457c478bd9Sstevel@tonic-gate { 1467c478bd9Sstevel@tonic-gate 147986fd29aSsetje CB_VENTRY(cpr_fs_open); 148986fd29aSsetje 149986fd29aSsetje if (cb_rih == OBP_BADNODE) 150986fd29aSsetje return (-1); 151986fd29aSsetje return (prom_fopen(cb_rih, path)); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* 156986fd29aSsetje * Direct read if using block special, 157986fd29aSsetje * otherwise use fs read 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate int 1607c478bd9Sstevel@tonic-gate cpr_read(int fd, caddr_t buf, size_t len) 1617c478bd9Sstevel@tonic-gate { 162*e7cbe64fSgw25295 if (!statefile_special || volname) 163986fd29aSsetje return (cpr_fs_read(fd, buf, len)); 164986fd29aSsetje else 1657c478bd9Sstevel@tonic-gate return (prom_read(fd, buf, len, 0, 0)); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate int 170986fd29aSsetje cpr_fs_read(int fd, caddr_t buf, int len) 1717c478bd9Sstevel@tonic-gate { 172986fd29aSsetje if (cb_rih == OBP_BADNODE) 173986fd29aSsetje return (-1); 174986fd29aSsetje return (prom_fread(cb_rih, fd, buf, len)); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate int 179986fd29aSsetje cpr_fs_close(int fd) 1807c478bd9Sstevel@tonic-gate { 181986fd29aSsetje CB_VPRINTF(("cpr_fs_close 0x%x\n", fd)); 182986fd29aSsetje 183986fd29aSsetje if (cb_rih == OBP_BADNODE) 184986fd29aSsetje return (-1); 185986fd29aSsetje prom_fclose(cb_rih, fd); 186986fd29aSsetje return (0); 187986fd29aSsetje } 188986fd29aSsetje 189986fd29aSsetje int 190986fd29aSsetje cpr_fs_seek(int fd, offset_t off) 191986fd29aSsetje { 192986fd29aSsetje if (cb_rih == OBP_BADNODE) 193986fd29aSsetje return (-1); 194986fd29aSsetje return (prom_fseek(cb_rih, fd, off)); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate int 1997c478bd9Sstevel@tonic-gate cpr_statefile_close(int fd) 2007c478bd9Sstevel@tonic-gate { 201986fd29aSsetje if (statefile_special) { 202986fd29aSsetje statefile_special = 0; 2037c478bd9Sstevel@tonic-gate return (prom_close(fd)); 204986fd29aSsetje } else 205986fd29aSsetje return (cpr_fs_close(fd)); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate void 2107c478bd9Sstevel@tonic-gate cb_spin(void) 2117c478bd9Sstevel@tonic-gate { 2127c478bd9Sstevel@tonic-gate static int spindex = 0; 2137c478bd9Sstevel@tonic-gate static char *spin_pairs[] = { "|\b", "/\b", "-\b", "\\\b" }; 2147c478bd9Sstevel@tonic-gate const size_t nspin_pairs = sizeof (spin_pairs) / sizeof (spin_pairs[0]); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate prom_printf(spin_pairs[spindex]); 2177c478bd9Sstevel@tonic-gate spindex = (spindex + 1) % nspin_pairs; 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate /* 2227c478bd9Sstevel@tonic-gate * translate vaddr to phys page number 2237c478bd9Sstevel@tonic-gate */ 2247c478bd9Sstevel@tonic-gate pfn_t 2257c478bd9Sstevel@tonic-gate cpr_vatopfn(caddr_t vaddr) 2267c478bd9Sstevel@tonic-gate { 2277c478bd9Sstevel@tonic-gate physaddr_t paddr; 2287c478bd9Sstevel@tonic-gate int valid, mode; 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate (void) prom_translate_virt(vaddr, &valid, &paddr, &mode); 2317c478bd9Sstevel@tonic-gate if (valid != -1) 2327c478bd9Sstevel@tonic-gate return (PFN_INVALID); 2337c478bd9Sstevel@tonic-gate return (paddr >> MMU_PAGESHIFT); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * unmap virt, then map virt to new phys; 2397c478bd9Sstevel@tonic-gate * see remap definition below 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate int 2427c478bd9Sstevel@tonic-gate prom_remap(size_t size, caddr_t virt, physaddr_t phys) 2437c478bd9Sstevel@tonic-gate { 2447c478bd9Sstevel@tonic-gate ihandle_t immu; 2457c478bd9Sstevel@tonic-gate cell_t ci[8]; 2467c478bd9Sstevel@tonic-gate int rv; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate immu = prom_mmu_ihandle(); 2497c478bd9Sstevel@tonic-gate if (immu == (ihandle_t)-1) 2507c478bd9Sstevel@tonic-gate return (ERR); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate ci[0] = p1275_ptr2cell("call-method"); /* Service name */ 2537c478bd9Sstevel@tonic-gate ci[1] = (cell_t)5; /* #argument cells */ 2547c478bd9Sstevel@tonic-gate ci[2] = (cell_t)0; /* #result cells */ 2557c478bd9Sstevel@tonic-gate ci[3] = p1275_ptr2cell("remap"); /* Arg1: Method name */ 2567c478bd9Sstevel@tonic-gate ci[4] = p1275_ihandle2cell(immu); /* Arg2: memory ihandle */ 2577c478bd9Sstevel@tonic-gate ci[5] = p1275_size2cell(size); /* remap arg0 */ 2587c478bd9Sstevel@tonic-gate ci[6] = p1275_ptr2cell(virt); /* remap arg1 */ 2597c478bd9Sstevel@tonic-gate ci[7] = p1275_ull2cell_low(phys); /* remap arg2 */ 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate promif_preprom(); 2627c478bd9Sstevel@tonic-gate rv = p1275_cif_handler(ci); 2637c478bd9Sstevel@tonic-gate promif_postprom(); 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate if (rv) 2667c478bd9Sstevel@tonic-gate return (rv); /* Service "call-method" failed */ 2677c478bd9Sstevel@tonic-gate return (0); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* 2727c478bd9Sstevel@tonic-gate * install remap definition in /virtual-memory node; 2737c478bd9Sstevel@tonic-gate * used for replacing a virt->phys mapping in one promif call; 2747c478bd9Sstevel@tonic-gate * this needs to be atomic from the client's perspective to 2757c478bd9Sstevel@tonic-gate * avoid faults while relocating client text. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate void 2787c478bd9Sstevel@tonic-gate install_remap(void) 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate static char remap_def[] = 2817c478bd9Sstevel@tonic-gate "\" /virtual-memory\" find-device " 2827c478bd9Sstevel@tonic-gate ": remap ( phys.lo virt size -- )" 2837c478bd9Sstevel@tonic-gate " 2dup unmap ( phys.lo virt size )" 2847c478bd9Sstevel@tonic-gate " 0 -rot -1 map ( ) ; " 2857c478bd9Sstevel@tonic-gate "device-end"; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate prom_interpret(remap_def, 0, 0, 0, 0, 0); 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * allocate virt and phys space without any mapping; 2937c478bd9Sstevel@tonic-gate * stores virt and phys addrs at *vap and *pap 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate int 2967c478bd9Sstevel@tonic-gate cb_alloc(size_t size, uint_t align, caddr_t *vap, physaddr_t *pap) 2977c478bd9Sstevel@tonic-gate { 2987c478bd9Sstevel@tonic-gate physaddr_t phys; 2997c478bd9Sstevel@tonic-gate caddr_t virt; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate virt = prom_allocate_virt(align, (size_t)align); 3027c478bd9Sstevel@tonic-gate if (virt == (caddr_t)-1) 3037c478bd9Sstevel@tonic-gate return (ERR); 3047c478bd9Sstevel@tonic-gate if (prom_allocate_phys(size, align, &phys) == -1) { 3057c478bd9Sstevel@tonic-gate prom_free_virt(size, virt); 3067c478bd9Sstevel@tonic-gate return (ERR); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate *vap = virt; 3107c478bd9Sstevel@tonic-gate *pap = phys; 3117c478bd9Sstevel@tonic-gate return (0); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate static int 316fa9e4066Sahrens get_intprop(pnode_t node, caddr_t prop, void *dst) 3177c478bd9Sstevel@tonic-gate { 3187c478bd9Sstevel@tonic-gate int len, glen; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate len = sizeof (uint_t); 3217c478bd9Sstevel@tonic-gate glen = prom_getprop(node, prop, dst); 3227c478bd9Sstevel@tonic-gate if (glen != len) 3237c478bd9Sstevel@tonic-gate return (ERR); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate return (0); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate /* 3307c478bd9Sstevel@tonic-gate * find cpu node for the boot processor 3317c478bd9Sstevel@tonic-gate * 3327c478bd9Sstevel@tonic-gate * sets globals: 3337c478bd9Sstevel@tonic-gate * cb_mid 3347c478bd9Sstevel@tonic-gate */ 335fa9e4066Sahrens static pnode_t 3367c478bd9Sstevel@tonic-gate get_cpu_node(void) 3377c478bd9Sstevel@tonic-gate { 3387c478bd9Sstevel@tonic-gate static char *props[] = { "upa-portid", "portid", NULL }; 339fa9e4066Sahrens pnode_t node; 3407c478bd9Sstevel@tonic-gate char *str, *name, **propp; 3417c478bd9Sstevel@tonic-gate uint_t cpu_id; 3427c478bd9Sstevel@tonic-gate int err; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate str = "get_cpu_node"; 3457c478bd9Sstevel@tonic-gate name = "cpu"; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate cb_mid = getmid(); 3487c478bd9Sstevel@tonic-gate for (node = prom_rootnode(); ; node = prom_nextnode(node)) { 3497c478bd9Sstevel@tonic-gate node = prom_findnode_bydevtype(node, name); 3507c478bd9Sstevel@tonic-gate if (node == OBP_NONODE) { 3517c478bd9Sstevel@tonic-gate prom_printf("\n%s: cant find node for devtype \"%s\"\n", 3527c478bd9Sstevel@tonic-gate str, name); 3537c478bd9Sstevel@tonic-gate break; 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate cpu_id = (uint_t)-1; 3577c478bd9Sstevel@tonic-gate for (propp = props; *propp; propp++) { 3587c478bd9Sstevel@tonic-gate err = get_intprop(node, *propp, &cpu_id); 3597c478bd9Sstevel@tonic-gate CB_VPRINTF((" cpu node 0x%x, " 3607c478bd9Sstevel@tonic-gate "prop \"%s\", cpu_id %d\n", 3617c478bd9Sstevel@tonic-gate node, *propp, (int)cpu_id)); 3627c478bd9Sstevel@tonic-gate if (err == 0) 3637c478bd9Sstevel@tonic-gate break; 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (cpu_id == cb_mid) 3677c478bd9Sstevel@tonic-gate return (node); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate return (OBP_NONODE); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * lookup prom properties 3767c478bd9Sstevel@tonic-gate * 3777c478bd9Sstevel@tonic-gate * sets globals: 3787c478bd9Sstevel@tonic-gate * cb_dents 3797c478bd9Sstevel@tonic-gate * cb_clock_freq 3807c478bd9Sstevel@tonic-gate * cpu_delay 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate int 3837c478bd9Sstevel@tonic-gate cb_get_props(void) 3847c478bd9Sstevel@tonic-gate { 3857c478bd9Sstevel@tonic-gate uint_t clock_mhz; 386fa9e4066Sahrens pnode_t node; 3877c478bd9Sstevel@tonic-gate struct cb_props *cbp; 3887c478bd9Sstevel@tonic-gate static struct cb_props cpu_data[] = { 3897c478bd9Sstevel@tonic-gate "#dtlb-entries", &cb_dents, 3907c478bd9Sstevel@tonic-gate "clock-frequency", &cb_clock_freq, 3917c478bd9Sstevel@tonic-gate NULL, NULL, 3927c478bd9Sstevel@tonic-gate }; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate CB_VENTRY(cb_get_props); 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate node = get_cpu_node(); 3977c478bd9Sstevel@tonic-gate if (node == OBP_NONODE) 3987c478bd9Sstevel@tonic-gate return (ERR); 3997c478bd9Sstevel@tonic-gate for (cbp = cpu_data; cbp->prop; cbp++) { 4007c478bd9Sstevel@tonic-gate if (get_intprop(node, cbp->prop, cbp->datap)) { 4017c478bd9Sstevel@tonic-gate prom_printf("\n%s: getprop error, " 4027c478bd9Sstevel@tonic-gate "node 0x%x, prop \"%s\"\n", 4037c478bd9Sstevel@tonic-gate prog, node, cbp->prop); 4047c478bd9Sstevel@tonic-gate return (ERR); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate CB_VPRINTF((" \"%s\" = 0x%x\n", 4077c478bd9Sstevel@tonic-gate cbp->prop, *cbp->datap)); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* 4117c478bd9Sstevel@tonic-gate * setup cpu_delay for cb_usec_wait 4127c478bd9Sstevel@tonic-gate */ 4137c478bd9Sstevel@tonic-gate clock_mhz = (cb_clock_freq + 500000) / 1000000; 4147c478bd9Sstevel@tonic-gate cpu_delay = clock_mhz - 7; 4157c478bd9Sstevel@tonic-gate CB_VPRINTF((" clock_mhz %d, cpu_delay %d\n", 4167c478bd9Sstevel@tonic-gate clock_mhz, cpu_delay)); 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate return (0); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* 4237c478bd9Sstevel@tonic-gate * map-in data pages 4247c478bd9Sstevel@tonic-gate * size should fit tte_bit.sz 4257c478bd9Sstevel@tonic-gate * rw should be 0 or TTE_HWWR_INT 4267c478bd9Sstevel@tonic-gate */ 4277c478bd9Sstevel@tonic-gate void 4287c478bd9Sstevel@tonic-gate cb_mapin(caddr_t vaddr, pfn_t ppn, uint_t size, uint_t rw, uint_t dtlb_index) 4297c478bd9Sstevel@tonic-gate { 4307c478bd9Sstevel@tonic-gate tte_t tte; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(size) | 4337c478bd9Sstevel@tonic-gate TTE_PFN_INTHI(ppn); 4347c478bd9Sstevel@tonic-gate tte.tte_intlo = TTE_PFN_INTLO(ppn) | TTE_LCK_INT | 4357c478bd9Sstevel@tonic-gate TTE_CP_INT | TTE_CV_INT | TTE_PRIV_INT | rw; 4367c478bd9Sstevel@tonic-gate set_dtlb_entry(dtlb_index, vaddr, &tte); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate static char * 4417c478bd9Sstevel@tonic-gate prom_strstr(char *string, char *substr) 4427c478bd9Sstevel@tonic-gate { 4437c478bd9Sstevel@tonic-gate char *strp, *subp, *tmp, c; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate if (substr == NULL || *substr == '\0') 4467c478bd9Sstevel@tonic-gate return (string); 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate strp = string; 4497c478bd9Sstevel@tonic-gate subp = substr; 4507c478bd9Sstevel@tonic-gate c = *subp; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate while (*strp) { 4537c478bd9Sstevel@tonic-gate if (*strp++ == c) { 4547c478bd9Sstevel@tonic-gate tmp = strp; 4557c478bd9Sstevel@tonic-gate while ((c = *++subp) == *strp++ && c) 4567c478bd9Sstevel@tonic-gate ; 4577c478bd9Sstevel@tonic-gate if (c == '\0') 4587c478bd9Sstevel@tonic-gate return (tmp - 1); 4597c478bd9Sstevel@tonic-gate strp = tmp; 4607c478bd9Sstevel@tonic-gate subp = substr; 4617c478bd9Sstevel@tonic-gate c = *subp; 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate return (NULL); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate static void 4707c478bd9Sstevel@tonic-gate cb_set_idev(char *istr) 4717c478bd9Sstevel@tonic-gate { 4727c478bd9Sstevel@tonic-gate if (reset_input) { 4737c478bd9Sstevel@tonic-gate prom_interpret(istr, 0, 0, 0, 0, 0); 4747c478bd9Sstevel@tonic-gate CB_VPRINTF(("\ncb_set_idev: reset with [%s]\n", istr)); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate /* 4807c478bd9Sstevel@tonic-gate * workaround for USB keyboard: 4817c478bd9Sstevel@tonic-gate * USB DMA activity has been known to corrupt kernel pages while cprboot 4827c478bd9Sstevel@tonic-gate * is restoring them. to quiesce the USB chip, we craft a "null" device 4837c478bd9Sstevel@tonic-gate * and temporarily use that as the prom's input device. this effectively 4847c478bd9Sstevel@tonic-gate * disables the USB keyboard until the cpr module restores the original 4857c478bd9Sstevel@tonic-gate * prom and a kernel driver re-inits and takes-over control of USB. 4867c478bd9Sstevel@tonic-gate * 4877c478bd9Sstevel@tonic-gate * may set globals: 4887c478bd9Sstevel@tonic-gate * reset_input 4897c478bd9Sstevel@tonic-gate */ 4907c478bd9Sstevel@tonic-gate int 4917c478bd9Sstevel@tonic-gate cb_usb_setup(void) 4927c478bd9Sstevel@tonic-gate { 4937c478bd9Sstevel@tonic-gate char sp[OBP_MAXPATHLEN]; 4947c478bd9Sstevel@tonic-gate static char cb_nulldev[] = { 4957c478bd9Sstevel@tonic-gate "\" /\" select-dev " 4967c478bd9Sstevel@tonic-gate "new-device " 4977c478bd9Sstevel@tonic-gate "\" nulldev\" device-name " 4987c478bd9Sstevel@tonic-gate ": read 2drop -2 ; " 4997c478bd9Sstevel@tonic-gate ": open true ; " 5007c478bd9Sstevel@tonic-gate ": close ; " 5017c478bd9Sstevel@tonic-gate ": install-abort ; " 5027c478bd9Sstevel@tonic-gate ": remove-abort ; " 5037c478bd9Sstevel@tonic-gate ": write 2drop 0 ; " 5047c478bd9Sstevel@tonic-gate ": restore ; " 5057c478bd9Sstevel@tonic-gate "finish-device " 5067c478bd9Sstevel@tonic-gate "unselect-dev" 5077c478bd9Sstevel@tonic-gate }; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate CB_VENTRY(cb_usb_setup); 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate bzero(sp, sizeof (sp)); 5127c478bd9Sstevel@tonic-gate prom_interpret("stdin @ ihandle>devname swap -rot move", 5137c478bd9Sstevel@tonic-gate (uintptr_t)sp, 0, 0, 0, 0); 5147c478bd9Sstevel@tonic-gate if (prom_strstr(sp, "usb") && prom_strstr(sp, "keyboard")) { 5157c478bd9Sstevel@tonic-gate prom_interpret(cb_nulldev, 0, 0, 0, 0, 0); 5167c478bd9Sstevel@tonic-gate reset_input = 1; 5177c478bd9Sstevel@tonic-gate cb_set_idev(null_input); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate return (0); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* 5257c478bd9Sstevel@tonic-gate * switch input to keyboard before entering the prom, and switch to the 5267c478bd9Sstevel@tonic-gate * crafted nulldev after returning from the prom. this occurs only when 5277c478bd9Sstevel@tonic-gate * stdinpath is a USB keyboard; entering the prom is usually done only 5287c478bd9Sstevel@tonic-gate * for debugging purposes - see check_halt() and above DMA comment. 5297c478bd9Sstevel@tonic-gate */ 5307c478bd9Sstevel@tonic-gate void 5317c478bd9Sstevel@tonic-gate cb_enter_mon(void) 5327c478bd9Sstevel@tonic-gate { 5337c478bd9Sstevel@tonic-gate cb_set_idev(kbd_input); 5347c478bd9Sstevel@tonic-gate prom_enter_mon(); 5357c478bd9Sstevel@tonic-gate cb_set_idev(null_input); 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate /* 5407c478bd9Sstevel@tonic-gate * similar to above before exiting to the prom 5417c478bd9Sstevel@tonic-gate */ 5427c478bd9Sstevel@tonic-gate void 5437c478bd9Sstevel@tonic-gate cb_exit_to_mon(void) 5447c478bd9Sstevel@tonic-gate { 5457c478bd9Sstevel@tonic-gate cb_set_idev(kbd_input); 5467c478bd9Sstevel@tonic-gate prom_exit_to_mon(); 5477c478bd9Sstevel@tonic-gate } 548