1 /*
   2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 /*
   6  * radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
   7  * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
   8  */
   9 /*
  10  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  11  * All Rights Reserved.
  12  *
  13  * Permission is hereby granted, free of charge, to any person obtaining a
  14  * copy of this software and associated documentation files (the "Software"),
  15  * to deal in the Software without restriction, including without limitation
  16  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  17  * and/or sell copies of the Software, and to permit persons to whom the
  18  * Software is furnished to do so, subject to the following conditions:
  19  *
  20  * The above copyright notice and this permission notice (including the next
  21  * paragraph) shall be included in all copies or substantial portions of the
  22  * Software.
  23  *
  24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  27  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  28  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  29  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  30  * OTHER DEALINGS IN THE SOFTWARE.
  31  *
  32  * Authors:
  33  *    Gareth Hughes <gareth@valinux.com>
  34  *
  35  */
  36 
  37 #include "drmP.h"
  38 #include "drm.h"
  39 #include "radeon_drm.h"
  40 #include "radeon_drv.h"
  41 #include "drm_pciids.h"
  42 
  43 int radeon_no_wb = 1;
  44 
  45 /*
  46  * cb_ops entrypoint
  47  */
  48 extern struct cb_ops drm_cb_ops;
  49 
  50 /* drv_PCI_IDs comes from drm_pciids.h */
  51 static drm_pci_id_list_t radeon_pciidlist[] = {
  52         radeon_PCI_IDS
  53 };
  54 
  55 /*
  56  * module entrypoint
  57  */
  58 static int radeon_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
  59 static int radeon_attach(dev_info_t *, ddi_attach_cmd_t);
  60 static int radeon_detach(dev_info_t *, ddi_detach_cmd_t);
  61 
  62 extern void radeon_init_ioctl_arrays(void);
  63 extern uint_t radeon_driver_irq_handler(caddr_t);
  64 extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
  65 
  66 /*
  67  * Local routines
  68  */
  69 static void radeon_configure(drm_driver_t *);
  70 
  71 /*
  72  * DRM driver
  73  */
  74 static drm_driver_t     radeon_driver = {0};
  75 
  76 static struct dev_ops radeon_dev_ops = {
  77         DEVO_REV,                       /* devo_rev */
  78         0,                              /* devo_refcnt */
  79         radeon_info,                    /* devo_getinfo */
  80         nulldev,                        /* devo_identify */
  81         nulldev,                        /* devo_probe */
  82         radeon_attach,                  /* devo_attach */
  83         radeon_detach,                  /* devo_detach */
  84         nodev,                          /* devo_reset */
  85         &drm_cb_ops,                        /* devo_cb_ops */
  86         NULL,                           /* devo_bus_ops */
  87         NULL,                           /* power */
  88         ddi_quiesce_not_supported,      /* devo_quiesce */
  89 };
  90 
  91 static struct modldrv modldrv = {
  92         &mod_driverops,                     /* drv_modops */
  93         "radeon DRM driver",            /* drv_linkinfo */
  94         &radeon_dev_ops,                    /* drv_dev_ops */
  95 };
  96 
  97 static struct modlinkage modlinkage = {
  98         MODREV_1, (void *) &modldrv, NULL
  99 };
 100 
 101 
 102 /*
 103  * softstate head
 104  */
 105 static void     *radeon_statep;
 106 
 107 int
 108 _init(void)
 109 {
 110         int error;
 111 
 112         radeon_configure(&radeon_driver);
 113 
 114         if ((error = ddi_soft_state_init(&radeon_statep,
 115             sizeof (drm_device_t), DRM_MAX_INSTANCES)) != 0)
 116                 return (error);
 117 
 118         if ((error = mod_install(&modlinkage)) != 0) {
 119                 ddi_soft_state_fini(&radeon_statep);
 120                 return (error);
 121         }
 122 
 123         return (error);
 124 
 125 }       /* _init() */
 126 
 127 int
 128 _fini(void)
 129 {
 130         int error;
 131 
 132         if ((error = mod_remove(&modlinkage)) != 0)
 133                 return (error);
 134 
 135         (void) ddi_soft_state_fini(&radeon_statep);
 136 
 137         return (0);
 138 
 139 }       /* _fini() */
 140 
 141 int
 142 _info(struct modinfo *modinfop)
 143 {
 144         return (mod_info(&modlinkage, modinfop));
 145 
 146 }       /* _info() */
 147 
 148 
 149 static int
 150 radeon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 151 {
 152         drm_device_t    *statep;
 153         void            *handle;
 154         int             unit;
 155 
 156         if (cmd != DDI_ATTACH) {
 157                 DRM_ERROR("radeon_attach: only attach op supported");
 158                 return (DDI_FAILURE);
 159         }
 160 
 161         unit =  ddi_get_instance(dip);
 162         if (ddi_soft_state_zalloc(radeon_statep, unit) != DDI_SUCCESS) {
 163                 cmn_err(CE_WARN,
 164                     "radeon_attach: alloc softstate failed unit=%d", unit);
 165                 return (DDI_FAILURE);
 166         }
 167         statep = ddi_get_soft_state(radeon_statep, unit);
 168         statep->dip = dip;
 169         statep->driver = &radeon_driver;
 170 
 171         /*
 172          * Call drm_supp_register to create minor nodes for us
 173          */
 174         handle = drm_supp_register(dip, statep);
 175         if (handle == NULL) {
 176                 DRM_ERROR("radeon_attach: drm_supp_register failed");
 177                 goto err_exit1;
 178         }
 179         statep->drm_handle = handle;
 180 
 181         /*
 182          * After drm_supp_register, we can call drm_xxx routine
 183          */
 184         statep->drm_supported = DRM_UNSUPPORT;
 185         if (drm_probe(statep, radeon_pciidlist) != DDI_SUCCESS) {
 186                 DRM_ERROR("radeon_open: "
 187                     "DRM current don't support this graphics card");
 188                 goto err_exit2;
 189         }
 190         statep->drm_supported = DRM_SUPPORT;
 191 
 192         /* call common attach code */
 193         if (drm_attach(statep) != DDI_SUCCESS) {
 194                 DRM_ERROR("radeon_attach: drm_attach failed");
 195                 goto err_exit2;
 196         }
 197         return (DDI_SUCCESS);
 198 
 199 err_exit2:
 200         (void) drm_supp_unregister(handle);
 201 err_exit1:
 202         (void) ddi_soft_state_free(radeon_statep, unit);
 203         return (DDI_FAILURE);
 204 
 205 }       /* radeon_attach() */
 206 
 207 static int
 208 radeon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 209 {
 210         drm_device_t    *statep;
 211         int                     unit;
 212 
 213         if (cmd != DDI_DETACH)
 214                 return (DDI_FAILURE);
 215 
 216         unit =  ddi_get_instance(dip);
 217         statep = ddi_get_soft_state(radeon_statep, unit);
 218         if (statep == NULL)
 219                 return (DDI_FAILURE);
 220 
 221         (void) drm_detach(statep);
 222         (void) drm_supp_unregister(statep->drm_handle);
 223         (void) ddi_soft_state_free(radeon_statep, unit);
 224 
 225         return (DDI_SUCCESS);
 226 
 227 }       /* radeon_detach() */
 228 
 229 /*ARGSUSED*/
 230 static int
 231 radeon_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
 232 {
 233         drm_device_t    *statep;
 234         int             error = DDI_SUCCESS;
 235         int             unit;
 236 
 237         unit = drm_dev_to_instance((dev_t)arg);
 238         switch (infocmd) {
 239         case DDI_INFO_DEVT2DEVINFO:
 240                 statep = ddi_get_soft_state(radeon_statep, unit);
 241                 if (statep == NULL || statep->dip == NULL) {
 242                         error = DDI_FAILURE;
 243                 } else {
 244                         *result = (void *) statep->dip;
 245                         error = DDI_SUCCESS;
 246                 }
 247                 break;
 248         case DDI_INFO_DEVT2INSTANCE:
 249                 *result = (void *)(uintptr_t)unit;
 250                 error = DDI_SUCCESS;
 251                 break;
 252         default:
 253                 error = DDI_FAILURE;
 254                 break;
 255         }
 256         return (error);
 257 
 258 }       /* radeon_info() */
 259 
 260 static void
 261 radeon_configure(drm_driver_t *driver)
 262 {
 263         driver->buf_priv_size = sizeof (drm_radeon_buf_priv_t);
 264         driver->load                 = radeon_driver_load;
 265         driver->unload               = radeon_driver_unload;
 266         driver->firstopen            = radeon_driver_firstopen;
 267         driver->open                 = radeon_driver_open;
 268         driver->preclose             = radeon_driver_preclose;
 269         driver->postclose            = radeon_driver_postclose;
 270         driver->lastclose            = radeon_driver_lastclose;
 271         driver->vblank_wait          = radeon_driver_vblank_wait;
 272         driver->vblank_wait2         = radeon_driver_vblank_wait2;
 273         driver->irq_preinstall       = radeon_driver_irq_preinstall;
 274         driver->irq_postinstall      = radeon_driver_irq_postinstall;
 275         driver->irq_uninstall        = radeon_driver_irq_uninstall;
 276         driver->irq_handler          = radeon_driver_irq_handler;
 277         driver->dma_ioctl            = radeon_cp_buffers;
 278 
 279         driver->driver_ioctls        = radeon_ioctls;
 280         driver->max_driver_ioctl     = radeon_max_ioctl;
 281 
 282         driver->driver_name          = DRIVER_NAME;
 283         driver->driver_desc          = DRIVER_DESC;
 284         driver->driver_date          = DRIVER_DATE;
 285         driver->driver_major         = DRIVER_MAJOR;
 286         driver->driver_minor         = DRIVER_MINOR;
 287         driver->driver_patchlevel    = DRIVER_PATCHLEVEL;
 288 
 289         driver->use_agp              = 1;
 290         driver->use_mtrr             = 1;
 291         driver->use_pci_dma          = 1;
 292         driver->use_sg               = 1;
 293         driver->use_dma              = 1;
 294         driver->use_irq              = 1;
 295         driver->use_vbl_irq          = 1;
 296         driver->use_vbl_irq2         = 1;
 297 
 298 }       /* radeon_configure() */