Home | History | Annotate | Line # | Download | only in bsd-core
      1 /*-
      2  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
      3  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     23  * OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  * Authors:
     26  *    Rickard E. (Rik) Faith <faith (at) valinux.com>
     27  *    Gareth Hughes <gareth (at) valinux.com>
     28  *
     29  */
     30 
     31 /** @file drm_drv.c
     32  * The catch-all file for DRM device support, including module setup/teardown,
     33  * open/close, and ioctl dispatch.
     34  */
     35 
     36 
     37 #if defined(__FreeBSD__)
     38 #include <sys/limits.h>
     39 #elif   defined(__NetBSD__)
     40 #include <sys/module.h>
     41 #endif
     42 #include "drmP.h"
     43 #include "drm.h"
     44 #include "drm_sarea.h"
     45 
     46 #ifdef DRM_DEBUG_DEFAULT_ON
     47 int drm_debug_flag = 1;
     48 #else
     49 int drm_debug_flag = 0;
     50 #endif
     51 
     52 static int drm_load(struct drm_device *dev);
     53 static void drm_unload(struct drm_device *dev);
     54 static drm_pci_id_list_t *drm_find_description(int vendor, int device,
     55     drm_pci_id_list_t *idlist);
     56 
     57 #if defined(__FreeBSD__)
     58 #define DRIVER_SOFTC(unit) \
     59 	((struct drm_device *)devclass_get_softc(drm_devclass, unit))
     60 
     61 MODULE_VERSION(drm, 1);
     62 MODULE_DEPEND(drm, agp, 1, 1, 1);
     63 MODULE_DEPEND(drm, pci, 1, 1, 1);
     64 MODULE_DEPEND(drm, mem, 1, 1, 1);
     65 #elif   defined(__NetBSD__)
     66 #define DRIVER_SOFTC(kdev) drm_get_device_from_kdev(kdev)
     67 #endif
     68 
     69 static drm_ioctl_desc_t		  drm_ioctls[256] = {
     70 	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
     71 	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
     72 	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
     73 	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
     74 	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
     75 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
     76 	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
     77 	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
     78 
     79 	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     80 	DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     81 	DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     82 	DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     83 
     84 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     85 	DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
     86 
     87 	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     88 	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
     89 
     90 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
     91 	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     92 	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     93 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
     94 	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     95 	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     96 	DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
     97 
     98 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
     99 	DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    100 
    101 	DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
    102 	DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
    103 
    104 	DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
    105 
    106 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    107 	DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    108 	DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
    109 	DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
    110 	DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
    111 	DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma, DRM_AUTH),
    112 
    113 	DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    114 
    115 #ifndef DRM_NO_AGP
    116 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    117 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    118 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    119 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
    120 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    121 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    122 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    123 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    124 #endif
    125 
    126 	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    127 	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    128 	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
    129 	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
    130 	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    131 };
    132 
    133 #if defined(__FreeBSD__)
    134 static struct cdevsw drm_cdevsw = {
    135 	.d_version =	D_VERSION,
    136 	.d_open =	drm_open,
    137 	.d_read =	drm_read,
    138 	.d_ioctl =	drm_ioctl,
    139 	.d_poll =	drm_poll,
    140 	.d_mmap =	drm_mmap,
    141 	.d_name =	"drm",
    142 	.d_flags =	D_TRACKCLOSE
    143 };
    144 
    145 int drm_msi = 1;	/* Enable by default. */
    146 TUNABLE_INT("hw.drm.msi", &drm_msi);
    147 
    148 static struct drm_msi_blacklist_entry drm_msi_blacklist[] = {
    149 	{0x8086, 0x2772}, /* Intel i945G	*/ \
    150 	{0x8086, 0x27A2}, /* Intel i945GM	*/ \
    151 	{0x8086, 0x27AE}, /* Intel i945GME	*/ \
    152 	{0, 0}
    153 };
    154 
    155 static int drm_msi_is_blacklisted(int vendor, int device)
    156 {
    157 	int i = 0;
    158 
    159 	for (i = 0; drm_msi_blacklist[i].vendor != 0; i++) {
    160 		if ((drm_msi_blacklist[i].vendor == vendor) &&
    161 		    (drm_msi_blacklist[i].device == device)) {
    162 			return 1;
    163 		}
    164 	}
    165 
    166 	return 0;
    167 }
    168 
    169 int drm_probe(device_t kdev, drm_pci_id_list_t *idlist)
    170 {
    171 	drm_pci_id_list_t *id_entry;
    172 	int vendor, device;
    173 #if __FreeBSD_version < 700010
    174 	device_t realdev;
    175 
    176 	if (!strcmp(device_get_name(kdev), "drmsub"))
    177 		realdev = device_get_parent(kdev);
    178 	else
    179 		realdev = kdev;
    180 	vendor = pci_get_vendor(realdev);
    181 	device = pci_get_device(realdev);
    182 #else
    183 	vendor = pci_get_vendor(kdev);
    184 	device = pci_get_device(kdev);
    185 #endif
    186 
    187 	if (pci_get_class(kdev) != PCIC_DISPLAY
    188 	    || pci_get_subclass(kdev) != PCIS_DISPLAY_VGA)
    189 		return ENXIO;
    190 
    191 	id_entry = drm_find_description(vendor, device, idlist);
    192 	if (id_entry != NULL) {
    193 		if (!device_get_desc(kdev)) {
    194 			DRM_DEBUG("desc : %s\n", device_get_desc(kdev));
    195 			device_set_desc(kdev, id_entry->name);
    196 		}
    197 		return 0;
    198 	}
    199 
    200 	return ENXIO;
    201 }
    202 
    203 int drm_attach(device_t kdev, drm_pci_id_list_t *idlist)
    204 {
    205 	struct drm_device *dev;
    206 	drm_pci_id_list_t *id_entry;
    207 	int unit, msicount;
    208 
    209 	unit = device_get_unit(kdev);
    210 	dev = device_get_softc(kdev);
    211 
    212 #if __FreeBSD_version < 700010
    213 	if (!strcmp(device_get_name(kdev), "drmsub"))
    214 		dev->device = device_get_parent(kdev);
    215 	else
    216 		dev->device = kdev;
    217 #else
    218 	dev->device = kdev;
    219 #endif
    220 	dev->devnode = make_dev(&drm_cdevsw,
    221 			unit,
    222 			DRM_DEV_UID,
    223 			DRM_DEV_GID,
    224 			DRM_DEV_MODE,
    225 			"dri/card%d", unit);
    226 
    227 #if __FreeBSD_version >= 700053
    228 	dev->pci_domain = pci_get_domain(dev->device);
    229 #else
    230 	dev->pci_domain = 0;
    231 #endif
    232 	dev->pci_bus = pci_get_bus(dev->device);
    233 	dev->pci_slot = pci_get_slot(dev->device);
    234 	dev->pci_func = pci_get_function(dev->device);
    235 
    236 	dev->pci_vendor = pci_get_vendor(dev->device);
    237 	dev->pci_device = pci_get_device(dev->device);
    238 
    239 	if (drm_msi &&
    240 	    !drm_msi_is_blacklisted(dev->pci_vendor, dev->pci_device)) {
    241 		msicount = pci_msi_count(dev->device);
    242 		DRM_DEBUG("MSI count = %d\n", msicount);
    243 		if (msicount > 1)
    244 			msicount = 1;
    245 
    246 		if (pci_alloc_msi(dev->device, &msicount) == 0) {
    247 			DRM_INFO("MSI enabled %d message(s)\n", msicount);
    248 			dev->msi_enabled = 1;
    249 			dev->irqrid = 1;
    250 		}
    251 	}
    252 
    253 	dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ,
    254 	    &dev->irqrid, RF_SHAREABLE);
    255 	if (!dev->irqr) {
    256 		return ENOENT;
    257 	}
    258 
    259 	dev->irq = (int) rman_get_start(dev->irqr);
    260 
    261 	mtx_init(&dev->dev_lock, "drmdev", NULL, MTX_DEF);
    262 	mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF);
    263 	mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF);
    264 	mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF);
    265 
    266 	id_entry = drm_find_description(dev->pci_vendor,
    267 	    dev->pci_device, idlist);
    268 	dev->id_entry = id_entry;
    269 
    270 	return drm_load(dev);
    271 }
    272 
    273 int drm_detach(device_t kdev)
    274 {
    275 	struct drm_device *dev;
    276 
    277 	dev = device_get_softc(kdev);
    278 
    279 	drm_unload(dev);
    280 
    281 	bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
    282 
    283 	if (dev->msi_enabled) {
    284 		pci_release_msi(dev->device);
    285 		DRM_INFO("MSI released\n");
    286 	}
    287 
    288 	return 0;
    289 }
    290 
    291 #ifndef DRM_DEV_NAME
    292 #define DRM_DEV_NAME "drm"
    293 #endif
    294 
    295 devclass_t drm_devclass;
    296 
    297 #elif   defined(__NetBSD__)
    298 
    299 /*
    300  * Mapping from device minor to struct drm_device.
    301  * This is needed, because each driver (radeon, i915, etc.) has its own
    302  * _cd structure, so we can't just lookup from _cd with minor.
    303  */
    304 struct drm_device *drm_units[DRM_MAXUNITS];
    305 
    306 struct cdevsw drm_cdevsw = {
    307 	.d_open = drm_open,
    308 	.d_close = drm_close,
    309 	.d_read = drm_read,
    310 	.d_write = nowrite,
    311 	.d_ioctl = drm_ioctl,
    312 	.d_stop = nostop,
    313 	.d_tty = notty,
    314 	.d_poll = drm_poll,
    315 	.d_mmap = drm_mmap,
    316 	.d_kqfilter = nokqfilter,
    317 	.d_discard = nodiscard,
    318 	.d_flag = D_TTY | D_NEGOFFSAFE
    319 };
    320 
    321 int drm_refcnt = 0;
    322 
    323 int
    324 drm_probe(struct pci_attach_args *pa, drm_pci_id_list_t *idlist)
    325 {
    326 	drm_pci_id_list_t *id_entry;
    327 
    328 	id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
    329 	    PCI_PRODUCT(pa->pa_id), idlist);
    330 	if (id_entry != NULL) {
    331 		return 1;
    332 	}
    333 
    334 	return 0;
    335 }
    336 
    337 void
    338 drm_attach(device_t kdev, struct pci_attach_args *pa, drm_pci_id_list_t *idlist)
    339 {
    340 	device_t parent_dev;
    341 	struct drm_device *dev;
    342 	int unit, parent_unit;
    343 
    344 	unit = device_unit(kdev);
    345 	if (unit < 0 || unit >= DRM_MAXUNITS)
    346 		panic("drm_attach: device unit %d invalid", unit);
    347 	if (drm_units[unit] != NULL)
    348 		panic("drm_attach: unit %d already attached", unit);
    349 
    350 	/*
    351 	 * this is kind of ugly but we fake up the pci "domain" by using
    352 	 * our pci unit number, so, find our parent pci device's unit...
    353 	 */
    354 	parent_dev = kdev;
    355 	do {
    356 		parent_dev = device_parent(parent_dev);
    357 	} while (parent_dev && !device_is_a(parent_dev, "pci"));
    358 	parent_unit = device_unit(parent_dev);
    359 	if (parent_unit < 0)
    360 		panic("drm_attach: device parent_unit %d invalid", parent_unit);
    361 
    362 	dev = device_private(kdev);
    363 	dev->device = kdev;
    364 	drm_units[unit] = dev;
    365 
    366 	for (unit = 0; unit < DRM_MAX_PCI_RESOURCE; unit++)
    367 	{
    368 		dev->pci_map_data[unit].mapped = 0;
    369 		dev->pci_map_data[unit].maptype =
    370 			pci_mapreg_type(pa->pa_pc, pa->pa_tag,
    371 				PCI_MAPREG_START + unit*4);
    372 		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag,
    373 				PCI_MAPREG_START + unit*4,
    374 				dev->pci_map_data[unit].maptype,
    375 				&(dev->pci_map_data[unit].base),
    376 				&(dev->pci_map_data[unit].size),
    377 				&(dev->pci_map_data[unit].flags)))
    378 		{
    379 			DRM_DEBUG("pci_mapreg info for %d failed\n",
    380 				PCI_MAPREG_START + unit*4);
    381 			dev->pci_map_data[unit].base = 0;
    382 			dev->pci_map_data[unit].size = 0;
    383 		}
    384 		if (dev->pci_map_data[unit].maptype == PCI_MAPREG_TYPE_MEM)
    385 			dev->pci_map_data[unit].flags |= BUS_SPACE_MAP_LINEAR;
    386 		if (dev->pci_map_data[unit].maptype ==
    387 		    (PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT))
    388 			dev->pci_map_data[unit].flags |= BUS_SPACE_MAP_LINEAR;
    389 		DRM_DEBUG("pci resource %d: type=%d, base=%lx, size=%zx, flags=%x\n",
    390 			unit, dev->pci_map_data[unit].maptype,
    391 			(unsigned long)dev->pci_map_data[unit].base,
    392 			dev->pci_map_data[unit].size,
    393 			dev->pci_map_data[unit].flags);
    394 	}
    395 	for (unit = 0; unit < DRM_MAX_PCI_RESOURCE; unit++) {
    396 		dev->agp_map_data[unit].mapped = 0;
    397 		dev->agp_map_data[unit].maptype = PCI_MAPREG_TYPE_MEM;
    398 	}
    399 
    400 	mutex_init(&dev->dev_lock, MUTEX_DEFAULT, IPL_NONE);
    401 	mutex_init(&dev->irq_lock, MUTEX_DEFAULT, IPL_VM);
    402 	mutex_init(&dev->vbl_lock, MUTEX_DEFAULT, IPL_NONE);
    403 	mutex_init(&dev->drw_lock, MUTEX_DEFAULT, IPL_NONE);
    404 
    405 	memcpy(&dev->pa, pa, sizeof(dev->pa));
    406 
    407 	dev->irq = pa->pa_intrpin;
    408 	dev->pci_domain = parent_unit;
    409 	dev->pci_bus = pa->pa_bus;
    410 	dev->pci_slot = pa->pa_device;
    411 	dev->pci_func = pa->pa_function;
    412 	dev->pci_vendor = PCI_VENDOR(pa->pa_id);
    413 	dev->pci_device = PCI_PRODUCT(pa->pa_id);
    414 
    415 	dev->id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
    416 	    PCI_PRODUCT(pa->pa_id), idlist);
    417 
    418 	aprint_naive("\n");
    419 	aprint_normal(": %s\n", dev->id_entry->name);
    420 	drm_load(dev);
    421 }
    422 
    423 int
    424 drm_detach(device_t self, int flags)
    425 {
    426 	struct drm_device *dev = device_private(self);
    427 
    428 	/* XXX locking */
    429 	if (dev->open_count)
    430 		return EBUSY;
    431 
    432 	drm_unload(dev);
    433 
    434 	drm_units[device_unit(self)] = NULL;
    435 
    436 	free(dev->driver, DRM_MEM_DRIVER);
    437 
    438 	return 0;
    439 }
    440 
    441 #endif
    442 
    443 drm_pci_id_list_t *drm_find_description(int vendor, int device,
    444     drm_pci_id_list_t *idlist)
    445 {
    446 	int i = 0;
    447 
    448 	for (i = 0; idlist[i].vendor != 0; i++) {
    449 		if ((idlist[i].vendor == vendor) &&
    450 		    ((idlist[i].device == device) ||
    451 		    (idlist[i].device == 0))) {
    452 			return &idlist[i];
    453 		}
    454 	}
    455 	return NULL;
    456 }
    457 
    458 static int drm_firstopen(struct drm_device *dev)
    459 {
    460 	drm_local_map_t *map;
    461 	int i;
    462 
    463 	DRM_SPINLOCK_ASSERT(&dev->dev_lock);
    464 
    465 	/* prebuild the SAREA */
    466 	i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
    467 	    _DRM_CONTAINS_LOCK, &map);
    468 	if (i != 0)
    469 		return i;
    470 
    471 	if (dev->driver->firstopen)
    472 		dev->driver->firstopen(dev);
    473 
    474 	dev->buf_use = 0;
    475 
    476 	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
    477 		i = drm_dma_setup(dev);
    478 		if (i != 0)
    479 			return i;
    480 	}
    481 
    482 	for (i = 0; i < DRM_HASH_SIZE; i++) {
    483 		dev->magiclist[i].head = NULL;
    484 		dev->magiclist[i].tail = NULL;
    485 	}
    486 
    487 	dev->lock.lock_queue = 0;
    488 	dev->irq_enabled = 0;
    489 	dev->context_flag = 0;
    490 	dev->last_context = 0;
    491 	dev->if_version = 0;
    492 
    493 #if defined(__FreeBSD__)
    494 	dev->buf_sigio = NULL;
    495 #elif   defined(__NetBSD__)
    496 	dev->buf_pgid = 0;
    497 #endif
    498 
    499 	DRM_DEBUG("\n");
    500 
    501 	return 0;
    502 }
    503 
    504 static int drm_lastclose(struct drm_device *dev)
    505 {
    506 	drm_magic_entry_t *pt, *next;
    507 	drm_local_map_t *map, *mapsave;
    508 	int i;
    509 
    510 	DRM_SPINLOCK_ASSERT(&dev->dev_lock);
    511 
    512 	DRM_DEBUG("\n");
    513 
    514 	if (dev->driver->lastclose != NULL)
    515 		dev->driver->lastclose(dev);
    516 
    517 	if (dev->irq_enabled)
    518 		drm_irq_uninstall(dev);
    519 
    520 	if (dev->unique) {
    521 		free(dev->unique, DRM_MEM_DRIVER);
    522 		dev->unique = NULL;
    523 		dev->unique_len = 0;
    524 	}
    525 	/* Clear pid list */
    526 	for (i = 0; i < DRM_HASH_SIZE; i++) {
    527 		for (pt = dev->magiclist[i].head; pt; pt = next) {
    528 			next = pt->next;
    529 			free(pt, DRM_MEM_MAGIC);
    530 		}
    531 		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
    532 	}
    533 
    534 	DRM_UNLOCK();
    535 	drm_drawable_free_all(dev);
    536 	DRM_LOCK();
    537 
    538 #ifndef DRM_NO_AGP
    539 	/* Clear AGP information */
    540 	if (dev->agp) {
    541 		drm_agp_mem_t *entry;
    542 		drm_agp_mem_t *nexte;
    543 
    544 		/* Remove AGP resources, but leave dev->agp intact until
    545 		 * drm_unload is called.
    546 		 */
    547 		for (entry = dev->agp->memory; entry; entry = nexte) {
    548 			nexte = entry->next;
    549 			if (entry->bound)
    550 				drm_agp_unbind_memory(entry->handle);
    551 			drm_agp_free_memory(entry->handle);
    552 			free(entry, DRM_MEM_AGPLISTS);
    553 		}
    554 		dev->agp->memory = NULL;
    555 
    556 		if (dev->agp->acquired)
    557 			drm_agp_release(dev);
    558 
    559 		dev->agp->acquired = 0;
    560 		dev->agp->enabled  = 0;
    561 	}
    562 #endif
    563 	if (dev->sg != NULL) {
    564 		drm_sg_cleanup(dev->sg);
    565 		dev->sg = NULL;
    566 	}
    567 
    568 	TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
    569 		if (!(map->flags & _DRM_DRIVER))
    570 			drm_rmmap(dev, map);
    571 	}
    572 
    573 	drm_dma_takedown(dev);
    574 	if (dev->lock.hw_lock) {
    575 		dev->lock.hw_lock = NULL; /* SHM removed */
    576 		dev->lock.file_priv = NULL;
    577 		DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
    578 	}
    579 
    580 	return 0;
    581 }
    582 
    583 static int drm_load(struct drm_device *dev)
    584 {
    585 	int i, retcode;
    586 
    587 	DRM_DEBUG("\n");
    588 
    589 	TAILQ_INIT(&dev->maplist);
    590 
    591 	drm_mem_init();
    592 	drm_sysctl_init(dev);
    593 	TAILQ_INIT(&dev->files);
    594 
    595 	dev->counters  = 6;
    596 	dev->types[0]  = _DRM_STAT_LOCK;
    597 	dev->types[1]  = _DRM_STAT_OPENS;
    598 	dev->types[2]  = _DRM_STAT_CLOSES;
    599 	dev->types[3]  = _DRM_STAT_IOCTLS;
    600 	dev->types[4]  = _DRM_STAT_LOCKS;
    601 	dev->types[5]  = _DRM_STAT_UNLOCKS;
    602 
    603 	for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
    604 		atomic_set(&dev->counts[i], 0);
    605 
    606 	if (dev->driver->load != NULL) {
    607 		DRM_LOCK();
    608 		/* Shared code returns -errno. */
    609 		retcode = -dev->driver->load(dev,
    610 		    dev->id_entry->driver_private);
    611 #if defined(__FreeBSD__)
    612 		if (pci_enable_busmaster(dev->device))
    613 			DRM_ERROR("Request to enable bus-master failed.\n");
    614 #endif
    615 		DRM_UNLOCK();
    616 		if (retcode != 0)
    617 			goto error;
    618 	}
    619 
    620 #ifndef DRM_NO_AGP
    621 	if (drm_core_has_AGP(dev)) {
    622 		if (drm_device_is_agp(dev))
    623 			dev->agp = drm_agp_init(dev);
    624 		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) &&
    625 		    dev->agp == NULL) {
    626 			DRM_ERROR("Card isn't AGP, or couldn't initialize "
    627 			    "AGP.\n");
    628 			retcode = ENOMEM;
    629 			goto error;
    630 		}
    631 		if (dev->agp != NULL) {
    632 			if (drm_mtrr_add(dev->agp->info.ai_aperture_base,
    633 			    dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0)
    634 				dev->agp->mtrr = 1;
    635 		}
    636 	}
    637 #endif
    638 
    639 	retcode = drm_ctxbitmap_init(dev);
    640 	if (retcode != 0) {
    641 		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
    642 		goto error;
    643 	}
    644 
    645 #if defined(__FreeBSD__)
    646 	dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL);
    647 	if (dev->drw_unrhdr == NULL) {
    648 		DRM_ERROR("Couldn't allocate drawable number allocator\n");
    649 		goto error;
    650 	}
    651 #else
    652 	dev->drw_no = 0;
    653 #endif
    654 
    655 #if defined(__NetBSD__)
    656 	aprint_normal_dev(dev->device,
    657 #else
    658 	DRM_INFO(
    659 #endif
    660         "Initialized %s %d.%d.%d %s\n",
    661 	    dev->driver->name,
    662 	    dev->driver->major,
    663 	    dev->driver->minor,
    664 	    dev->driver->patchlevel,
    665 	    dev->driver->date);
    666 
    667 	return 0;
    668 
    669 error:
    670 	drm_sysctl_cleanup(dev);
    671 	DRM_LOCK();
    672 	drm_lastclose(dev);
    673 	DRM_UNLOCK();
    674 #if defined(__FreeBSD__)
    675 	destroy_dev(dev->devnode);
    676 #endif
    677 
    678 	DRM_SPINUNINIT(&dev->drw_lock);
    679 	DRM_SPINUNINIT(&dev->vbl_lock);
    680 	DRM_SPINUNINIT(&dev->irq_lock);
    681 	DRM_SPINUNINIT(&dev->dev_lock);
    682 
    683 	return retcode;
    684 }
    685 
    686 static void drm_unload(struct drm_device *dev)
    687 {
    688 #if defined(__FreeBSD__)
    689 	int i;
    690 #endif
    691 
    692 	DRM_DEBUG("\n");
    693 
    694 	drm_sysctl_cleanup(dev);
    695 #if defined(__FreeBSD__)
    696 	destroy_dev(dev->devnode);
    697 #endif
    698 
    699 	drm_ctxbitmap_cleanup(dev);
    700 
    701 	if (dev->agp && dev->agp->mtrr) {
    702 		int __unused retcode;
    703 
    704 		retcode = drm_mtrr_del(0,
    705 		    dev->agp->info.ai_aperture_base,
    706 		    dev->agp->info.ai_aperture_size, DRM_MTRR_WC);
    707 		DRM_DEBUG("mtrr_del = %d", retcode);
    708 	}
    709 
    710 	DRM_LOCK();
    711 	drm_lastclose(dev);
    712 	DRM_UNLOCK();
    713 
    714 	drm_vblank_cleanup(dev);
    715 
    716 #if defined(__FreeBSD__)
    717 	/* Clean up PCI resources allocated by drm_bufs.c.  We're not really
    718 	 * worried about resource consumption while the DRM is inactive (between
    719 	 * lastclose and firstopen or unload) because these aren't actually
    720 	 * taking up KVA, just keeping the PCI resource allocated.
    721 	 */
    722 	for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
    723 		if (dev->pcir[i] == NULL)
    724 			continue;
    725 		bus_release_resource(dev->device, SYS_RES_MEMORY,
    726 		    dev->pcirid[i], dev->pcir[i]);
    727 		dev->pcir[i] = NULL;
    728 	}
    729 #endif
    730 
    731 	if (dev->agp) {
    732 		free(dev->agp, DRM_MEM_AGPLISTS);
    733 		dev->agp = NULL;
    734 	}
    735 
    736 	if (dev->driver->unload != NULL) {
    737 		DRM_LOCK();
    738 		dev->driver->unload(dev);
    739 		DRM_UNLOCK();
    740 	}
    741 
    742 #if defined(__FreeBSD__)
    743 	delete_unrhdr(dev->drw_unrhdr);
    744 #endif
    745 
    746 	drm_mem_uninit();
    747 
    748 #if defined(__FreeBSD__)
    749 	if (pci_disable_busmaster(dev->device))
    750 		DRM_ERROR("Request to disable bus-master failed.\n");
    751 #endif
    752 
    753 	DRM_SPINUNINIT(&dev->drw_lock);
    754 	DRM_SPINUNINIT(&dev->vbl_lock);
    755 	DRM_SPINUNINIT(&dev->irq_lock);
    756 	DRM_SPINUNINIT(&dev->dev_lock);
    757 }
    758 
    759 int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
    760 {
    761 	struct drm_version *drmvers = data;
    762 	int len;
    763 
    764 #define DRM_COPY( name, value )						\
    765 	len = strlen( value );						\
    766 	if ( len > name##_len ) len = name##_len;			\
    767 	name##_len = strlen( value );					\
    768 	if ( len && name ) {						\
    769 		if ( DRM_COPY_TO_USER( name, value, len ) )		\
    770 			return EFAULT;				\
    771 	}
    772 
    773 	drmvers->version_major		= dev->driver->major;
    774 	drmvers->version_minor		= dev->driver->minor;
    775 	drmvers->version_patchlevel	= dev->driver->patchlevel;
    776 
    777 	DRM_COPY(drmvers->name, dev->driver->name);
    778 	DRM_COPY(drmvers->date, dev->driver->date);
    779 	DRM_COPY(drmvers->desc, dev->driver->desc);
    780 
    781 	return 0;
    782 }
    783 
    784 int drm_open(DRM_CDEV kdev, int flags, int fmt, DRM_STRUCTCDEVPROC *p)
    785 {
    786 	struct drm_device *dev = NULL;
    787 	int retcode = 0;
    788 
    789 #if defined(__FreeBSD__)
    790 	dev = DRIVER_SOFTC(dev2unit(kdev));
    791 #elif   defined(__NetBSD__)
    792 	dev = DRIVER_SOFTC(kdev);
    793 	if (dev == NULL)
    794 		return ENXIO;
    795 	dev->kdev = kdev;
    796 #endif
    797 
    798 	DRM_DEBUG("open_count = %d\n", dev->open_count);
    799 
    800 	retcode = drm_open_helper(kdev, flags, fmt, DRM_CDEVPROC_REAL(p), dev);
    801 
    802 	if (!retcode) {
    803 		atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
    804 		DRM_LOCK();
    805 #if defined(__FreeBSD__)
    806 		device_busy(dev->device);
    807 #endif
    808 		if (!dev->open_count++)
    809 			retcode = drm_firstopen(dev);
    810 		DRM_UNLOCK();
    811 	}
    812 
    813 	return retcode;
    814 }
    815 
    816 #if defined(__FreeBSD__)
    817 void drm_close(void *data)
    818 #elif   defined(__NetBSD__)
    819 int
    820 drm_close(dev_t kdev, int flags, int fmt, struct lwp *l)
    821 #endif
    822 {
    823 	struct drm_file *file_priv;
    824 	struct drm_device *dev;
    825 	int retcode = 0;
    826 
    827 #if defined(__FreeBSD__)
    828 	file_priv = data;
    829 	dev = file_priv->dev;
    830 #elif   defined(__NetBSD__)
    831 	dev = DRIVER_SOFTC(kdev);
    832 #endif
    833 
    834 	DRM_DEBUG("open_count = %d\n", dev->open_count);
    835 
    836 	DRM_LOCK();
    837 
    838 #if defined(__NetBSD__)
    839 	file_priv = drm_find_file_by_proc(dev, l->l_proc);
    840 	if (file_priv == NULL) {
    841 		DRM_UNLOCK();
    842 		DRM_ERROR("can't find authenticator\n");
    843 		return EINVAL;
    844 	}
    845 #endif
    846 
    847 	if (dev->driver->preclose != NULL)
    848 		dev->driver->preclose(dev, file_priv);
    849 
    850 	/* ========================================================
    851 	 * Begin inline drm_release
    852 	 */
    853 
    854 #if defined(__FreeBSD__)
    855 	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
    856 	    DRM_CURRENTPID, (long)dev->device, dev->open_count);
    857 #elif   defined(__NetBSD__)
    858 	DRM_DEBUG("pid = %d, device = 0x%p, open_count = %d\n",
    859 	    DRM_CURRENTPID, dev->device, dev->open_count);
    860 #endif
    861 
    862 	if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
    863 	    && dev->lock.file_priv == file_priv) {
    864 		DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
    865 			  DRM_CURRENTPID,
    866 			  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
    867 		if (dev->driver->reclaim_buffers_locked != NULL)
    868 			dev->driver->reclaim_buffers_locked(dev, file_priv);
    869 
    870 		drm_lock_free(&dev->lock,
    871 		    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
    872 
    873 				/* FIXME: may require heavy-handed reset of
    874                                    hardware at this point, possibly
    875                                    processed via a callback to the X
    876                                    server. */
    877 	} else if (dev->driver->reclaim_buffers_locked != NULL &&
    878 	    dev->lock.hw_lock != NULL) {
    879 		/* The lock is required to reclaim buffers */
    880 		for (;;) {
    881 			if (!dev->lock.hw_lock) {
    882 				/* Device has been unregistered */
    883 				retcode = EINTR;
    884 				break;
    885 			}
    886 			if (drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) {
    887 				dev->lock.file_priv = file_priv;
    888 				dev->lock.lock_time = jiffies;
    889 				atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
    890 				break;	/* Got lock */
    891 			}
    892 			/* Contention */
    893 #if defined(__FreeBSD__)
    894 			retcode = mtx_sleep((void *)&dev->lock.lock_queue,
    895 			    &dev->dev_lock, PCATCH, "drmlk2", 0);
    896 #elif   defined(__NetBSD__)
    897 			retcode = mtsleep((void *)&dev->lock.lock_queue,
    898 			    PCATCH, "drmlk2", 0, &dev->dev_lock);
    899 #endif
    900 			if (retcode)
    901 				break;
    902 		}
    903 		if (retcode == 0) {
    904 			dev->driver->reclaim_buffers_locked(dev, file_priv);
    905 			drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
    906 		}
    907 	}
    908 
    909 	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
    910 	    !dev->driver->reclaim_buffers_locked)
    911 		drm_reclaim_buffers(dev, file_priv);
    912 
    913 #if defined(__FreeBSD__)
    914 	funsetown(&dev->buf_sigio);
    915 #else
    916 	dev->buf_pgid = 0;
    917 #endif
    918 
    919 	if (dev->driver->postclose != NULL)
    920 		dev->driver->postclose(dev, file_priv);
    921 	TAILQ_REMOVE(&dev->files, file_priv, link);
    922 	free(file_priv, DRM_MEM_FILES);
    923 
    924 	/* ========================================================
    925 	 * End inline drm_release
    926 	 */
    927 
    928 	atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
    929 #if defined(__FreeBSD__)
    930 	device_unbusy(dev->device);
    931 #endif
    932 #if defined(__NetBSD__)
    933 	/* On NetBSD, close will only be called once */
    934 	DRM_DEBUG("setting open_count %d to 1\n", (int)dev->open_count);
    935 	while (dev->open_count != 1) {
    936 		/*
    937 		 * XXXMRG probably should assert that we are freeing
    938 		 * one of these each time.  i think.
    939 		 */
    940 		if (!TAILQ_EMPTY(&dev->files)) {
    941 			file_priv = TAILQ_FIRST(&dev->files);
    942 			TAILQ_REMOVE(&dev->files, file_priv, link);
    943 		}
    944 		dev->open_count--;
    945 	}
    946 #endif
    947 	if (--dev->open_count == 0) {
    948 		retcode = drm_lastclose(dev);
    949 	}
    950 
    951 	DRM_UNLOCK();
    952 
    953 #if defined(__NetBSD__)
    954 	return retcode;
    955 #endif
    956 }
    957 
    958 /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.
    959  */
    960 int drm_ioctl(DRM_CDEV kdev, u_long cmd, DRM_IOCTL_DATA data, int flags,
    961     DRM_STRUCTCDEVPROC *p)
    962 {
    963 	struct drm_device *dev = drm_get_device_from_kdev(kdev);
    964 	int retcode = 0;
    965 	drm_ioctl_desc_t *ioctl;
    966 	int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv);
    967 	int nr = DRM_IOCTL_NR(cmd);
    968 	int is_driver_ioctl = 0;
    969 	struct drm_file *file_priv;
    970 
    971 #if defined(__FreeBSD__)
    972 	retcode = devfs_get_cdevpriv((void **)&file_priv);
    973 	if (retcode != 0) {
    974 		DRM_ERROR("can't find authenticator\n");
    975 		return EINVAL;
    976 	}
    977 #elif   defined(__NetBSD__)
    978 	DRM_LOCK();
    979 	file_priv = drm_find_file_by_proc(dev, p->l_proc);
    980 	DRM_UNLOCK();
    981 	if (file_priv == NULL) {
    982 		DRM_ERROR("can't find authenticator\n");
    983 		return EINVAL;
    984 	}
    985 #endif
    986 
    987 	atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
    988 	++file_priv->ioctl_count;
    989 
    990 #if defined(__FreeBSD__)
    991 	DRM_DEBUG("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
    992 	    DRM_CURRENTPID, cmd, nr, (long)dev->device,
    993 	    file_priv->authenticated);
    994 #elif   defined(__NetBSD__)
    995 	DRM_DEBUG("pid=%d, cmd=0x%02lx, nr=0x%02x, dev %p, auth=%d\n",
    996 	    DRM_CURRENTPID, cmd, nr, dev->device,
    997 	    file_priv->authenticated);
    998 #endif
    999 
   1000 	switch (cmd) {
   1001 	case FIONBIO:
   1002 	case FIOASYNC:
   1003 		return 0;
   1004 
   1005 #if defined(__FreeBSD__)
   1006 	case FIOSETOWN:
   1007 		return fsetown(*(int *)data, &dev->buf_sigio);
   1008 
   1009 	case FIOGETOWN:
   1010 		*(int *) data = fgetown(&dev->buf_sigio);
   1011 		return 0;
   1012 #endif
   1013 #if defined(__NetBSD__)
   1014 	case SIOCSPGRP:
   1015 	case TIOCSPGRP:
   1016 	case FIOSETOWN:
   1017 		return fsetown(&dev->buf_pgid, cmd, data);
   1018 
   1019 	case SIOCGPGRP:
   1020 	case TIOCGPGRP:
   1021 	case FIOGETOWN:
   1022 		return fgetown(dev->buf_pgid, cmd, data);
   1023 #endif
   1024 	}
   1025 
   1026 	if (IOCGROUP(cmd) != DRM_IOCTL_BASE) {
   1027 		DRM_DEBUG("Bad ioctl group 0x%x\n", (int)IOCGROUP(cmd));
   1028 		return EINVAL;
   1029 	}
   1030 
   1031 	ioctl = &drm_ioctls[nr];
   1032 	/* It's not a core DRM ioctl, try driver-specific. */
   1033 	if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
   1034 		/* The array entries begin at DRM_COMMAND_BASE ioctl nr */
   1035 		nr -= DRM_COMMAND_BASE;
   1036 		if (nr > dev->driver->max_ioctl) {
   1037 			DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n",
   1038 			    nr, dev->driver->max_ioctl);
   1039 			return EINVAL;
   1040 		}
   1041 		ioctl = &dev->driver->ioctls[nr];
   1042 		is_driver_ioctl = 1;
   1043 	}
   1044 	func = ioctl->func;
   1045 
   1046 	if (func == NULL) {
   1047 		DRM_DEBUG("no function\n");
   1048 		return EINVAL;
   1049 	}
   1050 
   1051 	if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(DRM_CDEVPROC_REAL(p))) ||
   1052 	    ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
   1053 	    ((ioctl->flags & DRM_MASTER) && !file_priv->master))
   1054 		return EACCES;
   1055 
   1056 	if (is_driver_ioctl) {
   1057 		DRM_LOCK();
   1058 		/* shared code returns -errno */
   1059 		retcode = -func(dev, data, file_priv);
   1060 		DRM_UNLOCK();
   1061 	} else {
   1062 		retcode = func(dev, data, file_priv);
   1063 	}
   1064 
   1065 	if (retcode != 0)
   1066 		DRM_DEBUG("    returning %d\n", retcode);
   1067 
   1068 	return retcode;
   1069 }
   1070 
   1071 drm_local_map_t *drm_getsarea(struct drm_device *dev)
   1072 {
   1073 	drm_local_map_t *map;
   1074 
   1075 	DRM_SPINLOCK_ASSERT(&dev->dev_lock);
   1076 	TAILQ_FOREACH(map, &dev->maplist, link) {
   1077 		if (map->type == _DRM_SHM && (map->flags & _DRM_CONTAINS_LOCK))
   1078 			return map;
   1079 	}
   1080 
   1081 	return NULL;
   1082 }
   1083 
   1084 #if DRM_LINUX
   1085 
   1086 #include <sys/sysproto.h>
   1087 
   1088 MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
   1089 
   1090 #define LINUX_IOCTL_DRM_MIN		0x6400
   1091 #define LINUX_IOCTL_DRM_MAX		0x64ff
   1092 
   1093 static linux_ioctl_function_t drm_linux_ioctl;
   1094 static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl,
   1095     LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
   1096 
   1097 SYSINIT(drm_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
   1098     linux_ioctl_register_handler, &drm_handler);
   1099 SYSUNINIT(drm_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE,
   1100     linux_ioctl_unregister_handler, &drm_handler);
   1101 
   1102 /* The bits for in/out are switched on Linux */
   1103 #define LINUX_IOC_IN	IOC_OUT
   1104 #define LINUX_IOC_OUT	IOC_IN
   1105 
   1106 static int
   1107 drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
   1108 {
   1109 	int error;
   1110 	int cmd = args->cmd;
   1111 
   1112 	args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
   1113 	if (cmd & LINUX_IOC_IN)
   1114 		args->cmd |= IOC_IN;
   1115 	if (cmd & LINUX_IOC_OUT)
   1116 		args->cmd |= IOC_OUT;
   1117 
   1118 	error = ioctl(p, (struct ioctl_args *)args);
   1119 
   1120 	return error;
   1121 }
   1122 #endif /* DRM_LINUX */
   1123 
   1124 #if defined(__NetBSD__)
   1125 /* Module support */
   1126 
   1127 MODULE(MODULE_CLASS_DRIVER, drm, "pci");
   1128 
   1129 static int
   1130 drm_modcmd(modcmd_t cmd, void *arg)
   1131 {
   1132 #ifdef _MODULE
   1133 	int bmajor = -1, cmajor = -1;
   1134 
   1135 	switch (cmd) {
   1136 	case MODULE_CMD_INIT:
   1137 		return devsw_attach("drm", NULL, &bmajor, &drm_cdevsw, &cmajor);
   1138 	case MODULE_CMD_FINI:
   1139 		devsw_detach(NULL, &drm_cdevsw);
   1140 		return 0;
   1141 	default:
   1142 		return ENOTTY;
   1143 	}
   1144 #else
   1145 	if (cmd == MODULE_CMD_INIT)
   1146 		return 0;
   1147 	return ENOTTY;
   1148 #endif
   1149 }
   1150 
   1151 #endif /* __NetBSD__ */
   1152