0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <video/sisfb.h>
0035
0036 #include <drm/drm_device.h>
0037 #include <drm/drm_file.h>
0038 #include <drm/sis_drm.h>
0039
0040 #include "sis_drv.h"
0041
0042
0043 #define VIDEO_TYPE 0
0044 #define AGP_TYPE 1
0045
0046
0047 struct sis_memblock {
0048 struct drm_mm_node mm_node;
0049 struct sis_memreq req;
0050 struct list_head owner_list;
0051 };
0052
0053 #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
0054
0055
0056 #define SIS_MM_ALIGN_SHIFT 0
0057 #define SIS_MM_ALIGN_MASK 0
0058
0059 #else
0060
0061 #define SIS_MM_ALIGN_SHIFT 4
0062 #define SIS_MM_ALIGN_MASK ((1 << SIS_MM_ALIGN_SHIFT) - 1)
0063
0064 #endif
0065
0066 static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
0067 {
0068 drm_sis_private_t *dev_priv = dev->dev_private;
0069 drm_sis_fb_t *fb = data;
0070
0071 mutex_lock(&dev->struct_mutex);
0072
0073
0074 drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> SIS_MM_ALIGN_SHIFT);
0075
0076 dev_priv->vram_initialized = 1;
0077 dev_priv->vram_offset = fb->offset;
0078
0079 mutex_unlock(&dev->struct_mutex);
0080 DRM_DEBUG("offset = %lu, size = %lu\n", fb->offset, fb->size);
0081
0082 return 0;
0083 }
0084
0085 static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
0086 void *data, int pool)
0087 {
0088 drm_sis_private_t *dev_priv = dev->dev_private;
0089 drm_sis_mem_t *mem = data;
0090 int retval = 0, user_key;
0091 struct sis_memblock *item;
0092 struct sis_file_private *file_priv = file->driver_priv;
0093 unsigned long offset;
0094
0095 mutex_lock(&dev->struct_mutex);
0096
0097 if (0 == ((pool == 0) ? dev_priv->vram_initialized :
0098 dev_priv->agp_initialized)) {
0099 DRM_ERROR
0100 ("Attempt to allocate from uninitialized memory manager.\n");
0101 mutex_unlock(&dev->struct_mutex);
0102 return -EINVAL;
0103 }
0104
0105 item = kzalloc(sizeof(*item), GFP_KERNEL);
0106 if (!item) {
0107 retval = -ENOMEM;
0108 goto fail_alloc;
0109 }
0110
0111 mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
0112 if (pool == AGP_TYPE) {
0113 retval = drm_mm_insert_node(&dev_priv->agp_mm,
0114 &item->mm_node,
0115 mem->size);
0116 offset = item->mm_node.start;
0117 } else {
0118 #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
0119 item->req.size = mem->size;
0120 sis_malloc(&item->req);
0121 if (item->req.size == 0)
0122 retval = -ENOMEM;
0123 offset = item->req.offset;
0124 #else
0125 retval = drm_mm_insert_node(&dev_priv->vram_mm,
0126 &item->mm_node,
0127 mem->size);
0128 offset = item->mm_node.start;
0129 #endif
0130 }
0131 if (retval)
0132 goto fail_alloc;
0133
0134 retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL);
0135 if (retval < 0)
0136 goto fail_idr;
0137 user_key = retval;
0138
0139 list_add(&item->owner_list, &file_priv->obj_list);
0140 mutex_unlock(&dev->struct_mutex);
0141
0142 mem->offset = ((pool == 0) ?
0143 dev_priv->vram_offset : dev_priv->agp_offset) +
0144 (offset << SIS_MM_ALIGN_SHIFT);
0145 mem->free = user_key;
0146 mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
0147
0148 return 0;
0149
0150 fail_idr:
0151 drm_mm_remove_node(&item->mm_node);
0152 fail_alloc:
0153 kfree(item);
0154 mutex_unlock(&dev->struct_mutex);
0155
0156 mem->offset = 0;
0157 mem->size = 0;
0158 mem->free = 0;
0159
0160 DRM_DEBUG("alloc %d, size = %ld, offset = %ld\n", pool, mem->size,
0161 mem->offset);
0162
0163 return retval;
0164 }
0165
0166 static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
0167 {
0168 drm_sis_private_t *dev_priv = dev->dev_private;
0169 drm_sis_mem_t *mem = data;
0170 struct sis_memblock *obj;
0171
0172 mutex_lock(&dev->struct_mutex);
0173 obj = idr_find(&dev_priv->object_idr, mem->free);
0174 if (obj == NULL) {
0175 mutex_unlock(&dev->struct_mutex);
0176 return -EINVAL;
0177 }
0178
0179 idr_remove(&dev_priv->object_idr, mem->free);
0180 list_del(&obj->owner_list);
0181 if (drm_mm_node_allocated(&obj->mm_node))
0182 drm_mm_remove_node(&obj->mm_node);
0183 #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
0184 else
0185 sis_free(obj->req.offset);
0186 #endif
0187 kfree(obj);
0188 mutex_unlock(&dev->struct_mutex);
0189 DRM_DEBUG("free = 0x%lx\n", mem->free);
0190
0191 return 0;
0192 }
0193
0194 static int sis_fb_alloc(struct drm_device *dev, void *data,
0195 struct drm_file *file_priv)
0196 {
0197 return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE);
0198 }
0199
0200 static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
0201 struct drm_file *file_priv)
0202 {
0203 drm_sis_private_t *dev_priv = dev->dev_private;
0204 drm_sis_agp_t *agp = data;
0205 dev_priv = dev->dev_private;
0206
0207 mutex_lock(&dev->struct_mutex);
0208 drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> SIS_MM_ALIGN_SHIFT);
0209
0210 dev_priv->agp_initialized = 1;
0211 dev_priv->agp_offset = agp->offset;
0212 mutex_unlock(&dev->struct_mutex);
0213
0214 DRM_DEBUG("offset = %lu, size = %lu\n", agp->offset, agp->size);
0215 return 0;
0216 }
0217
0218 static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data,
0219 struct drm_file *file_priv)
0220 {
0221
0222 return sis_drm_alloc(dev, file_priv, data, AGP_TYPE);
0223 }
0224
0225 static drm_local_map_t *sis_reg_init(struct drm_device *dev)
0226 {
0227 struct drm_map_list *entry;
0228 drm_local_map_t *map;
0229
0230 list_for_each_entry(entry, &dev->maplist, head) {
0231 map = entry->map;
0232 if (!map)
0233 continue;
0234 if (map->type == _DRM_REGISTERS)
0235 return map;
0236 }
0237 return NULL;
0238 }
0239
0240 int sis_idle(struct drm_device *dev)
0241 {
0242 drm_sis_private_t *dev_priv = dev->dev_private;
0243 uint32_t idle_reg;
0244 unsigned long end;
0245 int i;
0246
0247 if (dev_priv->idle_fault)
0248 return 0;
0249
0250 if (dev_priv->mmio == NULL) {
0251 dev_priv->mmio = sis_reg_init(dev);
0252 if (dev_priv->mmio == NULL) {
0253 DRM_ERROR("Could not find register map.\n");
0254 return 0;
0255 }
0256 }
0257
0258
0259
0260
0261
0262 if (dev_priv->chipset != SIS_CHIP_315)
0263 return 0;
0264
0265
0266
0267
0268
0269
0270 end = jiffies + (HZ * 3);
0271
0272 for (i = 0; i < 4; ++i) {
0273 do {
0274 idle_reg = SIS_READ(0x85cc);
0275 } while (!time_after_eq(jiffies, end) &&
0276 ((idle_reg & 0x80000000) != 0x80000000));
0277 }
0278
0279 if (time_after_eq(jiffies, end)) {
0280 DRM_ERROR("Graphics engine idle timeout. "
0281 "Disabling idle check\n");
0282 dev_priv->idle_fault = 1;
0283 }
0284
0285
0286
0287
0288
0289
0290 return 0;
0291 }
0292
0293
0294 void sis_lastclose(struct drm_device *dev)
0295 {
0296 drm_sis_private_t *dev_priv = dev->dev_private;
0297
0298 if (!dev_priv)
0299 return;
0300
0301 mutex_lock(&dev->struct_mutex);
0302 if (dev_priv->vram_initialized) {
0303 drm_mm_takedown(&dev_priv->vram_mm);
0304 dev_priv->vram_initialized = 0;
0305 }
0306 if (dev_priv->agp_initialized) {
0307 drm_mm_takedown(&dev_priv->agp_mm);
0308 dev_priv->agp_initialized = 0;
0309 }
0310 dev_priv->mmio = NULL;
0311 mutex_unlock(&dev->struct_mutex);
0312 }
0313
0314 void sis_reclaim_buffers_locked(struct drm_device *dev,
0315 struct drm_file *file)
0316 {
0317 struct sis_file_private *file_priv = file->driver_priv;
0318 struct sis_memblock *entry, *next;
0319
0320 if (!(dev->master && file->master->lock.hw_lock))
0321 return;
0322
0323 drm_legacy_idlelock_take(&file->master->lock);
0324
0325 mutex_lock(&dev->struct_mutex);
0326 if (list_empty(&file_priv->obj_list)) {
0327 mutex_unlock(&dev->struct_mutex);
0328 drm_legacy_idlelock_release(&file->master->lock);
0329
0330 return;
0331 }
0332
0333 sis_idle(dev);
0334
0335
0336 list_for_each_entry_safe(entry, next, &file_priv->obj_list,
0337 owner_list) {
0338 list_del(&entry->owner_list);
0339 if (drm_mm_node_allocated(&entry->mm_node))
0340 drm_mm_remove_node(&entry->mm_node);
0341 #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
0342 else
0343 sis_free(entry->req.offset);
0344 #endif
0345 kfree(entry);
0346 }
0347 mutex_unlock(&dev->struct_mutex);
0348
0349 drm_legacy_idlelock_release(&file->master->lock);
0350
0351 return;
0352 }
0353
0354 const struct drm_ioctl_desc sis_ioctls[] = {
0355 DRM_IOCTL_DEF_DRV(SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
0356 DRM_IOCTL_DEF_DRV(SIS_FB_FREE, sis_drm_free, DRM_AUTH),
0357 DRM_IOCTL_DEF_DRV(SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
0358 DRM_IOCTL_DEF_DRV(SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
0359 DRM_IOCTL_DEF_DRV(SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
0360 DRM_IOCTL_DEF_DRV(SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
0361 };
0362
0363 int sis_max_ioctl = ARRAY_SIZE(sis_ioctls);