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
prom_memory_ihandle(void)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
prom_allocate_phys(size_t size,uint_t align,unsigned long long * physaddr)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
prom_claim_phys(size_t size,unsigned long long physaddr)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
prom_free_phys(size_t size,unsigned long long physaddr)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
prom_mem_phandle(void)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
prom_phys_installed_len(void)182 prom_phys_installed_len(void)
183 {
184 	return (prom_getproplen(prom_mem_phandle(), "reg"));
185 }
186 
187 int
prom_phys_avail_len(void)188 prom_phys_avail_len(void)
189 {
190 	return (prom_getproplen(prom_mem_phandle(), "available"));
191 }
192 
193 int
prom_phys_installed(caddr_t prop)194 prom_phys_installed(caddr_t prop)
195 {
196 	return (prom_getprop(prom_mem_phandle(), "reg", prop));
197 }
198 
199 int
prom_phys_avail(caddr_t prop)200 prom_phys_avail(caddr_t prop)
201 {
202 	return (prom_getprop(prom_mem_phandle(), "available", prop));
203 }
204