Print this page
    
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/drm/drm_sunmod.c
          +++ new/usr/src/uts/common/io/drm/drm_sunmod.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27   27  /*
  28   28   * Common misc module interfaces of DRM under Solaris
  29   29   */
  30   30  
  31   31  /*
  32   32   * This module calls into gfx and agpmaster misc modules respectively
  33   33   * for generic graphics operations and AGP master device support.
  34   34   */
  35   35  
  36   36  #include "drm_sunmod.h"
  37   37  #include <sys/modctl.h>
  38   38  #include <sys/kmem.h>
  39   39  #include <vm/seg_kmem.h>
  40   40  
  41   41  static struct modlmisc modlmisc = {
  42   42          &mod_miscops, "DRM common interfaces"
  43   43  };
  44   44  
  45   45  static struct modlinkage modlinkage = {
  46   46          MODREV_1, (void *)&modlmisc, NULL
  47   47  };
  48   48  
  49   49  static drm_inst_list_t  *drm_inst_head;
  50   50  static kmutex_t drm_inst_list_lock;
  51   51  
  52   52  static int drm_sun_open(dev_t *, int, int, cred_t *);
  53   53  static int drm_sun_close(dev_t, int, int, cred_t *);
  54   54  static int drm_sun_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
  55   55  static int drm_sun_devmap(dev_t, devmap_cookie_t, offset_t, size_t,
  56   56      size_t *, uint_t);
  57   57  
  58   58  /*
  59   59   * devmap callbacks for AGP and PCI GART
  60   60   */
  61   61  static int drm_devmap_map(devmap_cookie_t, dev_t,
  62   62      uint_t, offset_t, size_t, void **);
  63   63  static int drm_devmap_dup(devmap_cookie_t, void *,
  64   64      devmap_cookie_t, void **);
  65   65  static void drm_devmap_unmap(devmap_cookie_t, void *,
  66   66      offset_t, size_t, devmap_cookie_t, void **, devmap_cookie_t, void **);
  67   67  
  68   68  static drm_inst_list_t *drm_supp_alloc_drv_entry(dev_info_t *);
  69   69  static drm_inst_state_t *drm_sup_devt_to_state(dev_t);
  70   70  static void drm_supp_free_drv_entry(dev_info_t *);
  71   71  
  72   72  static struct devmap_callback_ctl drm_devmap_callbacks = {
  73   73                  DEVMAP_OPS_REV,                 /* devmap_rev */
  74   74                  drm_devmap_map,                         /* devmap_map */
  75   75                  NULL,                   /* devmap_access */
  76   76                  drm_devmap_dup,                 /* devmap_dup */
  77   77                  drm_devmap_unmap                /* devmap_unmap */
  78   78  };
  79   79  
  80   80  /*
  81   81   * Common device operations structure for all DRM drivers
  82   82   */
  83   83  struct cb_ops drm_cb_ops = {
  84   84          drm_sun_open,                   /* cb_open */
  85   85          drm_sun_close,                  /* cb_close */
  86   86          nodev,                                  /* cb_strategy */
  87   87          nodev,                                  /* cb_print */
  88   88          nodev,                                  /* cb_dump */
  89   89          nodev,                                  /* cb_read */
  90   90          nodev,                                  /* cb_write */
  91   91          drm_sun_ioctl,          /* cb_ioctl */
  92   92          drm_sun_devmap,         /* cb_devmap */
  93   93          nodev,                                  /* cb_mmap */
  94   94          NULL,                   /* cb_segmap */
  95   95          nochpoll,                               /* cb_chpoll */
  96   96          ddi_prop_op,            /* cb_prop_op */
  97   97          0,                                      /* cb_stream */
  98   98          D_NEW | D_MTSAFE |D_DEVMAP      /* cb_flag */
  99   99  };
 100  100  
 101  101  int
 102  102  _init(void)
 103  103  {
 104  104          int     error;
 105  105  
 106  106          if ((error = mod_install(&modlinkage)) != 0) {
 107  107                  return (error);
 108  108          }
 109  109  
 110  110          /* initialize the instance list lock */
 111  111          mutex_init(&drm_inst_list_lock, NULL, MUTEX_DRIVER, NULL);
 112  112          return (0);
 113  113  }
 114  114  
 115  115  int
 116  116  _fini(void)
 117  117  {
 118  118          int     err;
 119  119  
 120  120          if ((err = mod_remove(&modlinkage)) != 0)
 121  121                  return (err);
 122  122  
 123  123          mutex_destroy(&drm_inst_list_lock);
 124  124          return (0);
 125  125  }
 126  126  
 127  127  int
 128  128  _info(struct modinfo *modinfop)
 129  129  {
 130  130          return (mod_info(&modlinkage, modinfop));
 131  131  }
 132  132  
  
    | 
      ↓ open down ↓ | 
    132 lines elided | 
    
      ↑ open up ↑ | 
  
 133  133  void *
 134  134  drm_supp_register(dev_info_t *dip, drm_device_t *dp)
 135  135  {
 136  136          int             error;
 137  137          char    buf[80];
 138  138          int             instance = ddi_get_instance(dip);
 139  139          ddi_acc_handle_t        pci_cfg_handle;
 140  140          agp_master_softc_t      *agpm;
 141  141          drm_inst_state_t        *mstate;
 142  142          drm_inst_list_t         *entry;
 143      -        gfxp_vgatext_softc_ptr_t gfxp;
      143 +        gfxp_fb_softc_ptr_t     gfxp;
 144  144          struct dev_ops  *devop;
 145  145  
 146  146          ASSERT(dip != NULL);
 147  147  
 148  148          entry = drm_supp_alloc_drv_entry(dip);
 149  149          if (entry == NULL) {
 150  150                  cmn_err(CE_WARN, "drm_supp_register: failed to get softstate");
 151  151                  return (NULL);
 152  152          }
 153  153          mstate = &entry->disl_state;
 154  154  
 155  155          /*
 156  156           * DRM drivers are required to use common cb_ops
 157  157           */
 158  158          devop = ddi_get_driver(dip);
 159  159          if (devop->devo_cb_ops != &drm_cb_ops) {
 160  160                  devop->devo_cb_ops = &drm_cb_ops;
 161  161          }
 162  162  
 163  163          /* Generic graphics initialization */
 164      -        gfxp = gfxp_vgatext_softc_alloc();
 165      -        error = gfxp_vgatext_attach(dip, DDI_ATTACH, gfxp);
      164 +        gfxp = gfxp_fb_softc_alloc();
      165 +        error = gfxp_fb_attach(dip, DDI_ATTACH, gfxp);
 166  166          if (error != DDI_SUCCESS) {
 167  167                  DRM_ERROR("drm_supp_regiter: failed to init gfx");
 168  168                  goto exit1;
 169  169          }
 170  170  
 171  171          /* create a minor node for common graphics ops */
 172  172          (void) sprintf(buf, "%s%d", GFX_NAME, instance);
 173  173          error = ddi_create_minor_node(dip, buf, S_IFCHR,
 174  174              INST2NODE0(instance), DDI_NT_DISPLAY, NULL);
 175  175          if (error != DDI_SUCCESS) {
 176  176                  DRM_ERROR("drm_supp_regiter: "
 177  177                      "failed to create minor node for gfx");
 178  178                  goto exit2;
 179  179          }
 180  180  
 181  181          /* setup mapping for later PCI config space access */
 182  182          error = pci_config_setup(dip, &pci_cfg_handle);
 183  183          if (error != DDI_SUCCESS) {
 184  184                  DRM_ERROR("drm_supp_regiter: "
 185  185                      "PCI configuration space setup failed");
 186  186                  goto exit2;
 187  187          }
 188  188  
 189  189          /* AGP master attach */
 190  190          agpm = NULL;
 191  191          if (dp->driver->use_agp) {
 192  192                  DRM_DEBUG("drm_supp_regiter: driver use AGP\n");
 193  193                  error = agpmaster_attach(dip, &agpm,
 194  194                      pci_cfg_handle, INST2NODE1(instance));
 195  195                  if ((error != DDI_SUCCESS) && (dp->driver->require_agp)) {
 196  196                          DRM_ERROR("drm_supp_regiter: "
 197  197                              "AGP master support not available");
 198  198                          goto exit3;
 199  199                  }
 200  200          }
 201  201  
 202  202          mutex_enter(&mstate->mis_lock);
 203  203          mstate->mis_major = ddi_driver_major(dip);
 204  204          mstate->mis_dip = dip;
 205  205          mstate->mis_gfxp = gfxp;
 206  206          mstate->mis_agpm = agpm;
 207  207          mstate->mis_cfg_hdl = pci_cfg_handle;
 208  208          mstate->mis_devp = dp;
 209  209          mutex_exit(&mstate->mis_lock);
 210  210  
 211  211          /* create minor node for DRM access */
 212  212          (void) sprintf(buf, "%s%d", DRM_DEVNODE, instance);
 213  213          if (ddi_create_minor_node(dip, buf, S_IFCHR,
 214  214              INST2NODE2(instance), DDI_NT_DISPLAY_DRM, 0)) {
 215  215                  DRM_ERROR("supp_regiter: faled to create minor node for drm");
 216  216                  goto exit4;
  
    | 
      ↓ open down ↓ | 
    41 lines elided | 
    
      ↑ open up ↑ | 
  
 217  217          }
 218  218  
 219  219          return ((void *)mstate);
 220  220  
 221  221  exit4:
 222  222          if ((dp->driver->use_agp) && agpm)
 223  223                  agpmaster_detach(&agpm);
 224  224  exit3:
 225  225          pci_config_teardown(&pci_cfg_handle);
 226  226  exit2:
 227      -        (void) gfxp_vgatext_detach(dip, DDI_DETACH, gfxp);
      227 +        (void) gfxp_fb_detach(dip, DDI_DETACH, gfxp);
 228  228  exit1:
 229      -        gfxp_vgatext_softc_free(gfxp);
      229 +        gfxp_fb_softc_free(gfxp);
 230  230          drm_supp_free_drv_entry(dip);
 231  231          ddi_remove_minor_node(dip, NULL);
 232  232  
 233  233          return (NULL);
 234  234  }
 235  235  
 236  236  
 237  237  int
 238  238  drm_supp_unregister(void *handle)
 239  239  {
 240  240          drm_inst_list_t         *list;
 241  241          drm_inst_state_t        *mstate;
 242  242  
 243  243          list = (drm_inst_list_t *)handle;
 244  244          mstate = &list->disl_state;
 245  245          mutex_enter(&mstate->mis_lock);
 246  246  
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
 247  247          /* AGP master detach */
 248  248          if (mstate->mis_agpm != NULL)
 249  249                  agpmaster_detach(&mstate->mis_agpm);
 250  250  
 251  251          /* free PCI config access handle */
 252  252          if (mstate->mis_cfg_hdl)
 253  253                  pci_config_teardown(&mstate->mis_cfg_hdl);
 254  254  
 255  255          /* graphics misc module detach */
 256  256          if (mstate->mis_gfxp) {
 257      -                (void) gfxp_vgatext_detach(mstate->mis_dip, DDI_DETACH,
      257 +                (void) gfxp_fb_detach(mstate->mis_dip, DDI_DETACH,
 258  258                      mstate->mis_gfxp);
 259      -                gfxp_vgatext_softc_free(mstate->mis_gfxp);
      259 +                gfxp_fb_softc_free(mstate->mis_gfxp);
 260  260          }
 261  261  
 262  262          mstate->mis_devp = NULL;
 263  263  
 264  264          /* remove all minor nodes */
 265  265          ddi_remove_minor_node(mstate->mis_dip, NULL);
 266  266          mutex_exit(&mstate->mis_lock);
 267  267          drm_supp_free_drv_entry(mstate->mis_dip);
 268  268  
 269  269          return (DDI_SUCCESS);
 270  270  }
 271  271  
 272  272  
 273  273  /*ARGSUSED*/
 274  274  static int
 275  275  drm_sun_open(dev_t *devp, int flag, int otyp, cred_t *credp)
 276  276  {
 277  277          drm_inst_state_t        *mstate;
 278  278          drm_cminor_t    *mp, *newp;
 279  279          drm_device_t    *dp;
 280  280          minor_t         minor;
 281  281          int             newminor;
 282  282          int             instance;
 283  283          int             err;
 284  284  
 285  285          mstate = drm_sup_devt_to_state(*devp);
 286  286          /*
 287  287           * return ENXIO for deferred attach so that system can
 288  288           * attach us again.
 289  289           */
 290  290          if (mstate == NULL)
 291  291                  return (ENXIO);
 292  292  
 293  293          /*
 294  294           * The lest significant 15 bits are used for minor_number, and
 295  295           * the mid 3 bits are used for instance number. All minor numbers
 296  296           * are used as follows:
 297  297           * 0 -- gfx
 298  298           * 1 -- agpmaster
 299  299           * 2 -- drm
 300  300           * (3, MAX_CLONE_MINOR) -- drm minor node for clone open.
 301  301           */
 302  302          minor = DEV2MINOR(*devp);
 303  303          instance = DEV2INST(*devp);
 304  304          ASSERT(minor <= MAX_CLONE_MINOR);
 305  305  
 306  306          /*
 307  307           * No operations for VGA & AGP mater devices, always return OK.
 308  308           */
 309  309          if ((minor == GFX_MINOR) || (minor == AGPMASTER_MINOR))
 310  310                  return (0);
 311  311  
 312  312          /*
 313  313           * From here, we start to process drm
 314  314           */
 315  315  
 316  316          dp = mstate->mis_devp;
 317  317          if (!dp)
 318  318                  return (ENXIO);
 319  319  
 320  320          /*
 321  321           * Drm driver implements a software lock to serialize access
 322  322           * to graphics hardware based on per-process granulation. Before
 323  323           * operating graphics hardware, all clients, including kernel
 324  324           * and applications, must acquire this lock via DRM_IOCTL_LOCK
 325  325           * ioctl, and release it via DRM_IOCTL_UNLOCK after finishing
 326  326           * operations. Drm driver will grant r/w permission to the
 327  327           * process which acquires this lock (Kernel is assumed to have
 328  328           * process ID 0).
 329  329           *
 330  330           * A process might be terminated without releasing drm lock, in
 331  331           * this case, drm driver is responsible for clearing the holding.
 332  332           * To be informed of process exiting, drm driver uses clone open
 333  333           * to guarantee that each call to open(9e) have one corresponding
 334  334           * call to close(9e). In most cases, a process will close drm
 335  335           * during process termination, so that drm driver could have a
 336  336           * chance to release drm lock.
 337  337           *
 338  338           * In fact, a driver cannot know exactly when a process exits.
 339  339           * Clone open doesn't address this issue completely: Because of
 340  340           * inheritance, child processes inherit file descriptors from
 341  341           * their parent. As a result, if the parent exits before its
 342  342           * children, drm close(9e) entrypoint won't be called until all
 343  343           * of its children terminate.
 344  344           *
 345  345           * Another issue brought up by inhertance is the process PID
 346  346           * that calls the drm close() entry point may not be the same
 347  347           * as the one who called open(). Per-process struct is allocated
 348  348           * when a process first open() drm, and released when the process
 349  349           * last close() drm. Since open()/close() may be not the same
 350  350           * process, PID cannot be used for key to lookup per-process
 351  351           * struct. So, we associate minor number with per-process struct
 352  352           * during open()'ing, and find corresponding process struct
 353  353           * via minor number when close() is called.
 354  354           */
 355  355          newp = kmem_zalloc(sizeof (drm_cminor_t), KM_SLEEP);
 356  356          mutex_enter(&dp->dev_lock);
 357  357          for (newminor = DRM_MIN_CLONEMINOR; newminor < MAX_CLONE_MINOR;
 358  358              newminor ++) {
 359  359                  TAILQ_FOREACH(mp, &dp->minordevs, link) {
 360  360                          if (mp->minor == newminor)
 361  361                                  break;
 362  362                  }
 363  363                  if (mp == NULL)
 364  364                          goto gotminor;
 365  365          }
 366  366  
 367  367          mutex_exit(&dp->dev_lock);
 368  368          (void) kmem_free(newp, sizeof (drm_cminor_t));
 369  369          return (EMFILE);
 370  370  
 371  371  gotminor:
 372  372          TAILQ_INSERT_TAIL(&dp->minordevs, newp, link);
 373  373          newp->minor = newminor;
 374  374          mutex_exit(&dp->dev_lock);
 375  375          err = drm_open(dp, newp, flag, otyp, credp);
 376  376          if (err) {
 377  377                  mutex_enter(&dp->dev_lock);
 378  378                  TAILQ_REMOVE(&dp->minordevs, newp, link);
 379  379                  (void) kmem_free(newp, sizeof (drm_cminor_t));
 380  380                  mutex_exit(&dp->dev_lock);
 381  381  
 382  382                  return (err);
 383  383          }
 384  384  
 385  385          /* return a clone minor */
 386  386          newminor = newminor | (instance << NBITSMNODE);
 387  387          *devp = makedevice(getmajor(*devp), newminor);
 388  388          return (err);
 389  389  }
 390  390  
 391  391  /*ARGSUSED*/
 392  392  static int
 393  393  drm_sun_close(dev_t dev, int flag, int otyp, cred_t *credp)
 394  394  {
 395  395          drm_inst_state_t        *mstate;
 396  396          drm_device_t            *dp;
 397  397          minor_t         minor;
 398  398          int             ret;
 399  399  
 400  400          mstate = drm_sup_devt_to_state(dev);
 401  401          if (mstate == NULL)
 402  402                  return (EBADF);
 403  403  
 404  404          minor = DEV2MINOR(dev);
 405  405          ASSERT(minor <= MAX_CLONE_MINOR);
 406  406          if ((minor == GFX_MINOR) || (minor == AGPMASTER_MINOR))
 407  407                  return (0);
 408  408  
 409  409          dp = mstate->mis_devp;
 410  410          if (dp == NULL) {
 411  411                  DRM_ERROR("drm_sun_close: NULL soft state");
 412  412                  return (ENXIO);
 413  413          }
 414  414  
 415  415          ret = drm_close(dp, minor, flag, otyp, credp);
 416  416  
 417  417          return (ret);
 418  418  }
 419  419  
 420  420  /*ARGSUSED*/
 421  421  static int
 422  422  drm_sun_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
 423  423      cred_t *credp, int *rvalp)
 424  424  {
 425  425          extern drm_ioctl_desc_t drm_ioctls[];
 426  426  
 427  427          drm_inst_state_t        *mstate;
 428  428          drm_device_t            *dp;
 429  429          drm_ioctl_desc_t        *ioctl;
 430  430          drm_ioctl_t             *func;
 431  431          drm_file_t              *fpriv;
 432  432          minor_t         minor;
 433  433          int             retval;
 434  434          int             nr;
 435  435  
 436  436          if (cmd == VIS_GETIDENTIFIER) {
 437  437                  if (ddi_copyout(&text_ident, (void *)arg,
 438  438                      sizeof (struct vis_identifier), mode))
 439  439                          return (EFAULT);
 440  440          }
  
    | 
      ↓ open down ↓ | 
    171 lines elided | 
    
      ↑ open up ↑ | 
  
 441  441  
 442  442          mstate = drm_sup_devt_to_state(dev);
 443  443          if (mstate == NULL) {
 444  444                  return (EIO);
 445  445          }
 446  446  
 447  447          minor = DEV2MINOR(dev);
 448  448          ASSERT(minor <= MAX_CLONE_MINOR);
 449  449          switch (minor) {
 450  450          case GFX_MINOR:
 451      -                retval = gfxp_vgatext_ioctl(dev, cmd, arg,
      451 +                retval = gfxp_fb_ioctl(dev, cmd, arg,
 452  452                      mode, credp, rvalp, mstate->mis_gfxp);
 453  453                  return (retval);
 454  454  
 455  455          case AGPMASTER_MINOR:
 456  456                  retval = agpmaster_ioctl(dev, cmd, arg, mode,
 457  457                      credp, rvalp, mstate->mis_agpm);
 458  458                  return (retval);
 459  459  
 460  460          case DRM_MINOR:
 461  461          default:        /* DRM cloning minor nodes */
 462  462                  break;
 463  463          }
 464  464  
 465  465          dp = mstate->mis_devp;
 466  466          ASSERT(dp != NULL);
 467  467  
 468  468          nr = DRM_IOCTL_NR(cmd);
 469  469          ioctl = &drm_ioctls[nr];
 470  470          atomic_inc_32(&dp->counts[_DRM_STAT_IOCTLS]);
 471  471  
 472  472          /* It's not a core DRM ioctl, try driver-specific. */
 473  473          if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
 474  474                  /* The array entries begin at DRM_COMMAND_BASE ioctl nr */
 475  475                  nr -= DRM_COMMAND_BASE;
 476  476                  if (nr > dp->driver->max_driver_ioctl) {
 477  477                          DRM_ERROR("Bad driver ioctl number, 0x%x (of 0x%x)",
 478  478                              nr, dp->driver->max_driver_ioctl);
 479  479                          return (EINVAL);
 480  480                  }
 481  481                  ioctl = &dp->driver->driver_ioctls[nr];
 482  482          }
 483  483  
 484  484          func = ioctl->func;
 485  485          if (func == NULL) {
 486  486                  return (ENOTSUP);
 487  487          }
 488  488  
 489  489          mutex_enter(&dp->dev_lock);
 490  490          fpriv = drm_find_file_by_proc(dp, credp);
 491  491          mutex_exit(&dp->dev_lock);
 492  492          if (fpriv == NULL) {
 493  493                  DRM_ERROR("drm_sun_ioctl : can't find authenticator");
 494  494                  return (EACCES);
 495  495          }
 496  496  
 497  497          if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(credp)) ||
 498  498              ((ioctl->flags & DRM_AUTH) && !fpriv->authenticated) ||
 499  499              ((ioctl->flags & DRM_MASTER) && !fpriv->master))
 500  500                  return (EACCES);
 501  501  
 502  502          fpriv->dev = dev;
 503  503          fpriv->credp = credp;
 504  504  
 505  505          retval = func(dp, arg, fpriv, mode);
 506  506  
 507  507          return (retval);
 508  508  }
 509  509  
 510  510  /*ARGSUSED*/
 511  511  static int
 512  512  drm_sun_devmap(dev_t dev, devmap_cookie_t dhp, offset_t offset,
 513  513      size_t len, size_t *maplen, uint_t model)
 514  514  {
 515  515          extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
 516  516  
 517  517          drm_inst_state_t        *mstate;
 518  518          drm_device_t            *dp;
 519  519          ddi_umem_cookie_t       cookie;
 520  520          drm_local_map_t         *map = NULL;
 521  521          unsigned long   aperbase;
 522  522          u_offset_t              handle;
 523  523          offset_t                koff;
 524  524          caddr_t                 kva;
 525  525          minor_t                 minor;
 526  526          size_t                  length;
 527  527          int                     ret;
 528  528  
 529  529          static ddi_device_acc_attr_t dev_attr = {
 530  530                  DDI_DEVICE_ATTR_V0,
 531  531                  DDI_NEVERSWAP_ACC,
 532  532                  DDI_STRICTORDER_ACC,
 533  533          };
 534  534          static ddi_device_acc_attr_t gem_dev_attr = {
 535  535                  DDI_DEVICE_ATTR_V0,
 536  536                  DDI_NEVERSWAP_ACC,
  
    | 
      ↓ open down ↓ | 
    75 lines elided | 
    
      ↑ open up ↑ | 
  
 537  537                  DDI_MERGING_OK_ACC
 538  538          };
 539  539  
 540  540          mstate = drm_sup_devt_to_state(dev);
 541  541          if (mstate == NULL)
 542  542                  return (ENXIO);
 543  543  
 544  544          minor = DEV2MINOR(dev);
 545  545          switch (minor) {
 546  546          case GFX_MINOR:
 547      -                ret = gfxp_vgatext_devmap(dev, dhp, offset, len, maplen, model,
      547 +                ret = gfxp_fb_devmap(dev, dhp, offset, len, maplen, model,
 548  548                      mstate->mis_gfxp);
 549  549                  return (ret);
 550  550  
 551  551          case AGPMASTER_MINOR:
 552  552                  return (ENOTSUP);
 553  553  
 554  554          case DRM_MINOR:
 555  555                  break;
 556  556  
 557  557          default:
 558  558                  /* DRM cloning nodes */
 559  559                  if (minor > MAX_CLONE_MINOR)
 560  560                          return (EBADF);
 561  561                  break;
 562  562          }
 563  563  
 564  564  
 565  565          dp = mstate->mis_devp;
 566  566          if (dp == NULL) {
 567  567                  DRM_ERROR("drm_sun_devmap: NULL soft state");
 568  568                  return (EINVAL);
 569  569          }
 570  570  
 571  571          mutex_enter(&dp->dev_lock);
 572  572  
 573  573          if (dp->driver->use_gem == 1) {
 574  574                  struct idr_list *entry;
 575  575                  drm_cminor_t *mp;
 576  576  
 577  577                  mp = drm_find_file_by_minor(dp, minor);
 578  578                  if (!mp) {
 579  579                          mutex_exit(&dp->dev_lock);
 580  580                          DRM_ERROR("drm_sun_devmap: can't find authenticator");
 581  581                          return (EACCES);
 582  582                  }
 583  583  
 584  584                  spin_lock(&dp->struct_mutex);
 585  585                  idr_list_for_each(entry, &(mp->fpriv->object_idr)) {
 586  586                          if ((uintptr_t)entry->obj == (u_offset_t)offset) {
 587  587                                  map = entry->obj->map;
 588  588                                  goto goon;
 589  589                          }
 590  590                  }
 591  591  goon:
 592  592                  spin_unlock(&dp->struct_mutex);
 593  593          }
 594  594  
 595  595          if (map == NULL) {
 596  596                  /*
 597  597                   * We will solve 32-bit application on 64-bit kernel
 598  598                   * issue later, now, we just use low 32-bit
 599  599                   */
 600  600                  handle = (u_offset_t)offset;
 601  601                  handle &= 0xffffffff;
 602  602  
 603  603                  TAILQ_FOREACH(map, &dp->maplist, link) {
 604  604                          if (handle ==
 605  605                              ((u_offset_t)((uintptr_t)map->handle) & 0xffffffff))
 606  606                                  break;
 607  607                  }
 608  608  
 609  609                  /*
 610  610                   * Temporarily, because offset is phys_addr for register
 611  611                   * and framebuffer, is kernel virtual_addr for others
 612  612                   * Maybe we will use hash table to solve this issue later.
 613  613                   */
 614  614                  if (map == NULL) {
 615  615                          TAILQ_FOREACH(map, &dp->maplist, link) {
 616  616                                  if (handle == (map->offset & 0xffffffff))
 617  617                                          break;
 618  618                          }
 619  619                  }
 620  620          }
 621  621  
 622  622          if (map == NULL) {
 623  623                  u_offset_t      tmp;
 624  624  
 625  625                  mutex_exit(&dp->dev_lock);
 626  626                  cmn_err(CE_WARN, "Can't find map, offset=0x%llx, len=%x\n",
 627  627                      offset, (int)len);
 628  628                  cmn_err(CE_WARN, "Current mapping:\n");
 629  629                  TAILQ_FOREACH(map, &dp->maplist, link) {
 630  630                  tmp = (u_offset_t)((uintptr_t)map->handle) & 0xffffffff;
 631  631                  cmn_err(CE_WARN, "map(handle=0x%p, size=0x%lx,type=%d,"
 632  632                      "offset=0x%lx), handle=%llx, tmp=%lld", map->handle,
 633  633                      map->size, map->type, map->offset, handle, tmp);
 634  634                  }
 635  635                  return (-1);
 636  636          }
 637  637          if (map->flags & _DRM_RESTRICTED) {
 638  638                  mutex_exit(&dp->dev_lock);
 639  639                  cmn_err(CE_WARN, "restricted map\n");
 640  640                  return (-1);
 641  641          }
 642  642  
 643  643          mutex_exit(&dp->dev_lock);
 644  644          switch (map->type) {
 645  645          case _DRM_FRAME_BUFFER:
 646  646          case _DRM_REGISTERS:
 647  647                  {
 648  648                          int     regno;
 649  649                          off_t   regoff;
 650  650  
 651  651                          regno = drm_get_pci_index_reg(dp->dip,
 652  652                              map->offset, (uint_t)len, ®off);
 653  653                          if (regno < 0) {
 654  654                                  DRM_ERROR("devmap: failed to get register"
 655  655                                      " offset=0x%llx, len=0x%x", handle, len);
 656  656                                  return (EINVAL);
 657  657                          }
 658  658  
 659  659                          ret = devmap_devmem_setup(dhp, dp->dip, NULL,
 660  660                              regno, (offset_t)regoff, len, PROT_ALL,
 661  661                              0, &dev_attr);
 662  662                          if (ret != 0) {
 663  663                                  *maplen = 0;
 664  664                                  DRM_ERROR("devmap: failed, regno=%d,type=%d,"
 665  665                                      " handle=0x%x, offset=0x%llx, len=0x%x",
 666  666                                      regno, map->type, handle, offset, len);
 667  667                                  return (ret);
 668  668                          }
 669  669                          *maplen = len;
 670  670                          return (ret);
 671  671                  }
 672  672  
 673  673          case _DRM_SHM:
 674  674                  if (map->drm_umem_cookie == NULL)
 675  675                          return (EINVAL);
 676  676                  length = ptob(btopr(map->size));
 677  677                  ret = devmap_umem_setup(dhp, dp->dip, NULL,
 678  678                      map->drm_umem_cookie, 0, length,
 679  679                      PROT_ALL, IOMEM_DATA_CACHED, NULL);
 680  680                  if (ret != 0) {
 681  681                          *maplen = 0;
 682  682                          return (ret);
 683  683                  }
 684  684                  *maplen = length;
 685  685  
 686  686                  return (DDI_SUCCESS);
 687  687  
 688  688          case _DRM_AGP:
 689  689                  if (dp->agp == NULL) {
 690  690                          cmn_err(CE_WARN, "drm_sun_devmap: attempted to mmap AGP"
 691  691                              "memory before AGP support is enabled");
 692  692                          return (DDI_FAILURE);
 693  693                  }
 694  694  
 695  695                  aperbase = dp->agp->base;
 696  696                  koff = map->offset - aperbase;
 697  697                  length = ptob(btopr(len));
 698  698                  kva = map->dev_addr;
 699  699                  cookie = gfxp_umem_cookie_init(kva, length);
 700  700                  if (cookie == NULL) {
 701  701                          cmn_err(CE_WARN, "devmap:failed to get umem_cookie");
 702  702                          return (DDI_FAILURE);
 703  703                  }
 704  704  
 705  705                  if ((ret = devmap_umem_setup(dhp, dp->dip,
 706  706                      &drm_devmap_callbacks, cookie, 0, length, PROT_ALL,
 707  707                      IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr)) < 0) {
 708  708                          gfxp_umem_cookie_destroy(cookie);
 709  709                          cmn_err(CE_WARN, "devmap:failed, retval=%d", ret);
 710  710                          return (DDI_FAILURE);
 711  711                  }
 712  712                  *maplen = length;
 713  713                  break;
 714  714  
 715  715          case _DRM_SCATTER_GATHER:
 716  716                  koff = map->offset - (unsigned long)(caddr_t)dp->sg->virtual;
 717  717                  kva = map->dev_addr + koff;
 718  718                  length = ptob(btopr(len));
 719  719                  if (length > map->size) {
 720  720                          cmn_err(CE_WARN, "offset=0x%lx, virtual=0x%p,"
 721  721                              "mapsize=0x%lx,len=0x%lx", map->offset,
 722  722                              dp->sg->virtual, map->size, len);
 723  723                          return (DDI_FAILURE);
 724  724                  }
 725  725                  cookie = gfxp_umem_cookie_init(kva, length);
 726  726                  if (cookie == NULL) {
 727  727                          cmn_err(CE_WARN, "devmap:failed to get umem_cookie");
 728  728                          return (DDI_FAILURE);
 729  729                  }
 730  730                  ret = devmap_umem_setup(dhp, dp->dip,
 731  731                      &drm_devmap_callbacks, cookie, 0, length, PROT_ALL,
 732  732                      IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr);
 733  733                  if (ret != 0) {
 734  734                          cmn_err(CE_WARN, "sun_devmap: umem_setup fail");
 735  735                          gfxp_umem_cookie_destroy(cookie);
 736  736                          return (DDI_FAILURE);
 737  737                  }
 738  738                  *maplen = length;
 739  739                  break;
 740  740  
 741  741          case _DRM_TTM:
 742  742                  if (map->drm_umem_cookie == NULL)
 743  743                          return (EINVAL);
 744  744  
 745  745                  if (gfxp_devmap_umem_setup(dhp, dp->dip,
 746  746                      NULL, map->drm_umem_cookie, 0, map->size, PROT_ALL,
 747  747                      IOMEM_DATA_UC_WR_COMBINE | DEVMAP_ALLOW_REMAP,
 748  748                      &gem_dev_attr)) {
 749  749                          cmn_err(CE_WARN, "devmap:failed, retval=%d", ret);
 750  750                          return (DDI_FAILURE);
 751  751                  }
 752  752                  *maplen = map->size;
 753  753                  return (DDI_SUCCESS);
 754  754  
 755  755          default:
 756  756                  return (DDI_FAILURE);
 757  757          }
 758  758          return (DDI_SUCCESS);
 759  759  
 760  760  }
 761  761  
 762  762  /*ARGSUSED*/
 763  763  static int
 764  764  drm_devmap_map(devmap_cookie_t dhc, dev_t dev, uint_t flags,
 765  765      offset_t offset, size_t len, void **new_priv)
 766  766  {
 767  767          devmap_handle_t                 *dhp;
 768  768          drm_inst_state_t                *statep;
 769  769          struct ddi_umem_cookie  *cp;
 770  770  
 771  771          statep = drm_sup_devt_to_state(dev);
 772  772          ASSERT(statep != NULL);
 773  773  
 774  774          /*
 775  775           * This driver only supports MAP_SHARED,
 776  776           * and doesn't support MAP_PRIVATE
 777  777           */
 778  778          if (flags & MAP_PRIVATE) {
 779  779                  cmn_err(CE_WARN, "!DRM driver doesn't support MAP_PRIVATE");
 780  780                  return (EINVAL);
 781  781          }
 782  782  
 783  783          mutex_enter(&statep->dis_ctxlock);
 784  784          dhp = (devmap_handle_t *)dhc;
 785  785          cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
 786  786          cp->cook_refcnt = 1;
 787  787          mutex_exit(&statep->dis_ctxlock);
 788  788          *new_priv = statep;
 789  789  
 790  790          return (0);
 791  791  }
 792  792  
 793  793  /*ARGSUSED*/
 794  794  static void
 795  795  drm_devmap_unmap(devmap_cookie_t dhc, void *pvtp, offset_t off, size_t len,
 796  796      devmap_cookie_t new_dhp1, void **new_pvtp1, devmap_cookie_t new_dhp2,
 797  797      void **new_pvtp2)
 798  798  {
 799  799          devmap_handle_t         *dhp;
 800  800          devmap_handle_t         *ndhp;
 801  801          drm_inst_state_t                *statep;
 802  802          struct ddi_umem_cookie  *cp;
 803  803          struct ddi_umem_cookie  *ncp;
 804  804  
 805  805          dhp = (devmap_handle_t *)dhc;
 806  806          statep = (drm_inst_state_t *)pvtp;
 807  807  
 808  808          mutex_enter(&statep->dis_ctxlock);
 809  809          cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
 810  810          if (new_dhp1 != NULL) {
 811  811                  ndhp = (devmap_handle_t *)new_dhp1;
 812  812                  ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie;
 813  813                  ncp->cook_refcnt ++;
 814  814                  *new_pvtp1 = statep;
 815  815                  ASSERT(ncp == cp);
 816  816          }
 817  817  
 818  818          if (new_dhp2 != NULL) {
 819  819                  ndhp = (devmap_handle_t *)new_dhp2;
 820  820                  ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie;
 821  821                  ncp->cook_refcnt ++;
 822  822                  *new_pvtp2 = statep;
 823  823                  ASSERT(ncp == cp);
 824  824          }
 825  825  
 826  826          cp->cook_refcnt --;
 827  827          if (cp->cook_refcnt == 0) {
 828  828                  gfxp_umem_cookie_destroy(dhp->dh_cookie);
 829  829                  dhp->dh_cookie = NULL;
 830  830          }
 831  831          mutex_exit(&statep->dis_ctxlock);
 832  832  }
 833  833  
 834  834  
 835  835  /*ARGSUSED*/
 836  836  static int
 837  837  drm_devmap_dup(devmap_cookie_t dhc, void *pvtp, devmap_cookie_t new_dhc,
 838  838      void **new_pvtp)
 839  839  {
 840  840          devmap_handle_t                 *dhp;
 841  841          drm_inst_state_t    *statep;
 842  842          struct ddi_umem_cookie *cp;
 843  843  
 844  844          statep = (drm_inst_state_t *)pvtp;
 845  845          mutex_enter(&statep->dis_ctxlock);
 846  846          dhp = (devmap_handle_t *)dhc;
 847  847          cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
 848  848          cp->cook_refcnt ++;
 849  849          mutex_exit(&statep->dis_ctxlock);
 850  850          *new_pvtp = statep;
 851  851  
 852  852          return (0);
 853  853  }
 854  854  
 855  855  int
 856  856  drm_dev_to_instance(dev_t dev)
 857  857  {
 858  858          return (DEV2INST(dev));
 859  859  }
 860  860  
 861  861  /*
 862  862   * drm_supp_alloc_drv_entry()
 863  863   *
 864  864   * Description:
 865  865   *      Create a DRM entry and add it into the instance list (drm_inst_head).
 866  866   *      Note that we don't allow a duplicated entry
 867  867   */
 868  868  static drm_inst_list_t *
 869  869  drm_supp_alloc_drv_entry(dev_info_t *dip)
 870  870  {
 871  871          drm_inst_list_t **plist;
 872  872          drm_inst_list_t *list;
 873  873          drm_inst_list_t *entry;
 874  874  
 875  875          /* protect the driver list */
 876  876          mutex_enter(&drm_inst_list_lock);
 877  877          plist = &drm_inst_head;
 878  878          list = *plist;
 879  879          while (list) {
 880  880                  if (list->disl_state.mis_dip == dip) {
 881  881                          mutex_exit(&drm_inst_list_lock);
 882  882                          cmn_err(CE_WARN, "%s%d already registered",
 883  883                              ddi_driver_name(dip), ddi_get_instance(dip));
 884  884                          return (NULL);
 885  885                  }
 886  886                  plist = &list->disl_next;
 887  887                  list = list->disl_next;
 888  888          }
 889  889  
 890  890          /* "dip" is not registered, create new one and add to list */
 891  891          entry = kmem_zalloc(sizeof (*entry), KM_SLEEP);
 892  892          *plist = entry;
 893  893          entry->disl_state.mis_dip = dip;
 894  894          mutex_init(&entry->disl_state.mis_lock, NULL, MUTEX_DRIVER, NULL);
 895  895          mutex_init(&entry->disl_state.dis_ctxlock, NULL, MUTEX_DRIVER, NULL);
 896  896          mutex_exit(&drm_inst_list_lock);
 897  897  
 898  898          return (entry);
 899  899  
 900  900  }       /* drm_supp_alloc_drv_entry */
 901  901  
 902  902  /*
 903  903   * drm_supp_free_drv_entry()
 904  904   */
 905  905  static void
 906  906  drm_supp_free_drv_entry(dev_info_t *dip)
 907  907  {
 908  908          drm_inst_list_t         *list;
 909  909          drm_inst_list_t         **plist;
 910  910          drm_inst_state_t        *mstate;
 911  911  
 912  912          /* protect the driver list */
 913  913          mutex_enter(&drm_inst_list_lock);
 914  914          plist = &drm_inst_head;
 915  915          list = *plist;
 916  916          while (list) {
 917  917                  if (list->disl_state.mis_dip == dip) {
 918  918                          *plist = list->disl_next;
 919  919                          mstate = &list->disl_state;
 920  920                          mutex_destroy(&mstate->mis_lock);
 921  921                          mutex_destroy(&mstate->dis_ctxlock);
 922  922                          kmem_free(list, sizeof (*list));
 923  923                          mutex_exit(&drm_inst_list_lock);
 924  924                          return;
 925  925                  }
 926  926                  plist = &list->disl_next;
 927  927                  list = list->disl_next;
 928  928          }
 929  929          mutex_exit(&drm_inst_list_lock);
 930  930  
 931  931  }       /* drm_supp_free_drv_entry() */
 932  932  
 933  933  /*
 934  934   * drm_sup_devt_to_state()
 935  935   *
 936  936   * description:
 937  937   *      Get the soft state of DRM instance by device number
 938  938   */
 939  939  static drm_inst_state_t *
 940  940  drm_sup_devt_to_state(dev_t dev)
 941  941  {
 942  942          drm_inst_list_t *list;
 943  943          drm_inst_state_t        *mstate;
 944  944          major_t major = getmajor(dev);
 945  945          int             instance = DEV2INST(dev);
 946  946  
 947  947          mutex_enter(&drm_inst_list_lock);
 948  948          list = drm_inst_head;
 949  949          while (list) {
 950  950                  mstate = &list->disl_state;
 951  951                  mutex_enter(&mstate->mis_lock);
 952  952  
 953  953                  if ((mstate->mis_major == major) &&
 954  954                      (ddi_get_instance(mstate->mis_dip) == instance)) {
 955  955                          mutex_exit(&mstate->mis_lock);
 956  956                          mutex_exit(&drm_inst_list_lock);
 957  957                          return (mstate);
 958  958                  }
 959  959  
 960  960                  list = list->disl_next;
 961  961                  mutex_exit(&mstate->mis_lock);
 962  962          }
 963  963  
 964  964          mutex_exit(&drm_inst_list_lock);
 965  965          return (NULL);
 966  966  
 967  967  }       /* drm_sup_devt_to_state() */
 968  968  
 969  969  int
 970  970  drm_supp_get_irq(void *handle)
 971  971  {
 972  972          drm_inst_list_t *list;
 973  973          drm_inst_state_t    *mstate;
 974  974          int             irq;
 975  975  
 976  976          list = (drm_inst_list_t *)handle;
 977  977          mstate = &list->disl_state;
 978  978          ASSERT(mstate != NULL);
 979  979          irq = pci_config_get8(mstate->mis_cfg_hdl, PCI_CONF_ILINE);
 980  980          return (irq);
 981  981  }
 982  982  
 983  983  int
 984  984  drm_supp_device_capability(void *handle, int capid)
 985  985  {
 986  986          drm_inst_list_t *list;
 987  987          drm_inst_state_t    *mstate;
 988  988          uint8_t         cap = 0;
 989  989          uint16_t        caps_ptr;
 990  990  
 991  991          list = (drm_inst_list_t *)handle;
 992  992          mstate = &list->disl_state;
 993  993          ASSERT(mstate != NULL);
 994  994  
 995  995          /* has capabilities list ? */
 996  996          if ((pci_config_get16(mstate->mis_cfg_hdl, PCI_CONF_STAT) &
 997  997              PCI_CONF_CAP_MASK) == 0)
 998  998                  return (NULL);
 999  999  
1000 1000          caps_ptr = pci_config_get8(mstate->mis_cfg_hdl, PCI_CONF_CAP_PTR);
1001 1001          while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
1002 1002                  cap = pci_config_get32(mstate->mis_cfg_hdl, caps_ptr);
1003 1003                  if ((cap & PCI_CONF_CAPID_MASK) == capid)
1004 1004                          return (cap);
1005 1005                  caps_ptr = pci_config_get8(mstate->mis_cfg_hdl,
1006 1006                      caps_ptr + PCI_CAP_NEXT_PTR);
1007 1007          }
1008 1008  
1009 1009          return (0);
1010 1010  }
  
    | 
      ↓ open down ↓ | 
    453 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX