1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This file contains platform-dependent memory support routines, 30 * suitable for memory methods with 2-cell physical addresses. 31 * Use of these routines makes the caller platform-dependent, 32 * since the caller assumes knowledge of the physical layout of 33 * the machines address space. Generic programs should use the 34 * standard client interface memory allocators. 35 */ 36 37 #include <sys/promif.h> 38 #include <sys/promimpl.h> 39 40 ihandle_t 41 prom_memory_ihandle(void) 42 { 43 static ihandle_t imemory; 44 45 if (imemory != (ihandle_t)0) 46 return (imemory); 47 48 if (prom_getproplen(prom_chosennode(), "memory") != sizeof (ihandle_t)) 49 return (imemory = (ihandle_t)-1); 50 51 (void) prom_getprop(prom_chosennode(), "memory", (caddr_t)(&imemory)); 52 return (imemory); 53 } 54 55 /* 56 * Allocate physical memory, unmapped and possibly aligned. 57 * Returns 0: Success; Non-zero: failure. 58 * Returns *physaddr only if successful. 59 * 60 * This routine is suitable for platforms with 2-cell physical addresses 61 * and a single size cell in the "memory" node. 62 */ 63 int 64 prom_allocate_phys(size_t size, uint_t align, unsigned long long *physaddr) 65 { 66 cell_t ci[10]; 67 int rv; 68 ihandle_t imemory = prom_memory_ihandle(); 69 70 if ((imemory == (ihandle_t)-1)) 71 return (-1); 72 73 if (align == 0) 74 align = (uint_t)1; 75 76 ci[0] = p1275_ptr2cell("call-method"); /* Service name */ 77 ci[1] = (cell_t)4; /* #argument cells */ 78 ci[2] = (cell_t)3; /* #result cells */ 79 ci[3] = p1275_ptr2cell("claim"); /* Arg1: Method name */ 80 ci[4] = p1275_ihandle2cell(imemory); /* Arg2: memory ihandle */ 81 ci[5] = p1275_uint2cell(align); /* Arg3: SA1: align */ 82 ci[6] = p1275_size2cell(size); /* Arg4: SA2: size */ 83 84 promif_preprom(); 85 rv = p1275_cif_handler(&ci); 86 promif_postprom(); 87 88 if (rv != 0) 89 return (rv); 90 if (p1275_cell2int(ci[7]) != 0) /* Res1: Catch result */ 91 return (-1); 92 93 *physaddr = p1275_cells2ull(ci[8], ci[9]); 94 /* Res2: SR1: phys.hi ... Res3: SR2: phys.lo */ 95 return (0); 96 } 97 98 /* 99 * Claim a region of physical memory, unmapped. 100 * Returns 0: Success; Non-zero: failure. 101 * 102 * This routine is suitable for platforms with 2-cell physical addresses 103 * and a single size cell in the "memory" node. 104 */ 105 int 106 prom_claim_phys(size_t size, unsigned long long physaddr) 107 { 108 cell_t ci[10]; 109 int rv; 110 ihandle_t imemory = prom_memory_ihandle(); 111 112 if ((imemory == (ihandle_t)-1)) 113 return (-1); 114 115 ci[0] = p1275_ptr2cell("call-method"); /* Service name */ 116 ci[1] = (cell_t)6; /* #argument cells */ 117 ci[2] = (cell_t)1; /* #result cells */ 118 ci[3] = p1275_ptr2cell("claim"); /* Arg1: Method name */ 119 ci[4] = p1275_ihandle2cell(imemory); /* Arg2: mmu ihandle */ 120 ci[5] = 0; /* Arg3: SA1: align */ 121 ci[6] = p1275_size2cell(size); /* Arg4: SA2: len */ 122 ci[7] = p1275_ull2cell_high(physaddr); /* Arg5: SA3: phys.hi */ 123 ci[8] = p1275_ull2cell_low(physaddr); /* Arg6: SA4: phys.lo */ 124 125 promif_preprom(); 126 rv = p1275_cif_handler(&ci); 127 promif_postprom(); 128 129 if (rv != 0) 130 return (rv); 131 if (p1275_cell2int(ci[9]) != 0) /* Res1: Catch result */ 132 return (-1); 133 134 return (0); 135 } 136 137 /* 138 * Free physical memory (no unmapping is done). 139 * This routine is suitable for platforms with 2-cell physical addresses 140 * with a single size cell. 141 */ 142 void 143 prom_free_phys(size_t size, unsigned long long physaddr) 144 { 145 cell_t ci[8]; 146 ihandle_t imemory = prom_memory_ihandle(); 147 148 if ((imemory == (ihandle_t)-1)) 149 return; 150 151 ci[0] = p1275_ptr2cell("call-method"); /* Service name */ 152 ci[1] = (cell_t)5; /* #argument cells */ 153 ci[2] = (cell_t)0; /* #return cells */ 154 ci[3] = p1275_ptr2cell("release"); /* Arg1: Method name */ 155 ci[4] = p1275_ihandle2cell(imemory); /* Arg2: memory ihandle */ 156 ci[5] = p1275_size2cell(size); /* Arg3: SA1: size */ 157 ci[6] = p1275_ull2cell_high(physaddr); /* Arg4: SA2: phys.hi */ 158 ci[7] = p1275_ull2cell_low(physaddr); /* Arg5: SA3: phys.lo */ 159 160 promif_preprom(); 161 (void) p1275_cif_handler(&ci); 162 promif_postprom(); 163 } 164 165 static pnode_t 166 prom_mem_phandle(void) 167 { 168 static pnode_t pmem = 0; 169 170 if (pmem == (pnode_t)0) { 171 ihandle_t ih; 172 173 if ((ih = prom_memory_ihandle()) == (ihandle_t)-1) 174 prom_panic("Can't get memory ihandle"); 175 pmem = prom_getphandle(ih); 176 } 177 return (pmem); 178 } 179 180 181 int 182 prom_phys_installed_len(void) 183 { 184 return (prom_getproplen(prom_mem_phandle(), "reg")); 185 } 186 187 int 188 prom_phys_avail_len(void) 189 { 190 return (prom_getproplen(prom_mem_phandle(), "available")); 191 } 192 193 int 194 prom_phys_installed(caddr_t prop) 195 { 196 return (prom_getprop(prom_mem_phandle(), "reg", prop)); 197 } 198 199 int 200 prom_phys_avail(caddr_t prop) 201 { 202 return (prom_getprop(prom_mem_phandle(), "available", prop)); 203 } 204