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 #include <sys/promif.h> 30 #include <sys/promimpl.h> 31 32 /* 33 * This allocator has SMCC-OBP-like semantics associated with it. 34 * Specifically, the alignment value specifies both a physical 35 * and virtual alignment. If virthint is zero, a suitable virt 36 * is chosen. In either case, align is not ignored. 37 * 38 * This routine returns NULL on failure. 39 * This routine is suitable for (the given semantics) machines with 40 * a 2-cell physical address. 41 * 42 * Memory allocated with prom_alloc can be freed with prom_free. 43 * 44 * The generic allocator is prom_malloc. 45 * 46 */ 47 48 caddr_t 49 prom_alloc(caddr_t virthint, size_t size, u_int align) 50 { 51 52 caddr_t virt = virthint; 53 unsigned long long physaddr; 54 55 if (align == 0) 56 align = (u_int)1; 57 58 /* 59 * First, allocate or claim the virtual address space. 60 * In either case, after this code, "virt" is the chosen address. 61 */ 62 if (virthint == 0) { 63 virt = prom_allocate_virt(align, size); 64 if (virt == (caddr_t)-1) 65 return ((caddr_t)0); 66 } else { 67 if (prom_claim_virt(size, virthint) == (caddr_t)-1) 68 return ((caddr_t)0); 69 } 70 71 /* 72 * Next, allocate the physical address space, at the specified 73 * physical alignment (or 1 byte alignment, if none specified) 74 */ 75 76 if (prom_allocate_phys(size, align, &physaddr) == -1) { 77 78 /* 79 * Request failed, free virtual address space and return. 80 */ 81 prom_free_virt(size, virt); 82 return ((caddr_t)0); 83 } 84 85 /* 86 * Next, create a mapping from the physical to virtual address, 87 * using a default "mode". 88 */ 89 90 if (prom_map_phys(-1, size, virt, physaddr) == -1) { 91 92 /* 93 * The call failed; release the physical and virtual 94 * addresses allocated or claimed, and return. 95 */ 96 97 prom_free_virt(size, virt); 98 prom_free_phys(size, physaddr); 99 return ((caddr_t)0); 100 } 101 return (virt); 102 } 103 104 /* 105 * This is the generic client interface to "claim" memory. 106 * These two routines belong in the common directory. 107 */ 108 caddr_t 109 prom_malloc(caddr_t virt, size_t size, u_int align) 110 { 111 cell_t ci[7]; 112 int rv; 113 114 ci[0] = p1275_ptr2cell("claim"); /* Service name */ 115 ci[1] = (cell_t)3; /* #argument cells */ 116 ci[2] = (cell_t)1; /* #result cells */ 117 ci[3] = p1275_ptr2cell(virt); /* Arg1: virt */ 118 ci[4] = p1275_size2cell(size); /* Arg2: size */ 119 ci[5] = p1275_uint2cell(align); /* Arg3: align */ 120 121 promif_preprom(); 122 rv = p1275_cif_handler(&ci); 123 promif_postprom(); 124 125 if (rv == 0) 126 return ((caddr_t)p1275_cell2ptr(ci[6])); /* Res1: base */ 127 return ((caddr_t)-1); 128 } 129 130 131 void 132 prom_free(caddr_t virt, size_t size) 133 { 134 cell_t ci[5]; 135 136 ci[0] = p1275_ptr2cell("release"); /* Service name */ 137 ci[1] = (cell_t)2; /* #argument cells */ 138 ci[2] = (cell_t)0; /* #result cells */ 139 ci[3] = p1275_ptr2cell(virt); /* Arg1: virt */ 140 ci[4] = p1275_size2cell(size); /* Arg2: size */ 141 142 promif_preprom(); 143 (void) p1275_cif_handler(&ci); 144 promif_postprom(); 145 } 146