1 /* 2 * Copyright 2007 Nouveau Project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <errno.h> 26 27 #include "nouveau_private.h" 28 29 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 15 30 #error nouveau_drm.h does not match expected patchlevel, update libdrm. 31 #endif 32 33 int 34 nouveau_device_open_existing(struct nouveau_device **dev, int close, 35 int fd, drm_context_t ctx) 36 { 37 struct nouveau_device_priv *nvdev; 38 drmVersionPtr ver; 39 uint64_t value; 40 int ret; 41 42 if (!dev || *dev) 43 return -EINVAL; 44 45 ver = drmGetVersion(fd); 46 if (!ver || ver->version_patchlevel != NOUVEAU_DRM_HEADER_PATCHLEVEL) 47 return -EINVAL; 48 drmFreeVersion(ver); 49 50 nvdev = calloc(1, sizeof(*nvdev)); 51 if (!nvdev) 52 return -ENOMEM; 53 nvdev->fd = fd; 54 nvdev->ctx = ctx; 55 nvdev->needs_close = close; 56 57 ret = drmCommandNone(nvdev->fd, DRM_NOUVEAU_CARD_INIT); 58 if (ret) { 59 nouveau_device_close((void *)&nvdev); 60 return ret; 61 } 62 63 ret = nouveau_device_get_param(&nvdev->base, 64 NOUVEAU_GETPARAM_VM_VRAM_BASE, &value); 65 if (ret) { 66 nouveau_device_close((void *)&nvdev); 67 return ret; 68 } 69 nvdev->base.vm_vram_base = value; 70 71 ret = nouveau_device_get_param(&nvdev->base, 72 NOUVEAU_GETPARAM_FB_SIZE, &value); 73 if (ret) { 74 nouveau_device_close((void *)&nvdev); 75 return ret; 76 } 77 nvdev->base.vm_vram_size = value; 78 79 ret = nouveau_device_get_param(&nvdev->base, 80 NOUVEAU_GETPARAM_AGP_SIZE, &value); 81 if (ret) { 82 nouveau_device_close((void *)&nvdev); 83 return ret; 84 } 85 nvdev->base.vm_gart_size = value; 86 87 ret = nouveau_bo_init(&nvdev->base); 88 if (ret) { 89 nouveau_device_close((void *)&nvdev); 90 return ret; 91 } 92 93 ret = nouveau_device_get_param(&nvdev->base, 94 NOUVEAU_GETPARAM_CHIPSET_ID, &value); 95 if (ret) { 96 nouveau_device_close((void *)&nvdev); 97 return ret; 98 } 99 nvdev->base.chipset = value; 100 101 *dev = &nvdev->base; 102 return 0; 103 } 104 105 int 106 nouveau_device_open(struct nouveau_device **dev, const char *busid) 107 { 108 drm_context_t ctx; 109 int fd, ret; 110 111 if (!dev || *dev) 112 return -EINVAL; 113 114 fd = drmOpen("nouveau", busid); 115 if (fd < 0) 116 return -EINVAL; 117 118 ret = drmCreateContext(fd, &ctx); 119 if (ret) { 120 drmClose(fd); 121 return ret; 122 } 123 124 ret = nouveau_device_open_existing(dev, 1, fd, ctx); 125 if (ret) { 126 drmDestroyContext(fd, ctx); 127 drmClose(fd); 128 return ret; 129 } 130 131 return 0; 132 } 133 134 void 135 nouveau_device_close(struct nouveau_device **dev) 136 { 137 struct nouveau_device_priv *nvdev; 138 139 if (!dev || !*dev) 140 return; 141 nvdev = nouveau_device(*dev); 142 *dev = NULL; 143 144 nouveau_bo_takedown(&nvdev->base); 145 146 if (nvdev->needs_close) { 147 drmDestroyContext(nvdev->fd, nvdev->ctx); 148 drmClose(nvdev->fd); 149 } 150 free(nvdev); 151 } 152 153 int 154 nouveau_device_get_param(struct nouveau_device *dev, 155 uint64_t param, uint64_t *value) 156 { 157 struct nouveau_device_priv *nvdev = nouveau_device(dev); 158 struct drm_nouveau_getparam g; 159 int ret; 160 161 if (!nvdev || !value) 162 return -EINVAL; 163 164 g.param = param; 165 ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM, 166 &g, sizeof(g)); 167 if (ret) 168 return ret; 169 170 *value = g.value; 171 return 0; 172 } 173 174 int 175 nouveau_device_set_param(struct nouveau_device *dev, 176 uint64_t param, uint64_t value) 177 { 178 struct nouveau_device_priv *nvdev = nouveau_device(dev); 179 struct drm_nouveau_setparam s; 180 int ret; 181 182 if (!nvdev) 183 return -EINVAL; 184 185 s.param = param; 186 s.value = value; 187 ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM, 188 &s, sizeof(s)); 189 if (ret) 190 return ret; 191 192 return 0; 193 } 194 195