drm_drv.c revision 277487
1223637Sbz/*- 2126258Smlaier * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 3126258Smlaier * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 4126258Smlaier * All Rights Reserved. 5126258Smlaier * 6126258Smlaier * Permission is hereby granted, free of charge, to any person obtaining a 7126258Smlaier * copy of this software and associated documentation files (the "Software"), 8126258Smlaier * to deal in the Software without restriction, including without limitation 9126258Smlaier * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10126258Smlaier * and/or sell copies of the Software, and to permit persons to whom the 11126258Smlaier * Software is furnished to do so, subject to the following conditions: 12126258Smlaier * 13126258Smlaier * The above copyright notice and this permission notice (including the next 14126258Smlaier * paragraph) shall be included in all copies or substantial portions of the 15126258Smlaier * Software. 16126258Smlaier * 17126258Smlaier * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18126258Smlaier * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19126258Smlaier * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20126258Smlaier * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21126258Smlaier * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22126258Smlaier * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23126258Smlaier * OTHER DEALINGS IN THE SOFTWARE. 24126258Smlaier * 25126258Smlaier * Authors: 26126258Smlaier * Rickard E. (Rik) Faith <faith@valinux.com> 27126258Smlaier * Gareth Hughes <gareth@valinux.com> 28126258Smlaier * 29126258Smlaier */ 30126258Smlaier 31126258Smlaier#include <sys/cdefs.h> 32126258Smlaier__FBSDID("$FreeBSD: head/sys/dev/drm2/drm_drv.c 277487 2015-01-21 16:10:37Z kib $"); 33126258Smlaier 34126258Smlaier/** @file drm_drv.c 35126258Smlaier * The catch-all file for DRM device support, including module setup/teardown, 36145836Smlaier * open/close, and ioctl dispatch. 37126258Smlaier */ 38240233Sglebius 39126258Smlaier#include <sys/limits.h> 40126258Smlaier#include <sys/sysent.h> 41126258Smlaier#include <dev/drm2/drmP.h> 42126261Smlaier#include <dev/drm2/drm.h> 43126261Smlaier#include <dev/drm2/drm_core.h> 44240233Sglebius#include <dev/drm2/drm_global.h> 45126258Smlaier#include <dev/drm2/drm_sarea.h> 46126258Smlaier#include <dev/drm2/drm_mode.h> 47126258Smlaier 48126258Smlaier#ifdef DRM_DEBUG_DEFAULT_ON 49171168Smlaierint drm_debug_flag = (DRM_DEBUGBITS_DEBUG | DRM_DEBUGBITS_KMS | 50171168Smlaier DRM_DEBUGBITS_FAILED_IOCTL); 51171168Smlaier#else 52171168Smlaierint drm_debug_flag = 0; 53171168Smlaier#endif 54171168Smlaierint drm_notyet_flag = 0; 55171168Smlaier 56126258Smlaierunsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ 57145836Smlaierunsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ 58223637Sbz 59126258Smlaier/* 60126258Smlaier * Default to use monotonic timestamps for wait-for-vblank and page-flip 61126258Smlaier * complete events. 62126258Smlaier */ 63126258Smlaierunsigned int drm_timestamp_monotonic = 1; 64126258Smlaier 65126258Smlaierstatic int drm_load(struct drm_device *dev); 66126258Smlaierstatic void drm_unload(struct drm_device *dev); 67171168Smlaierstatic drm_pci_id_list_t *drm_find_description(int vendor, int device, 68223637Sbz drm_pci_id_list_t *idlist); 69171168Smlaierstatic int drm_mmap_single(struct cdev *kdev, vm_ooffset_t *offset, 70126258Smlaier vm_size_t size, struct vm_object **obj_res, int nprot); 71126258Smlaier 72126258Smlaierstatic int 73126258Smlaierdrm_modevent(module_t mod, int type, void *data) 74126258Smlaier{ 75126258Smlaier 76126258Smlaier switch (type) { 77126258Smlaier case MOD_LOAD: 78126258Smlaier TUNABLE_INT_FETCH("drm.debug", &drm_debug_flag); 79126258Smlaier TUNABLE_INT_FETCH("drm.notyet", &drm_notyet_flag); 80130613Smlaier break; 81171168Smlaier } 82171168Smlaier return (0); 83145836Smlaier} 84145836Smlaier 85145836Smlaierstatic moduledata_t drm_mod = { 86145836Smlaier "drmn", 87145836Smlaier drm_modevent, 88145836Smlaier 0 89145836Smlaier}; 90145836SmlaierDECLARE_MODULE(drmn, drm_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 91145836SmlaierMODULE_VERSION(drmn, 1); 92145836SmlaierMODULE_DEPEND(drmn, agp, 1, 1, 1); 93145836SmlaierMODULE_DEPEND(drmn, pci, 1, 1, 1); 94145836SmlaierMODULE_DEPEND(drmn, mem, 1, 1, 1); 95145836SmlaierMODULE_DEPEND(drmn, iicbus, 1, 1, 1); 96145836Smlaier 97145836Smlaierstatic drm_ioctl_desc_t drm_ioctls[256] = { 98145836Smlaier DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0), 99145836Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), 100145836Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), 101145836Smlaier DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), 102145836Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0), 103145836Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), 104126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), 105171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED), 106240233Sglebius DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY), 107126258Smlaier 108126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 109126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 110126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 111240233Sglebius DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 112223637Sbz 113126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 114130613Smlaier DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH), 115126258Smlaier 116126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 117126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), 118171168Smlaier 119171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), 120171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), 121171168Smlaier 122126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), 123126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 124126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 125126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH), 126126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 127126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 128126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), 129126258Smlaier 130126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 131126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 132126258Smlaier 133126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), 134126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), 135126258Smlaier 136126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), 137126258Smlaier 138126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 139130613Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 140130613Smlaier DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH), 141130613Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH), 142130613Smlaier DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH), 143130613Smlaier DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma, DRM_AUTH), 144130613Smlaier 145126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 146126258Smlaier 147126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 148126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 149126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 150126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH), 151126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 152126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 153126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 154126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 155130613Smlaier 156126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 157130613Smlaier DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 158126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED), 159126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), 160126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 161130613Smlaier 162126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED), 163126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), 164127145Smlaier DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), 165127145Smlaier 166130613Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 167171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 168171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 169171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 170171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 171171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 172171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 173171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED), 174171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), 175171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 176171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 177171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 178171168Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 179126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW|DRM_UNLOCKED), 180126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 181126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 182126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 183126258Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 184126263Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 185126263Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 186126263Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 187126263Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 188126263Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 189223637Sbz DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 190126261Smlaier DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 191240233Sglebius DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 192240233Sglebius DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 193240233Sglebius}; 194126261Smlaier 195240233Sglebiusstatic struct cdevsw drm_cdevsw = { 196240233Sglebius .d_version = D_VERSION, 197240233Sglebius .d_open = drm_open, 198240233Sglebius .d_read = drm_read, 199240233Sglebius .d_ioctl = drm_ioctl, 200126261Smlaier .d_poll = drm_poll, 201240233Sglebius .d_mmap = drm_mmap, 202240233Sglebius .d_mmap_single = drm_mmap_single, 203240233Sglebius .d_name = "drm", 204240233Sglebius .d_flags = D_TRACKCLOSE 205240233Sglebius}; 206223637Sbz 207240233Sglebiusstatic int drm_msi = 1; /* Enable by default. */ 208240233SglebiusSYSCTL_NODE(_hw, OID_AUTO, drm, CTLFLAG_RW, NULL, "DRM device"); 209240233SglebiusSYSCTL_INT(_hw_drm, OID_AUTO, msi, CTLFLAG_RDTUN, &drm_msi, 1, 210240233Sglebius "Enable MSI interrupts for drm devices"); 211240233Sglebius 212240233Sglebiusstatic struct drm_msi_blacklist_entry drm_msi_blacklist[] = { 213240233Sglebius {0x8086, 0x2772}, /* Intel i945G */ \ 214240233Sglebius {0x8086, 0x27A2}, /* Intel i945GM */ \ 215240233Sglebius {0x8086, 0x27AE}, /* Intel i945GME */ \ 216126261Smlaier {0, 0} 217240233Sglebius}; 218240233Sglebius 219240233Sglebiusstatic int drm_msi_is_blacklisted(struct drm_device *dev, unsigned long flags) 220126261Smlaier{ 221240233Sglebius int i = 0; 222240233Sglebius 223240233Sglebius if (dev->driver->use_msi != NULL) { 224240233Sglebius int use_msi; 225240233Sglebius 226240233Sglebius use_msi = dev->driver->use_msi(dev, flags); 227240233Sglebius 228240233Sglebius return (!use_msi); 229126261Smlaier } 230223637Sbz 231223637Sbz /* TODO: Maybe move this to a callback in i915? */ 232223637Sbz for (i = 0; drm_msi_blacklist[i].vendor != 0; i++) { 233126261Smlaier if ((drm_msi_blacklist[i].vendor == dev->pci_vendor) && 234223637Sbz (drm_msi_blacklist[i].device == dev->pci_device)) { 235223637Sbz return 1; 236223637Sbz } 237223637Sbz } 238223637Sbz 239223637Sbz return 0; 240240233Sglebius} 241126258Smlaier 242126258Smlaierint drm_probe(device_t kdev, drm_pci_id_list_t *idlist) 243223637Sbz{ 244126258Smlaier drm_pci_id_list_t *id_entry; 245126258Smlaier int vendor, device; 246126258Smlaier 247126258Smlaier vendor = pci_get_vendor(kdev); 248126258Smlaier device = pci_get_device(kdev); 249223637Sbz 250126258Smlaier if (pci_get_class(kdev) != PCIC_DISPLAY 251126258Smlaier || (pci_get_subclass(kdev) != PCIS_DISPLAY_VGA && 252126258Smlaier pci_get_subclass(kdev) != PCIS_DISPLAY_OTHER)) 253126258Smlaier return ENXIO; 254126258Smlaier 255223637Sbz id_entry = drm_find_description(vendor, device, idlist); 256126258Smlaier if (id_entry != NULL) { 257126258Smlaier if (!device_get_desc(kdev)) { 258126258Smlaier DRM_DEBUG("desc : %s\n", device_get_desc(kdev)); 259126258Smlaier device_set_desc(kdev, id_entry->name); 260126258Smlaier } 261223637Sbz return 0; 262126258Smlaier } 263126258Smlaier 264126258Smlaier return ENXIO; 265126258Smlaier} 266126258Smlaier 267126258Smlaierint drm_attach(device_t kdev, drm_pci_id_list_t *idlist) 268126258Smlaier{ 269126258Smlaier struct drm_device *dev; 270126258Smlaier drm_pci_id_list_t *id_entry; 271126258Smlaier int error, msicount; 272126258Smlaier 273126258Smlaier dev = device_get_softc(kdev); 274126258Smlaier 275126258Smlaier dev->device = kdev; 276126258Smlaier 277126258Smlaier dev->pci_domain = pci_get_domain(dev->device); 278126258Smlaier dev->pci_bus = pci_get_bus(dev->device); 279126258Smlaier dev->pci_slot = pci_get_slot(dev->device); 280126258Smlaier dev->pci_func = pci_get_function(dev->device); 281126258Smlaier 282126258Smlaier dev->pci_vendor = pci_get_vendor(dev->device); 283126258Smlaier dev->pci_device = pci_get_device(dev->device); 284126258Smlaier dev->pci_subvendor = pci_get_subvendor(dev->device); 285126258Smlaier dev->pci_subdevice = pci_get_subdevice(dev->device); 286126258Smlaier 287126258Smlaier id_entry = drm_find_description(dev->pci_vendor, 288126258Smlaier dev->pci_device, idlist); 289126258Smlaier dev->id_entry = id_entry; 290126258Smlaier 291126258Smlaier if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) { 292126258Smlaier if (drm_msi && 293126258Smlaier !drm_msi_is_blacklisted(dev, dev->id_entry->driver_private)) { 294126258Smlaier msicount = pci_msi_count(dev->device); 295126258Smlaier DRM_DEBUG("MSI count = %d\n", msicount); 296126258Smlaier if (msicount > 1) 297126258Smlaier msicount = 1; 298126258Smlaier 299126258Smlaier if (pci_alloc_msi(dev->device, &msicount) == 0) { 300126258Smlaier DRM_INFO("MSI enabled %d message(s)\n", 301126258Smlaier msicount); 302126258Smlaier dev->msi_enabled = 1; 303126258Smlaier dev->irqrid = 1; 304126258Smlaier } 305126258Smlaier } 306126258Smlaier 307126258Smlaier dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, 308126258Smlaier &dev->irqrid, RF_SHAREABLE); 309126258Smlaier if (!dev->irqr) { 310126258Smlaier return (ENOENT); 311126258Smlaier } 312126258Smlaier 313126258Smlaier dev->irq = (int) rman_get_start(dev->irqr); 314126258Smlaier } 315126258Smlaier 316126258Smlaier mtx_init(&dev->dev_lock, "drmdev", NULL, MTX_DEF); 317126258Smlaier mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF); 318126258Smlaier mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF); 319126258Smlaier mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF); 320126258Smlaier mtx_init(&dev->event_lock, "drmev", NULL, MTX_DEF); 321126258Smlaier sx_init(&dev->dev_struct_lock, "drmslk"); 322126258Smlaier 323126258Smlaier error = drm_load(dev); 324126258Smlaier if (error) 325126258Smlaier goto error; 326126258Smlaier 327126258Smlaier error = drm_create_cdevs(kdev); 328126258Smlaier if (error) 329126258Smlaier goto error; 330126258Smlaier 331126258Smlaier return (error); 332126258Smlaiererror: 333126258Smlaier if (dev->irqr) { 334126258Smlaier bus_release_resource(dev->device, SYS_RES_IRQ, 335126258Smlaier dev->irqrid, dev->irqr); 336126258Smlaier } 337126258Smlaier if (dev->msi_enabled) { 338126258Smlaier pci_release_msi(dev->device); 339126258Smlaier } 340126258Smlaier return (error); 341126258Smlaier} 342126258Smlaier 343126258Smlaierint 344126258Smlaierdrm_create_cdevs(device_t kdev) 345126258Smlaier{ 346126258Smlaier struct drm_device *dev; 347126258Smlaier int error, unit; 348126258Smlaier 349126258Smlaier unit = device_get_unit(kdev); 350126258Smlaier dev = device_get_softc(kdev); 351126258Smlaier 352126258Smlaier error = make_dev_p(MAKEDEV_WAITOK | MAKEDEV_CHECKNAME, &dev->devnode, 353126258Smlaier &drm_cdevsw, 0, DRM_DEV_UID, DRM_DEV_GID, 354126258Smlaier DRM_DEV_MODE, "dri/card%d", unit); 355126258Smlaier if (error == 0) 356126258Smlaier dev->devnode->si_drv1 = dev; 357126258Smlaier return (error); 358126258Smlaier} 359126258Smlaier 360126258Smlaierint drm_detach(device_t kdev) 361126258Smlaier{ 362126258Smlaier struct drm_device *dev; 363126258Smlaier 364126258Smlaier dev = device_get_softc(kdev); 365126258Smlaier drm_unload(dev); 366126258Smlaier if (dev->irqr) { 367126258Smlaier bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, 368126258Smlaier dev->irqr); 369126258Smlaier if (dev->msi_enabled) { 370231852Sbz pci_release_msi(dev->device); 371231852Sbz DRM_INFO("MSI released\n"); 372231852Sbz } 373231852Sbz } 374231852Sbz return (0); 375171168Smlaier} 376171168Smlaier 377231852Sbz#ifndef DRM_DEV_NAME 378171168Smlaier#define DRM_DEV_NAME "drm" 379231852Sbz#endif 380171168Smlaier 381171168Smlaierdevclass_t drm_devclass; 382171168Smlaier 383223637Sbzdrm_pci_id_list_t *drm_find_description(int vendor, int device, 384223637Sbz drm_pci_id_list_t *idlist) 385223637Sbz{ 386223637Sbz int i = 0; 387171168Smlaier 388171168Smlaier for (i = 0; idlist[i].vendor != 0; i++) { 389171168Smlaier if ((idlist[i].vendor == vendor) && 390171168Smlaier ((idlist[i].device == device) || 391171168Smlaier (idlist[i].device == 0))) { 392126258Smlaier return &idlist[i]; 393126258Smlaier } 394171168Smlaier } 395126258Smlaier return NULL; 396126258Smlaier} 397126258Smlaier 398126258Smlaierstatic int drm_firstopen(struct drm_device *dev) 399126258Smlaier{ 400126258Smlaier drm_local_map_t *map; 401126258Smlaier int i; 402126258Smlaier 403126258Smlaier DRM_LOCK_ASSERT(dev); 404126258Smlaier 405126258Smlaier /* prebuild the SAREA */ 406126258Smlaier i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, 407126258Smlaier _DRM_CONTAINS_LOCK, &map); 408145836Smlaier if (i != 0) 409126258Smlaier return i; 410126258Smlaier 411126258Smlaier if (dev->driver->firstopen) 412126258Smlaier dev->driver->firstopen(dev); 413126258Smlaier 414126258Smlaier dev->buf_use = 0; 415126258Smlaier 416130613Smlaier if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) { 417126258Smlaier i = drm_dma_setup(dev); 418126258Smlaier if (i != 0) 419126258Smlaier return i; 420126258Smlaier } 421126258Smlaier 422126258Smlaier for (i = 0; i < DRM_HASH_SIZE; i++) { 423126258Smlaier dev->magiclist[i].head = NULL; 424126258Smlaier dev->magiclist[i].tail = NULL; 425126258Smlaier } 426126258Smlaier 427126258Smlaier dev->lock.lock_queue = 0; 428126258Smlaier if (!drm_core_check_feature(dev, DRIVER_MODESET)) 429126258Smlaier dev->irq_enabled = 0; 430126258Smlaier dev->context_flag = 0; 431126258Smlaier dev->last_context = 0; 432126258Smlaier dev->if_version = 0; 433126258Smlaier 434126258Smlaier dev->buf_sigio = NULL; 435126258Smlaier 436126258Smlaier DRM_DEBUG("\n"); 437126258Smlaier 438126258Smlaier return 0; 439126258Smlaier} 440126258Smlaier 441126258Smlaierstatic int drm_lastclose(struct drm_device *dev) 442126258Smlaier{ 443126258Smlaier drm_magic_entry_t *pt, *next; 444126258Smlaier drm_local_map_t *map, *mapsave; 445126258Smlaier int i; 446126258Smlaier 447126258Smlaier DRM_LOCK_ASSERT(dev); 448126258Smlaier 449126258Smlaier DRM_DEBUG("\n"); 450126258Smlaier 451126258Smlaier if (dev->driver->lastclose != NULL) 452126258Smlaier dev->driver->lastclose(dev); 453126258Smlaier 454126258Smlaier if (!drm_core_check_feature(dev, DRIVER_MODESET) && dev->irq_enabled) 455126258Smlaier drm_irq_uninstall(dev); 456126258Smlaier 457126258Smlaier if (dev->unique) { 458126258Smlaier free(dev->unique, DRM_MEM_DRIVER); 459126258Smlaier dev->unique = NULL; 460126258Smlaier dev->unique_len = 0; 461126258Smlaier } 462126258Smlaier /* Clear pid list */ 463126258Smlaier for (i = 0; i < DRM_HASH_SIZE; i++) { 464126258Smlaier for (pt = dev->magiclist[i].head; pt; pt = next) { 465126258Smlaier next = pt->next; 466126258Smlaier free(pt, DRM_MEM_MAGIC); 467126258Smlaier } 468126258Smlaier dev->magiclist[i].head = dev->magiclist[i].tail = NULL; 469126258Smlaier } 470126258Smlaier 471126258Smlaier DRM_UNLOCK(dev); 472126258Smlaier drm_drawable_free_all(dev); 473126258Smlaier DRM_LOCK(dev); 474126258Smlaier 475126258Smlaier /* Clear AGP information */ 476126258Smlaier if (dev->agp) { 477126258Smlaier drm_agp_mem_t *entry; 478126258Smlaier drm_agp_mem_t *nexte; 479126258Smlaier 480126258Smlaier /* Remove AGP resources, but leave dev->agp intact until 481126258Smlaier * drm_unload is called. 482126258Smlaier */ 483126258Smlaier for (entry = dev->agp->memory; entry; entry = nexte) { 484126258Smlaier nexte = entry->next; 485126258Smlaier if (entry->bound) 486126258Smlaier drm_agp_unbind_memory(entry->handle); 487126258Smlaier drm_agp_free_memory(entry->handle); 488126258Smlaier free(entry, DRM_MEM_AGPLISTS); 489126258Smlaier } 490126258Smlaier dev->agp->memory = NULL; 491126258Smlaier 492126258Smlaier if (dev->agp->acquired) 493126258Smlaier drm_agp_release(dev); 494126258Smlaier 495126258Smlaier dev->agp->acquired = 0; 496126258Smlaier dev->agp->enabled = 0; 497126258Smlaier } 498126258Smlaier if (dev->sg != NULL) { 499126258Smlaier drm_sg_cleanup(dev->sg); 500126258Smlaier dev->sg = NULL; 501126258Smlaier } 502126258Smlaier 503126258Smlaier TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) { 504126258Smlaier if (!(map->flags & _DRM_DRIVER)) 505126258Smlaier drm_rmmap(dev, map); 506126258Smlaier } 507126258Smlaier 508126258Smlaier drm_dma_takedown(dev); 509126258Smlaier if (dev->lock.hw_lock) { 510126258Smlaier dev->lock.hw_lock = NULL; /* SHM removed */ 511171168Smlaier dev->lock.file_priv = NULL; 512126258Smlaier DRM_WAKEUP_INT((void *)&dev->lock.lock_queue); 513126258Smlaier } 514126258Smlaier 515126258Smlaier return 0; 516126258Smlaier} 517126258Smlaier 518126258Smlaierstatic int drm_load(struct drm_device *dev) 519126258Smlaier{ 520126258Smlaier int i, retcode; 521126258Smlaier 522126258Smlaier DRM_DEBUG("\n"); 523126258Smlaier 524126258Smlaier TAILQ_INIT(&dev->maplist); 525126258Smlaier dev->map_unrhdr = new_unrhdr(1, ((1 << DRM_MAP_HANDLE_BITS) - 1), NULL); 526126258Smlaier if (dev->map_unrhdr == NULL) { 527126258Smlaier DRM_ERROR("Couldn't allocate map number allocator\n"); 528126258Smlaier return EINVAL; 529126258Smlaier } 530126258Smlaier 531126258Smlaier 532126258Smlaier drm_mem_init(); 533126258Smlaier drm_sysctl_init(dev); 534126258Smlaier TAILQ_INIT(&dev->files); 535126258Smlaier 536126258Smlaier dev->counters = 6; 537126258Smlaier dev->types[0] = _DRM_STAT_LOCK; 538126258Smlaier dev->types[1] = _DRM_STAT_OPENS; 539126258Smlaier dev->types[2] = _DRM_STAT_CLOSES; 540126258Smlaier dev->types[3] = _DRM_STAT_IOCTLS; 541126258Smlaier dev->types[4] = _DRM_STAT_LOCKS; 542126258Smlaier dev->types[5] = _DRM_STAT_UNLOCKS; 543126258Smlaier 544126258Smlaier for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++) 545126258Smlaier atomic_set(&dev->counts[i], 0); 546126258Smlaier 547126258Smlaier INIT_LIST_HEAD(&dev->vblank_event_list); 548126258Smlaier 549126258Smlaier if (drm_core_has_AGP(dev)) { 550145836Smlaier if (drm_device_is_agp(dev)) 551145836Smlaier dev->agp = drm_agp_init(); 552126258Smlaier if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && 553126258Smlaier dev->agp == NULL) { 554126258Smlaier DRM_ERROR("Card isn't AGP, or couldn't initialize " 555126258Smlaier "AGP.\n"); 556126258Smlaier retcode = ENOMEM; 557126258Smlaier goto error; 558126258Smlaier } 559126258Smlaier if (dev->agp != NULL && dev->agp->info.ai_aperture_base != 0) { 560126258Smlaier if (drm_mtrr_add(dev->agp->info.ai_aperture_base, 561126258Smlaier dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0) 562126258Smlaier dev->agp->mtrr = 1; 563126258Smlaier } 564126258Smlaier } 565126258Smlaier 566126258Smlaier retcode = drm_ctxbitmap_init(dev); 567171168Smlaier if (retcode != 0) { 568126258Smlaier DRM_ERROR("Cannot allocate memory for context bitmap.\n"); 569126258Smlaier goto error; 570126258Smlaier } 571171168Smlaier 572126258Smlaier dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL); 573126258Smlaier if (dev->drw_unrhdr == NULL) { 574126258Smlaier DRM_ERROR("Couldn't allocate drawable number allocator\n"); 575145836Smlaier retcode = ENOMEM; 576145836Smlaier goto error; 577126258Smlaier } 578126258Smlaier 579126258Smlaier if (dev->driver->driver_features & DRIVER_GEM) { 580126258Smlaier retcode = drm_gem_init(dev); 581171168Smlaier if (retcode != 0) { 582171168Smlaier DRM_ERROR("Cannot initialize graphics execution " 583126258Smlaier "manager (GEM)\n"); 584130613Smlaier goto error1; 585126258Smlaier } 586145836Smlaier } 587126258Smlaier 588126258Smlaier if (dev->driver->load != NULL) { 589130613Smlaier DRM_LOCK(dev); 590171168Smlaier /* Shared code returns -errno. */ 591130613Smlaier retcode = -dev->driver->load(dev, 592223637Sbz dev->id_entry->driver_private); 593223637Sbz if (pci_enable_busmaster(dev->device)) 594126258Smlaier DRM_ERROR("Request to enable bus-master failed.\n"); 595130613Smlaier DRM_UNLOCK(dev); 596130613Smlaier if (retcode != 0) 597130613Smlaier goto error1; 598223637Sbz } 599145836Smlaier 600145836Smlaier DRM_INFO("Initialized %s %d.%d.%d %s\n", 601145836Smlaier dev->driver->name, 602145836Smlaier dev->driver->major, 603145836Smlaier dev->driver->minor, 604126258Smlaier dev->driver->patchlevel, 605126258Smlaier dev->driver->date); 606126258Smlaier 607126258Smlaier return 0; 608145836Smlaier 609171168Smlaiererror1: 610171168Smlaier delete_unrhdr(dev->drw_unrhdr); 611126258Smlaier drm_gem_destroy(dev); 612126258Smlaiererror: 613126258Smlaier drm_ctxbitmap_cleanup(dev); 614126258Smlaier drm_sysctl_cleanup(dev); 615126258Smlaier DRM_LOCK(dev); 616126258Smlaier drm_lastclose(dev); 617223637Sbz DRM_UNLOCK(dev); 618126258Smlaier if (dev->devnode != NULL) 619126258Smlaier destroy_dev(dev->devnode); 620126258Smlaier 621126258Smlaier mtx_destroy(&dev->drw_lock); 622126258Smlaier mtx_destroy(&dev->vbl_lock); 623126258Smlaier mtx_destroy(&dev->irq_lock); 624126258Smlaier mtx_destroy(&dev->dev_lock); 625126258Smlaier mtx_destroy(&dev->event_lock); 626171168Smlaier sx_destroy(&dev->dev_struct_lock); 627126258Smlaier 628126258Smlaier return retcode; 629126258Smlaier} 630126258Smlaier 631126258Smlaierstatic void drm_unload(struct drm_device *dev) 632126258Smlaier{ 633126258Smlaier int i; 634126258Smlaier 635126258Smlaier DRM_DEBUG("\n"); 636126258Smlaier 637126258Smlaier drm_sysctl_cleanup(dev); 638126258Smlaier if (dev->devnode != NULL) 639126258Smlaier destroy_dev(dev->devnode); 640126258Smlaier 641126258Smlaier drm_ctxbitmap_cleanup(dev); 642126258Smlaier 643126258Smlaier if (dev->driver->driver_features & DRIVER_GEM) 644126258Smlaier drm_gem_destroy(dev); 645126258Smlaier 646126258Smlaier if (dev->agp && dev->agp->mtrr) { 647223637Sbz int __unused retcode; 648145836Smlaier 649145836Smlaier retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base, 650145836Smlaier dev->agp->info.ai_aperture_size, DRM_MTRR_WC); 651145836Smlaier DRM_DEBUG("mtrr_del = %d", retcode); 652145836Smlaier } 653145836Smlaier 654223637Sbz drm_vblank_cleanup(dev); 655223637Sbz 656223637Sbz DRM_LOCK(dev); 657223637Sbz drm_lastclose(dev); 658223637Sbz DRM_UNLOCK(dev); 659126258Smlaier 660126258Smlaier /* Clean up PCI resources allocated by drm_bufs.c. We're not really 661126258Smlaier * worried about resource consumption while the DRM is inactive (between 662126258Smlaier * lastclose and firstopen or unload) because these aren't actually 663126258Smlaier * taking up KVA, just keeping the PCI resource allocated. 664126258Smlaier */ 665126258Smlaier for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) { 666126258Smlaier if (dev->pcir[i] == NULL) 667130613Smlaier continue; 668130613Smlaier bus_release_resource(dev->device, SYS_RES_MEMORY, 669130613Smlaier dev->pcirid[i], dev->pcir[i]); 670240233Sglebius dev->pcir[i] = NULL; 671126258Smlaier } 672126258Smlaier 673126258Smlaier if (dev->agp) { 674126258Smlaier free(dev->agp, DRM_MEM_AGPLISTS); 675126258Smlaier dev->agp = NULL; 676126258Smlaier } 677126258Smlaier 678223637Sbz if (dev->driver->unload != NULL) { 679126258Smlaier DRM_LOCK(dev); 680130613Smlaier dev->driver->unload(dev); 681130613Smlaier DRM_UNLOCK(dev); 682200930Sdelphij } 683130613Smlaier 684126258Smlaier delete_unrhdr(dev->drw_unrhdr); 685171168Smlaier delete_unrhdr(dev->map_unrhdr); 686171168Smlaier 687126258Smlaier drm_mem_uninit(); 688145836Smlaier 689145836Smlaier if (pci_disable_busmaster(dev->device)) 690145836Smlaier DRM_ERROR("Request to disable bus-master failed.\n"); 691145836Smlaier 692145836Smlaier mtx_destroy(&dev->drw_lock); 693145836Smlaier mtx_destroy(&dev->vbl_lock); 694145836Smlaier mtx_destroy(&dev->irq_lock); 695145836Smlaier mtx_destroy(&dev->dev_lock); 696145836Smlaier mtx_destroy(&dev->event_lock); 697145836Smlaier sx_destroy(&dev->dev_struct_lock); 698130613Smlaier} 699240233Sglebius 700130613Smlaierint drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv) 701130613Smlaier{ 702130613Smlaier struct drm_version *version = data; 703130613Smlaier int len; 704171168Smlaier 705171168Smlaier#define DRM_COPY( name, value ) \ 706130613Smlaier len = strlen( value ); \ 707145836Smlaier if ( len > name##_len ) len = name##_len; \ 708145836Smlaier name##_len = strlen( value ); \ 709130613Smlaier if ( len && name ) { \ 710130613Smlaier if ( DRM_COPY_TO_USER( name, value, len ) ) \ 711130613Smlaier return EFAULT; \ 712130613Smlaier } 713130613Smlaier 714126258Smlaier version->version_major = dev->driver->major; 715130613Smlaier version->version_minor = dev->driver->minor; 716130613Smlaier version->version_patchlevel = dev->driver->patchlevel; 717126258Smlaier 718145836Smlaier DRM_COPY(version->name, dev->driver->name); 719145836Smlaier DRM_COPY(version->date, dev->driver->date); 720145836Smlaier DRM_COPY(version->desc, dev->driver->desc); 721145836Smlaier 722126258Smlaier return 0; 723145836Smlaier} 724145836Smlaier 725145836Smlaierint 726145836Smlaierdrm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p) 727145836Smlaier{ 728145836Smlaier struct drm_device *dev; 729126258Smlaier int retcode; 730145836Smlaier 731126258Smlaier dev = kdev->si_drv1; 732126258Smlaier if (dev == NULL) 733126258Smlaier return (ENXIO); 734126258Smlaier 735126258Smlaier DRM_DEBUG("open_count = %d\n", dev->open_count); 736126258Smlaier 737126258Smlaier retcode = drm_open_helper(kdev, flags, fmt, p, dev); 738126258Smlaier 739126258Smlaier if (retcode == 0) { 740223637Sbz atomic_inc(&dev->counts[_DRM_STAT_OPENS]); 741126258Smlaier DRM_LOCK(dev); 742126258Smlaier mtx_lock(&Giant); 743126258Smlaier device_busy(dev->device); 744126258Smlaier mtx_unlock(&Giant); 745223637Sbz if (!dev->open_count++) 746126258Smlaier retcode = drm_firstopen(dev); 747126258Smlaier DRM_UNLOCK(dev); 748171168Smlaier } 749223637Sbz 750126258Smlaier return (retcode); 751126258Smlaier} 752240233Sglebius 753223637Sbzvoid drm_close(void *data) 754223637Sbz{ 755223637Sbz struct drm_file *file_priv = data; 756171168Smlaier struct drm_device *dev = file_priv->dev; 757171168Smlaier int retcode = 0; 758223637Sbz 759171168Smlaier DRM_DEBUG("open_count = %d\n", dev->open_count); 760171168Smlaier 761223637Sbz DRM_LOCK(dev); 762223637Sbz 763223637Sbz if (dev->driver->preclose != NULL) 764223637Sbz dev->driver->preclose(dev, file_priv); 765223637Sbz 766223637Sbz /* ======================================================== 767223637Sbz * Begin inline drm_release 768240233Sglebius */ 769240233Sglebius 770223637Sbz DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", 771223637Sbz DRM_CURRENTPID, (long)dev->device, dev->open_count); 772240233Sglebius 773223637Sbz if (dev->driver->driver_features & DRIVER_GEM) 774223637Sbz drm_gem_release(dev, file_priv); 775223637Sbz 776223637Sbz if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) 777223637Sbz && dev->lock.file_priv == file_priv) { 778223637Sbz DRM_DEBUG("Process %d dead, freeing lock for context %d\n", 779223637Sbz DRM_CURRENTPID, 780126258Smlaier _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); 781223637Sbz if (dev->driver->reclaim_buffers_locked != NULL) 782223637Sbz dev->driver->reclaim_buffers_locked(dev, file_priv); 783223637Sbz 784223637Sbz drm_lock_free(&dev->lock, 785223637Sbz _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); 786240233Sglebius 787223637Sbz /* FIXME: may require heavy-handed reset of 788240233Sglebius hardware at this point, possibly 789240233Sglebius processed via a callback to the X 790223637Sbz server. */ 791223637Sbz } else if (dev->driver->reclaim_buffers_locked != NULL && 792223637Sbz dev->lock.hw_lock != NULL) { 793223637Sbz /* The lock is required to reclaim buffers */ 794223637Sbz for (;;) { 795223637Sbz if (!dev->lock.hw_lock) { 796223637Sbz /* Device has been unregistered */ 797223637Sbz retcode = EINTR; 798223637Sbz break; 799223637Sbz } 800223637Sbz if (drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) { 801223637Sbz dev->lock.file_priv = file_priv; 802223637Sbz dev->lock.lock_time = jiffies; 803223637Sbz atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); 804223637Sbz break; /* Got lock */ 805223637Sbz } 806223637Sbz /* Contention */ 807223637Sbz retcode = DRM_LOCK_SLEEP(dev, &dev->lock.lock_queue, 808223637Sbz PCATCH, "drmlk2", 0); 809223637Sbz if (retcode) 810223637Sbz break; 811240233Sglebius } 812223637Sbz if (retcode == 0) { 813223637Sbz dev->driver->reclaim_buffers_locked(dev, file_priv); 814223637Sbz drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT); 815223637Sbz } 816223637Sbz } 817223637Sbz 818223637Sbz if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && 819223637Sbz !dev->driver->reclaim_buffers_locked) 820223637Sbz drm_reclaim_buffers(dev, file_priv); 821223637Sbz 822223637Sbz funsetown(&dev->buf_sigio); 823223637Sbz seldrain(&file_priv->event_poll); 824223637Sbz 825223637Sbz if (dev->driver->postclose != NULL) 826223637Sbz dev->driver->postclose(dev, file_priv); 827223637Sbz TAILQ_REMOVE(&dev->files, file_priv, link); 828223637Sbz free(file_priv, DRM_MEM_FILES); 829223637Sbz 830223637Sbz /* ======================================================== 831223637Sbz * End inline drm_release 832223637Sbz */ 833223637Sbz 834223637Sbz atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); 835223637Sbz mtx_lock(&Giant); 836223637Sbz device_unbusy(dev->device); 837223637Sbz mtx_unlock(&Giant); 838223637Sbz if (--dev->open_count == 0) { 839223637Sbz retcode = drm_lastclose(dev); 840223637Sbz } 841223637Sbz 842223637Sbz DRM_UNLOCK(dev); 843223637Sbz} 844223637Sbz 845223637Sbzextern drm_ioctl_desc_t drm_compat_ioctls[]; 846223637Sbz 847223637Sbz/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. 848223637Sbz */ 849223637Sbzint drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, 850223637Sbz DRM_STRUCTPROC *p) 851223637Sbz{ 852240233Sglebius struct drm_device *dev = drm_get_device_from_kdev(kdev); 853223637Sbz int retcode = 0; 854223637Sbz drm_ioctl_desc_t *ioctl; 855223637Sbz int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv); 856223637Sbz int nr = DRM_IOCTL_NR(cmd); 857223637Sbz int is_driver_ioctl = 0; 858223637Sbz struct drm_file *file_priv; 859223637Sbz 860223637Sbz retcode = devfs_get_cdevpriv((void **)&file_priv); 861223637Sbz if (retcode != 0) { 862223637Sbz DRM_ERROR("can't find authenticator\n"); 863223637Sbz return EINVAL; 864223637Sbz } 865171168Smlaier 866171168Smlaier atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); 867171168Smlaier ++file_priv->ioctl_count; 868171168Smlaier 869240233Sglebius DRM_DEBUG("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n", 870171168Smlaier DRM_CURRENTPID, cmd, nr, (long)dev->device, 871200930Sdelphij file_priv->authenticated); 872171168Smlaier 873171168Smlaier switch (cmd) { 874223637Sbz case FIONBIO: 875223637Sbz case FIOASYNC: 876126258Smlaier return 0; 877223637Sbz 878223637Sbz case FIOSETOWN: 879223637Sbz return fsetown(*(int *)data, &dev->buf_sigio); 880223637Sbz 881223637Sbz case FIOGETOWN: 882223637Sbz *(int *) data = fgetown(&dev->buf_sigio); 883223637Sbz return 0; 884223637Sbz } 885223637Sbz 886223637Sbz if (IOCGROUP(cmd) != DRM_IOCTL_BASE) { 887223637Sbz DRM_DEBUG("Bad ioctl group 0x%x\n", (int)IOCGROUP(cmd)); 888223637Sbz return EINVAL; 889223637Sbz } 890223637Sbz 891223637Sbz#ifdef COMPAT_FREEBSD32 892223637Sbz /* 893223637Sbz * Called whenever a 32-bit process running under a 64-bit 894223637Sbz * kernel performs an ioctl on /dev/drm. 895223637Sbz */ 896223637Sbz if (SV_CURPROC_FLAG(SV_ILP32) && drm_compat_ioctls[nr].func != NULL) 897223637Sbz /* 898223637Sbz * Assume that ioctls without an explicit compat 899223637Sbz * routine will just work. This may not always be a 900223637Sbz * good assumption, but it's better than always 901240233Sglebius * failing. 902223637Sbz */ 903223637Sbz ioctl = &drm_compat_ioctls[nr]; 904223637Sbz else 905240233Sglebius#endif 906223637Sbz ioctl = &drm_ioctls[nr]; 907223637Sbz /* It's not a core DRM ioctl, try driver-specific. */ 908223637Sbz if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) { 909223637Sbz /* The array entries begin at DRM_COMMAND_BASE ioctl nr */ 910223637Sbz nr -= DRM_COMMAND_BASE; 911223637Sbz if (nr >= dev->driver->max_ioctl) { 912223637Sbz DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n", 913223637Sbz nr, dev->driver->max_ioctl); 914223637Sbz return EINVAL; 915223637Sbz } 916223637Sbz#ifdef COMPAT_FREEBSD32 917223637Sbz if (SV_CURPROC_FLAG(SV_ILP32) && 918223637Sbz nr < *dev->driver->compat_ioctls_nr && 919223637Sbz dev->driver->compat_ioctls[nr].func != NULL) 920223637Sbz ioctl = &dev->driver->compat_ioctls[nr]; 921223637Sbz else 922223637Sbz#endif 923223637Sbz ioctl = &dev->driver->ioctls[nr]; 924223637Sbz is_driver_ioctl = 1; 925223637Sbz } 926223637Sbz func = ioctl->func; 927223637Sbz 928223637Sbz if (func == NULL) { 929223637Sbz DRM_DEBUG("no function\n"); 930223637Sbz return EINVAL; 931223637Sbz } 932223637Sbz 933223637Sbz if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) || 934223637Sbz ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || 935223637Sbz ((ioctl->flags & DRM_MASTER) && !file_priv->master)) 936223637Sbz return EACCES; 937223637Sbz 938223637Sbz if (is_driver_ioctl) { 939223637Sbz if ((ioctl->flags & DRM_UNLOCKED) == 0) 940223637Sbz DRM_LOCK(dev); 941223637Sbz /* shared code returns -errno */ 942223637Sbz retcode = -func(dev, data, file_priv); 943223637Sbz if ((ioctl->flags & DRM_UNLOCKED) == 0) 944223637Sbz DRM_UNLOCK(dev); 945223637Sbz } else { 946223637Sbz retcode = func(dev, data, file_priv); 947223637Sbz } 948223637Sbz 949223637Sbz if (retcode != 0) 950223637Sbz DRM_DEBUG(" returning %d\n", retcode); 951223637Sbz if (retcode != 0 && 952223637Sbz (drm_debug_flag & DRM_DEBUGBITS_FAILED_IOCTL) != 0) { 953223637Sbz printf( 954223637Sbz"pid %d, cmd 0x%02lx, nr 0x%02x/%1d, dev 0x%lx, auth %d, res %d\n", 955223637Sbz DRM_CURRENTPID, cmd, nr, is_driver_ioctl, (long)dev->device, 956223637Sbz file_priv->authenticated, retcode); 957223637Sbz } 958223637Sbz 959223637Sbz return retcode; 960126258Smlaier} 961126258Smlaier 962126258Smlaierdrm_local_map_t *drm_getsarea(struct drm_device *dev) 963126258Smlaier{ 964126258Smlaier drm_local_map_t *map; 965126258Smlaier 966126258Smlaier DRM_LOCK_ASSERT(dev); 967126258Smlaier TAILQ_FOREACH(map, &dev->maplist, link) { 968126258Smlaier if (map->type == _DRM_SHM && (map->flags & _DRM_CONTAINS_LOCK)) 969171168Smlaier return map; 970171168Smlaier } 971126258Smlaier 972130613Smlaier return NULL; 973126258Smlaier} 974126258Smlaier 975126258Smlaierint 976126258Smlaierdrm_add_busid_modesetting(struct drm_device *dev, struct sysctl_ctx_list *ctx, 977126258Smlaier struct sysctl_oid *top) 978126258Smlaier{ 979126258Smlaier struct sysctl_oid *oid; 980126258Smlaier 981145836Smlaier snprintf(dev->busid_str, sizeof(dev->busid_str), 982145836Smlaier "pci:%04x:%02x:%02x.%d", dev->pci_domain, dev->pci_bus, 983126258Smlaier dev->pci_slot, dev->pci_func); 984145836Smlaier oid = SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "busid", 985145836Smlaier CTLFLAG_RD, dev->busid_str, 0, NULL); 986145836Smlaier if (oid == NULL) 987145836Smlaier return (ENOMEM); 988126258Smlaier dev->modesetting = (dev->driver->driver_features & DRIVER_MODESET) != 0; 989145836Smlaier oid = SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(top), OID_AUTO, 990145836Smlaier "modesetting", CTLFLAG_RD, &dev->modesetting, 0, NULL); 991145836Smlaier if (oid == NULL) 992171168Smlaier return (ENOMEM); 993126258Smlaier 994145836Smlaier return (0); 995145836Smlaier} 996126258Smlaier 997130613Smlaierstatic int 998130613Smlaierdrm_mmap_single(struct cdev *kdev, vm_ooffset_t *offset, vm_size_t size, 999126258Smlaier struct vm_object **obj_res, int nprot) 1000126258Smlaier{ 1001126258Smlaier struct drm_device *dev; 1002126258Smlaier 1003126258Smlaier dev = drm_get_device_from_kdev(kdev); 1004126258Smlaier if (dev->drm_ttm_bdev != NULL) { 1005223637Sbz return (ttm_bo_mmap_single(dev->drm_ttm_bdev, offset, size, 1006223637Sbz obj_res, nprot)); 1007240233Sglebius } else if ((dev->driver->driver_features & DRIVER_GEM) != 0) { 1008240233Sglebius return (drm_gem_mmap_single(dev, offset, size, obj_res, nprot)); 1009240233Sglebius } else { 1010240233Sglebius return (ENODEV); 1011240233Sglebius } 1012240233Sglebius} 1013240233Sglebius 1014240233Sglebius#if DRM_LINUX 1015240233Sglebius 1016240233Sglebius#include <sys/sysproto.h> 1017240233Sglebius 1018240233SglebiusMODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1); 1019240233Sglebius 1020240233Sglebius#define LINUX_IOCTL_DRM_MIN 0x6400 1021126258Smlaier#define LINUX_IOCTL_DRM_MAX 0x64ff 1022126258Smlaier 1023145836Smlaierstatic linux_ioctl_function_t drm_linux_ioctl; 1024126258Smlaierstatic struct linux_ioctl_handler drm_handler = {drm_linux_ioctl, 1025126258Smlaier LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX}; 1026126258Smlaier 1027126258Smlaier/* The bits for in/out are switched on Linux */ 1028126258Smlaier#define LINUX_IOC_IN IOC_OUT 1029126258Smlaier#define LINUX_IOC_OUT IOC_IN 1030126258Smlaier 1031223637Sbzstatic int 1032126258Smlaierdrm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args) 1033126258Smlaier{ 1034126258Smlaier int error; 1035126258Smlaier int cmd = args->cmd; 1036126258Smlaier 1037126258Smlaier args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT); 1038126258Smlaier if (cmd & LINUX_IOC_IN) 1039126258Smlaier args->cmd |= IOC_IN; 1040126258Smlaier if (cmd & LINUX_IOC_OUT) 1041126258Smlaier args->cmd |= IOC_OUT; 1042126258Smlaier 1043126258Smlaier error = ioctl(p, (struct ioctl_args *)args); 1044126258Smlaier 1045126258Smlaier return error; 1046126258Smlaier} 1047126258Smlaier#endif /* DRM_LINUX */ 1048126258Smlaier 1049126258Smlaier 1050126258Smlaierstatic int 1051126258Smlaierdrm_core_init(void *arg) 1052126258Smlaier{ 1053126258Smlaier 1054126258Smlaier drm_global_init(); 1055126258Smlaier 1056126258Smlaier#if DRM_LINUX 1057126258Smlaier linux_ioctl_register_handler(&drm_handler); 1058126258Smlaier#endif /* DRM_LINUX */ 1059126258Smlaier 1060126258Smlaier DRM_INFO("Initialized %s %d.%d.%d %s\n", 1061126258Smlaier CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE); 1062126258Smlaier return 0; 1063126258Smlaier} 1064126258Smlaier 1065126258Smlaierstatic void 1066126258Smlaierdrm_core_exit(void *arg) 1067126258Smlaier{ 1068126258Smlaier 1069126258Smlaier#if DRM_LINUX 1070126258Smlaier linux_ioctl_unregister_handler(&drm_handler); 1071126258Smlaier#endif /* DRM_LINUX */ 1072135615Smlaier 1073135615Smlaier drm_global_release(); 1074135615Smlaier} 1075135615Smlaier 1076135615SmlaierSYSINIT(drm_register, SI_SUB_KLD, SI_ORDER_MIDDLE, 1077135615Smlaier drm_core_init, NULL); 1078135615SmlaierSYSUNINIT(drm_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, 1079135615Smlaier drm_core_exit, NULL); 1080135615Smlaier 1081223637Sbzstatic bool 1082223637Sbzdmi_found(const struct dmi_system_id *dsi) 1083223637Sbz{ 1084223637Sbz char *hw_vendor, *hw_prod; 1085223637Sbz int i, slot; 1086126258Smlaier bool res; 1087126258Smlaier 1088126258Smlaier hw_vendor = kern_getenv("smbios.planar.maker"); 1089126258Smlaier hw_prod = kern_getenv("smbios.planar.product"); 1090126258Smlaier res = true; 1091240233Sglebius for (i = 0; i < nitems(dsi->matches); i++) { 1092126258Smlaier slot = dsi->matches[i].slot; 1093126258Smlaier switch (slot) { 1094126258Smlaier case DMI_NONE: 1095126258Smlaier break; 1096126258Smlaier case DMI_SYS_VENDOR: 1097126258Smlaier case DMI_BOARD_VENDOR: 1098126258Smlaier if (hw_vendor != NULL && 1099126258Smlaier !strcmp(hw_vendor, dsi->matches[i].substr)) { 1100126258Smlaier break; 1101126258Smlaier } else { 1102126258Smlaier res = false; 1103126258Smlaier goto out; 1104126258Smlaier } 1105126258Smlaier case DMI_PRODUCT_NAME: 1106126258Smlaier case DMI_BOARD_NAME: 1107126258Smlaier if (hw_prod != NULL && 1108126258Smlaier !strcmp(hw_prod, dsi->matches[i].substr)) { 1109126258Smlaier break; 1110130613Smlaier } else { 1111126258Smlaier res = false; 1112126258Smlaier goto out; 1113126258Smlaier } 1114126258Smlaier default: 1115130613Smlaier res = false; 1116130613Smlaier goto out; 1117126258Smlaier } 1118126258Smlaier } 1119126258Smlaierout: 1120126258Smlaier freeenv(hw_vendor); 1121126258Smlaier freeenv(hw_prod); 1122126258Smlaier 1123126258Smlaier return (res); 1124126258Smlaier} 1125126258Smlaier 1126171168Smlaierbool 1127171168Smlaierdmi_check_system(const struct dmi_system_id *sysid) 1128171168Smlaier{ 1129130613Smlaier const struct dmi_system_id *dsi; 1130130613Smlaier bool res; 1131130613Smlaier 1132171168Smlaier for (res = false, dsi = sysid; dsi->matches[0].slot != 0 ; dsi++) { 1133240233Sglebius if (dmi_found(dsi)) { 1134240233Sglebius res = true; 1135240233Sglebius if (dsi->callback != NULL && dsi->callback(dsi)) 1136240233Sglebius break; 1137240233Sglebius } 1138240233Sglebius } 1139171168Smlaier return (res); 1140171168Smlaier} 1141171168Smlaier