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