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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/debug.h> 30 #include <sys/types.h> 31 #include <sys/param.h> 32 #include <sys/time.h> 33 #include <sys/buf.h> 34 #include <sys/errno.h> 35 #include <sys/systm.h> 36 #include <sys/conf.h> 37 #include <sys/signal.h> 38 #include <vm/page.h> 39 #include <vm/as.h> 40 #include <vm/hat.h> 41 #include <vm/seg.h> 42 #include <vm/seg_dev.h> 43 #include <vm/hat_i86.h> 44 #include <sys/ddi.h> 45 #include <sys/devops.h> 46 #include <sys/sunddi.h> 47 #include <sys/ddi_impldefs.h> 48 #include <sys/fs/snode.h> 49 #include <sys/pci.h> 50 #include <sys/vmsystm.h> 51 #include "gfx_private.h" 52 53 /* 54 * Create a dummy ddi_umem_cookie given to gfxp_devmap_umem_setup(). 55 */ 56 ddi_umem_cookie_t 57 gfxp_umem_cookie_init(caddr_t kva, size_t size) 58 { 59 struct ddi_umem_cookie *umem_cookie; 60 61 umem_cookie = kmem_zalloc(sizeof (struct ddi_umem_cookie), KM_SLEEP); 62 63 if (umem_cookie == NULL) 64 return (NULL); 65 66 umem_cookie->cvaddr = kva; 67 umem_cookie->type = KMEM_NON_PAGEABLE; 68 umem_cookie->size = size; 69 70 return ((ddi_umem_cookie_t *)umem_cookie); 71 } 72 73 void 74 gfxp_umem_cookie_destroy(ddi_umem_cookie_t cookie) 75 { 76 kmem_free(cookie, sizeof (struct ddi_umem_cookie)); 77 } 78 79 /* 80 * called by driver devmap routine to pass kernel virtual address mapping 81 * info to the framework. used only for kernel memory 82 * allocated from ddi_dma_mem_alloc(). 83 */ 84 /*ARGSUSED*/ 85 int 86 gfxp_devmap_umem_setup(devmap_cookie_t dhc, dev_info_t *dip, 87 struct devmap_callback_ctl *callbackops, ddi_umem_cookie_t cookie, 88 offset_t off, size_t len, uint_t maxprot, uint_t flags, 89 ddi_device_acc_attr_t *accattrp) 90 { 91 devmap_handle_t *dhp = (devmap_handle_t *)dhc; 92 struct ddi_umem_cookie *cp = (struct ddi_umem_cookie *)cookie; 93 94 #ifdef lint 95 dip = dip; 96 #endif 97 98 if (cookie == NULL) 99 return (DDI_FAILURE); 100 101 /* For UMEM_TRASH, this restriction is not needed */ 102 if ((off + len) > cp->size) 103 return (DDI_FAILURE); 104 105 /* 106 * First to check if this function has been called for this dhp. 107 */ 108 if (dhp->dh_flags & DEVMAP_SETUP_DONE) 109 return (DDI_FAILURE); 110 111 if ((dhp->dh_prot & dhp->dh_orig_maxprot & maxprot) != dhp->dh_prot) 112 return (DDI_FAILURE); 113 114 if (flags & DEVMAP_MAPPING_INVALID) { 115 /* 116 * If DEVMAP_MAPPING_INVALID is specified, we have to grant 117 * remap permission. 118 */ 119 if (!(flags & DEVMAP_ALLOW_REMAP)) { 120 return (DDI_FAILURE); 121 } 122 } else { 123 dhp->dh_cookie = cookie; 124 dhp->dh_roff = ptob(btop(off)); 125 dhp->dh_cvaddr = cp->cvaddr + dhp->dh_roff; 126 } 127 128 if (accattrp != NULL) { 129 switch (accattrp->devacc_attr_dataorder) { 130 case DDI_STRICTORDER_ACC: 131 dhp->dh_hat_attr &= ~HAT_ORDER_MASK; 132 dhp->dh_hat_attr |= (HAT_STRICTORDER|HAT_PLAT_NOCACHE); 133 break; 134 case DDI_UNORDERED_OK_ACC: 135 dhp->dh_hat_attr &= ~HAT_ORDER_MASK; 136 dhp->dh_hat_attr |= HAT_UNORDERED_OK; 137 break; 138 case DDI_MERGING_OK_ACC: 139 dhp->dh_hat_attr &= ~HAT_ORDER_MASK; 140 dhp->dh_hat_attr |= (HAT_MERGING_OK|HAT_PLAT_NOCACHE); 141 break; 142 case DDI_LOADCACHING_OK_ACC: 143 dhp->dh_hat_attr &= ~HAT_ORDER_MASK; 144 dhp->dh_hat_attr |= HAT_LOADCACHING_OK; 145 break; 146 case DDI_STORECACHING_OK_ACC: 147 dhp->dh_hat_attr &= ~HAT_ORDER_MASK; 148 dhp->dh_hat_attr |= HAT_STORECACHING_OK; 149 break; 150 default: 151 return (DDI_FAILURE); 152 } 153 } 154 155 #ifdef __sparc 156 if (accattrp != NULL) { 157 if (accattrp->devacc_attr_endian_flags == 158 DDI_STRUCTURE_LE_ACC) { 159 dhp->dh_hat_attr &= ~HAT_ENDIAN_MASK; 160 dhp->dh_hat_attr |= HAT_STRUCTURE_LE; 161 } 162 } 163 #endif 164 165 /* 166 * The default is _not_ to pass HAT_LOAD_NOCONSIST to hat_devload(); 167 * we pass HAT_LOAD_NOCONSIST _only_ in cases where hat tries to 168 * create consistent mappings but our intention was to create 169 * non-consistent mappings. 170 * 171 * DEVMEM: hat figures it out it's DEVMEM and creates non-consistent 172 * mappings. 173 * 174 * kernel exported memory: hat figures it out it's memory and always 175 * creates consistent mappings. 176 * 177 * /dev/mem: non-consistent mappings. See comments in common/io/mem.c 178 * 179 * /dev/kmem: consistent mappings are created unless they are 180 * MAP_FIXED. We _explicitly_ tell hat to create non-consistent 181 * mappings by passing HAT_LOAD_NOCONSIST in case of MAP_FIXED 182 * mappings of /dev/kmem. See common/io/mem.c 183 */ 184 185 /* Only some of the flags bits are settable by the driver */ 186 dhp->dh_flags |= (flags & DEVMAP_SETUP_FLAGS); 187 188 dhp->dh_len = ptob(btopr(len)); 189 dhp->dh_maxprot = maxprot & dhp->dh_orig_maxprot; 190 ASSERT((dhp->dh_prot & dhp->dh_orig_maxprot & maxprot) == dhp->dh_prot); 191 192 if (callbackops != NULL) { 193 bcopy(callbackops, &dhp->dh_callbackops, 194 sizeof (struct devmap_callback_ctl)); 195 } 196 /* 197 * Initialize dh_lock if we want to do remap. 198 */ 199 if (dhp->dh_flags & DEVMAP_ALLOW_REMAP) { 200 mutex_init(&dhp->dh_lock, NULL, MUTEX_DEFAULT, NULL); 201 dhp->dh_flags |= DEVMAP_LOCK_INITED; 202 } 203 204 dhp->dh_flags |= DEVMAP_SETUP_DONE; 205 206 return (DDI_SUCCESS); 207 } 208