Home | History | Annotate | Download | only in nouveau
      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