Subversion Repositories Kolibri OS

Rev

Rev 6937 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include <drm/drmP.h>
  2. #include "intel_drv.h"
  3. #include <drm/i915_drm.h>
  4. #include <drm/drm_plane_helper.h>
  5. #include "i915_drv.h"
  6.  
  7. #include <syscall.h>
  8. #include <display.h>
  9.  
  10. int printf ( const char * format, ... );
  11.  
  12. void init_system_cursors(struct drm_device *dev);
  13.  
  14. display_t *os_display;
  15.  
  16. u32 cmd_buffer;
  17. u32 cmd_offset;
  18.  
  19. void init_render();
  20. int  sna_init();
  21.  
  22. static char *manufacturer_name(unsigned char *x)
  23. {
  24.     static char name[4];
  25.  
  26.     name[0] = ((x[0] & 0x7C) >> 2) + '@';
  27.     name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@';
  28.     name[2] = (x[1] & 0x1F) + '@';
  29.     name[3] = 0;
  30.  
  31.     return name;
  32. }
  33.  
  34. static int count_connector_modes(struct drm_connector* connector)
  35. {
  36.     struct drm_display_mode  *mode;
  37.     int count = 0;
  38.  
  39.     list_for_each_entry(mode, &connector->modes, head)
  40.         count++;
  41.  
  42.     return count;
  43. };
  44.  
  45. struct drm_framebuffer *get_framebuffer(struct drm_device *dev, struct drm_display_mode *mode, int tiling)
  46. {
  47.     struct drm_i915_private    *dev_priv = dev->dev_private;
  48.     struct intel_fbdev         *ifbdev   = dev_priv->fbdev;
  49.     struct intel_framebuffer   *intel_fb = ifbdev->fb;
  50.     struct drm_framebuffer     *fb = &intel_fb->base;
  51.     struct drm_i915_gem_object *obj = NULL;
  52.     int stride, size;
  53.  
  54.     stride = mode->hdisplay *4;
  55.  
  56.     if(IS_GEN3(dev))
  57.         tiling = 0;
  58.  
  59.     if(tiling)
  60.     {
  61.         int gen3size;
  62.  
  63.         stride = ALIGN(stride, 512);
  64.         size = stride * ALIGN(mode->vdisplay, 8);
  65.         size = ALIGN(size, 4096);
  66.     }
  67.     else
  68.     {
  69.         stride = ALIGN(stride, 64);
  70.         size = stride * ALIGN(mode->vdisplay, 2);
  71.     }
  72.  
  73.     DRM_DEBUG_KMS("size %x stride %x\n", size, stride);
  74.  
  75.     if(intel_fb == NULL || size > intel_fb->obj->base.size)
  76.     {
  77.         struct drm_mode_fb_cmd2 mode_cmd = {};
  78.         int ret;
  79.  
  80.         DRM_DEBUG_KMS("remove old framebuffer\n");
  81.         set_fake_framebuffer();
  82.         drm_framebuffer_remove(fb);
  83.         ifbdev->fb = NULL;
  84.         fb = NULL;
  85.         DRM_DEBUG_KMS("create new framebuffer\n");
  86.  
  87.         mode_cmd.width  = mode->hdisplay;
  88.         mode_cmd.height = mode->vdisplay;
  89.  
  90.         mode_cmd.pitches[0] = stride;
  91.         mode_cmd.pixel_format = DRM_FORMAT_XRGB8888;
  92.  
  93.         mutex_lock(&dev->struct_mutex);
  94.  
  95.         /* If the FB is too big, just don't use it since fbdev is not very
  96.         * important and we should probably use that space with FBC or other
  97.         * features. */
  98.         if (size * 2 < dev_priv->gtt.stolen_usable_size)
  99.             obj = i915_gem_object_create_stolen(dev, size);
  100.         if (obj == NULL)
  101.             obj = i915_gem_alloc_object(dev, size);
  102.         if (!obj) {
  103.             DRM_ERROR("failed to allocate framebuffer\n");
  104.             ret = -ENOMEM;
  105.             goto out;
  106.         }
  107.  
  108.         fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
  109.         if (IS_ERR(fb)) {
  110.             ret = PTR_ERR(fb);
  111.             goto out_unref;
  112.         }
  113.  
  114.         /* Flush everything out, we'll be doing GTT only from now on */
  115.         ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL);
  116.         if (ret) {
  117.             DRM_ERROR("failed to pin obj: %d\n", ret);
  118.             goto out_fb;
  119.         }
  120.         mutex_unlock(&dev->struct_mutex);
  121.         ifbdev->fb = to_intel_framebuffer(fb);
  122.     }
  123.  
  124.     obj = ifbdev->fb->obj;
  125.  
  126.     if(tiling)
  127.     {
  128.         obj->tiling_mode = I915_TILING_X;
  129.         fb->modifier[0]  = I915_FORMAT_MOD_X_TILED;
  130.         obj->fence_dirty = true;
  131.         obj->stride      = stride;
  132.     };
  133.  
  134.     if (obj->base.name == 0)
  135.     {
  136.         int ret;
  137.  
  138.         mutex_lock(&dev->object_name_lock);
  139.         idr_preload(GFP_KERNEL);
  140.         ret = idr_alloc(&dev->object_name_idr, &obj->base, 1, 0, GFP_NOWAIT);
  141.         idr_preload_end();
  142.         mutex_unlock(&dev->object_name_lock);
  143.         obj->base.name = ret;
  144.         obj->base.handle_count++;
  145.         DRM_DEBUG_KMS("%s allocate fb name %d\n", __FUNCTION__, obj->base.name );
  146.     }
  147.  
  148.     fb->width  = mode->hdisplay;
  149.     fb->height = mode->vdisplay;
  150.  
  151.     fb->pitches[0]  =
  152.     fb->pitches[1]  =
  153.     fb->pitches[2]  =
  154.     fb->pitches[3]  = stride;
  155.  
  156.     fb->bits_per_pixel = 32;
  157.     fb->depth = 24;
  158.  
  159.     return fb;
  160.  
  161. out_fb:
  162.     drm_framebuffer_remove(fb);
  163. out_unref:
  164.     drm_gem_object_unreference(&obj->base);
  165. out:
  166.     mutex_unlock(&dev->struct_mutex);
  167.     return NULL;
  168. }
  169.  
  170. static int set_mode(struct drm_device *dev, struct drm_connector *connector,
  171.                     struct drm_crtc *crtc, videomode_t *reqmode, bool strict)
  172. {
  173.     struct drm_i915_private *dev_priv = dev->dev_private;
  174.     struct drm_mode_config  *config   = &dev->mode_config;
  175.     struct drm_display_mode *mode     = NULL, *tmpmode;
  176.     struct drm_connector    *tmpc;
  177.     struct drm_framebuffer  *fb       = NULL;
  178.     struct drm_mode_set     set;
  179.     char  con_edid[128];
  180.     int ret;
  181.  
  182.     drm_modeset_lock_all(dev);
  183.  
  184.     list_for_each_entry(tmpc, &dev->mode_config.connector_list, head)
  185.     {
  186.         const struct drm_connector_funcs *f = tmpc->funcs;
  187.         if(tmpc == connector)
  188.             continue;
  189.         f->dpms(tmpc, DRM_MODE_DPMS_OFF);
  190.     };
  191.  
  192.     list_for_each_entry(tmpmode, &connector->modes, head)
  193.     {
  194.         if( (tmpmode->hdisplay == reqmode->width)  &&
  195.             (tmpmode->vdisplay == reqmode->height) &&
  196.             (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
  197.         {
  198.             mode = tmpmode;
  199.             goto do_set;
  200.         }
  201.     };
  202.  
  203.     if( (mode == NULL) && (strict == false) )
  204.     {
  205.         list_for_each_entry(tmpmode, &connector->modes, head)
  206.         {
  207.             if( (tmpmode->hdisplay == reqmode->width)  &&
  208.                 (tmpmode->vdisplay == reqmode->height) )
  209.             {
  210.                 mode = tmpmode;
  211.                 goto do_set;
  212.             }
  213.         };
  214.     };
  215.  
  216. out:
  217.     drm_modeset_unlock_all(dev);
  218.     DRM_ERROR("%s failed\n", __FUNCTION__);
  219.     return -1;
  220.  
  221. do_set:
  222.  
  223.     drm_modeset_unlock_all(dev);
  224.  
  225.     fb = get_framebuffer(dev, mode, 1);
  226.     if(fb == NULL)
  227.     {
  228.         DRM_ERROR("%s failed\n", __FUNCTION__);
  229.         return -1;
  230.     };
  231.     drm_framebuffer_reference(fb);
  232.  
  233.     drm_modeset_lock_all(dev);
  234.  
  235.     memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  236.  
  237.     DRM_DEBUG_KMS("set mode %dx%d: crtc %d connector %s\n"
  238.                   "monitor: %s model %x serial number %u\n",
  239.                 mode->hdisplay, mode->vdisplay,
  240.                 crtc->base.id, connector->name,
  241.                 manufacturer_name(con_edid + 0x08),
  242.                 (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  243.                 (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  244.                 + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  245.  
  246.     drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
  247.  
  248.     crtc->enabled = true;
  249.     os_display->crtc = crtc;
  250.  
  251.     DRM_DEBUG_KMS("fb:%p %dx%dx pitch %d format %x\n",
  252.             fb,fb->width,fb->height,fb->pitches[0],fb->pixel_format);
  253.  
  254.     set.crtc = crtc;
  255.     set.x = 0;
  256.     set.y = 0;
  257.     set.mode = mode;
  258.     set.connectors = &connector;
  259.     set.num_connectors = 1;
  260.     set.fb = fb;
  261.  
  262.     ret = drm_mode_set_config_internal(&set);
  263.  
  264.     if ( !ret )
  265.     {
  266.         struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
  267.         struct kos_framebuffer *kfb = intel_fb->private;
  268.         kolibri_framebuffer_update(dev, kfb);
  269.         DRM_DEBUG_KMS("kolibri framebuffer %p\n", kfb);
  270.  
  271.         os_display->width    = mode->hdisplay;
  272.         os_display->height   = mode->vdisplay;
  273.         os_display->vrefresh = drm_mode_vrefresh(mode);
  274.         sysSetFramebuffer(intel_fb->private);
  275.         sysSetScreen(mode->hdisplay, mode->vdisplay, fb->pitches[0]);
  276.  
  277.         os_display->connector = connector;
  278.         os_display->crtc = connector->encoder->crtc;
  279.         os_display->supported_modes = count_connector_modes(connector);
  280.  
  281.         crtc->cursor_x = os_display->width/2;
  282.         crtc->cursor_y = os_display->height/2;
  283.  
  284.         os_display->select_cursor(os_display->cursor);
  285.  
  286.         DRM_DEBUG_KMS("new mode %d x %d pitch %d\n",
  287.                        mode->hdisplay, mode->vdisplay, fb->pitches[0]);
  288.     }
  289.     else
  290.         DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  291.                    fb->width, fb->height, crtc);
  292.  
  293.     drm_framebuffer_unreference(fb);
  294.     drm_modeset_unlock_all(dev);
  295.  
  296.     return ret;
  297. }
  298.  
  299. static int set_mode_ex(struct drm_device *dev,
  300.                        struct drm_connector *connector, struct drm_display_mode *mode)
  301. {
  302.     struct drm_i915_private *dev_priv = dev->dev_private;
  303.     struct drm_connector    *tmpc;
  304.     struct drm_mode_config  *config   = &dev->mode_config;
  305.     struct drm_framebuffer  *fb       = NULL;
  306.     struct drm_mode_set     set;
  307.     struct drm_crtc *crtc = NULL;
  308.  
  309.     char  con_edid[128];
  310.     int stride;
  311.     int ret;
  312.  
  313.     fb = get_framebuffer(dev, mode, 1);
  314.     if(fb == NULL)
  315.     {
  316.         DRM_ERROR("%s failed\n", __FUNCTION__);
  317.         return -1;
  318.     };
  319.     drm_framebuffer_reference(fb);
  320.  
  321.     drm_modeset_lock_all(dev);
  322.  
  323.     list_for_each_entry(tmpc, &dev->mode_config.connector_list, head)
  324.     {
  325.         const struct drm_connector_funcs *f = tmpc->funcs;
  326.         if(tmpc == connector)
  327.             continue;
  328.         f->dpms(tmpc, DRM_MODE_DPMS_OFF);
  329.     };
  330.  
  331.     crtc = connector->encoder->crtc;
  332.  
  333.     memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  334.     DRM_DEBUG_KMS("set mode %dx%d: crtc %d connector %s\n"
  335.                   "monitor: %s model %x serial number %u\n",
  336.                 mode->hdisplay, mode->vdisplay,
  337.                 connector->encoder->crtc->base.id, connector->name,
  338.                 manufacturer_name(con_edid + 0x08),
  339.                 (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  340.                 (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  341.                 + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  342.  
  343.     drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
  344.  
  345.     crtc->enabled = true;
  346.     os_display->crtc = crtc;
  347.  
  348.     DRM_DEBUG_KMS("use framebuffer %p %dx%d pitch %d format %x\n",
  349.             fb,fb->width,fb->height,fb->pitches[0],fb->pixel_format);
  350.  
  351.     set.crtc = crtc;
  352.     set.x = 0;
  353.     set.y = 0;
  354.     set.mode = mode;
  355.     set.connectors = &connector;
  356.     set.num_connectors = 1;
  357.     set.fb = fb;
  358.  
  359.     ret = drm_mode_set_config_internal(&set);
  360.     if ( !ret )
  361.     {
  362.         struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
  363.         struct kos_framebuffer *kfb = intel_fb->private;
  364.         kolibri_framebuffer_update(dev, kfb);
  365.         DRM_DEBUG_KMS("kolibri framebuffer %p\n", kfb);
  366.  
  367.         os_display->width    = mode->hdisplay;
  368.         os_display->height   = mode->vdisplay;
  369.         os_display->vrefresh = drm_mode_vrefresh(mode);
  370.         sysSetFramebuffer(intel_fb->private);
  371.         sysSetScreen(mode->hdisplay, mode->vdisplay, fb->pitches[0]);
  372.  
  373.         os_display->connector = connector;
  374.         os_display->crtc = connector->encoder->crtc;
  375.         os_display->supported_modes = count_connector_modes(connector);
  376.  
  377.         crtc->cursor_x = os_display->width/2;
  378.         crtc->cursor_y = os_display->height/2;
  379.  
  380.         os_display->select_cursor(os_display->cursor);
  381.  
  382.         DRM_DEBUG_KMS("new mode %d x %d pitch %d\n",
  383.                        mode->hdisplay, mode->vdisplay, fb->pitches[0]);
  384.     }
  385.     else
  386.         DRM_ERROR(" failed to set mode %d_%d on crtc %p\n",
  387.                    fb->width, fb->height, connector->encoder->crtc);
  388.  
  389.     drm_framebuffer_unreference(fb);
  390.     drm_modeset_unlock_all(dev);
  391.     return ret;
  392. }
  393.  
  394. static int set_cmdline_mode(struct drm_device *dev, struct drm_connector *connector)
  395. {
  396.     struct drm_display_mode *mode;
  397.     int retval;
  398.  
  399.     mode = drm_mode_create_from_cmdline_mode(dev, &connector->cmdline_mode);
  400.     if(mode == NULL)
  401.         return EINVAL;
  402.  
  403.     retval = set_mode_ex(dev, connector, mode);
  404.  
  405.     drm_mode_destroy(dev, mode);
  406.     return retval;
  407. };
  408.  
  409. static struct drm_crtc *get_possible_crtc(struct drm_device *dev, struct drm_encoder *encoder)
  410. {
  411.     struct drm_crtc *tmp_crtc;
  412.     int crtc_mask = 1;
  413.  
  414.     list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head)
  415.     {
  416.         if (encoder->possible_crtcs & crtc_mask)
  417.         {
  418.             encoder->crtc = tmp_crtc;
  419.             DRM_DEBUG_KMS("use CRTC %p ID %d\n", tmp_crtc, tmp_crtc->base.id);
  420.             return tmp_crtc;
  421.         };
  422.         crtc_mask <<= 1;
  423.     };
  424.     return NULL;
  425. };
  426.  
  427. static int check_connector(struct drm_device *dev, struct drm_connector *connector)
  428. {
  429.     const struct drm_connector_helper_funcs *connector_funcs;
  430.     struct drm_encoder   *encoder;
  431.     struct drm_crtc      *crtc;
  432.  
  433.     if( connector->status != connector_status_connected)
  434.         return -EINVAL;
  435.  
  436.     encoder = connector->encoder;
  437.  
  438.     if(encoder == NULL)
  439.     {
  440.         connector_funcs = connector->helper_private;
  441.         encoder = connector_funcs->best_encoder(connector);
  442.  
  443.         if( encoder == NULL)
  444.         {
  445.             DRM_DEBUG_KMS("CONNECTOR %s ID: %d no active encoders\n",
  446.             connector->name, connector->base.id);
  447.             return -EINVAL;
  448.         };
  449.         connector->encoder = encoder;
  450.     }
  451.  
  452.     crtc = encoder->crtc;
  453.     if(crtc == NULL)
  454.         crtc = get_possible_crtc(dev, encoder);
  455.  
  456.     if(crtc != NULL)
  457.     {
  458.         DRM_DEBUG_KMS("%s connector: %p encode: %p crtc: %p\n",__FUNCTION__,
  459.                connector, encoder, crtc);
  460.         return 0;
  461.     }
  462.     else
  463.         DRM_DEBUG_KMS("No CRTC for encoder %d\n", encoder->base.id);
  464.     return -EINVAL;
  465. }
  466.  
  467. static struct drm_connector* get_cmdline_connector(struct drm_device *dev, const char *cmdline)
  468. {
  469.     struct drm_connector *connector;
  470.  
  471.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  472.     {
  473.         int name_len = __builtin_strlen(connector->name);
  474.  
  475.         if (name_len == 0)
  476.             continue;
  477.  
  478.         if (__builtin_strncmp(connector->name, cmdline, name_len))
  479.             continue;
  480.  
  481.         if(check_connector(dev, connector) == 0)
  482.             return connector;
  483.     }
  484.     return NULL;
  485. }
  486.  
  487.  
  488. static int choose_config(struct drm_device *dev, struct drm_connector **boot_connector,
  489.                   struct drm_crtc **boot_crtc)
  490. {
  491.     struct drm_connector *connector;
  492.  
  493.     if((i915.cmdline_mode != NULL) && (*i915.cmdline_mode != 0))
  494.     {
  495.         connector = get_cmdline_connector(dev, i915.cmdline_mode);
  496.         if(connector != NULL)
  497.         {
  498.             *boot_connector = connector;
  499.             *boot_crtc = connector->encoder->crtc;
  500.             return 0;
  501.         }
  502.     }
  503.  
  504.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  505.     {
  506.         if(check_connector(dev, connector) == 0)
  507.         {
  508.             *boot_connector = connector;
  509.             *boot_crtc = connector->encoder->crtc;
  510.             return 0;
  511.         };
  512.     };
  513.  
  514.     return -ENOENT;
  515. };
  516.  
  517.  
  518. static int get_boot_mode(struct drm_connector *connector, videomode_t *usermode)
  519. {
  520.     struct drm_display_mode *mode;
  521.  
  522.     list_for_each_entry(mode, &connector->modes, head)
  523.     {
  524.         if( os_display->width  == mode->hdisplay &&
  525.             os_display->height == mode->vdisplay &&
  526.             drm_mode_vrefresh(mode) == 60)
  527.         {
  528.             usermode->width  = os_display->width;
  529.             usermode->height = os_display->height;
  530.             usermode->freq   = 60;
  531.             return 1;
  532.         }
  533.     }
  534.     return 0;
  535. }
  536.  
  537. int init_display_kms(struct drm_device *dev, videomode_t *usermode)
  538. {
  539.     struct drm_connector_helper_funcs *connector_funcs;
  540.     struct drm_connector    *connector = NULL;
  541.     struct drm_crtc         *crtc = NULL;
  542.     struct drm_plane *plane;
  543.  
  544.     int ret;
  545.  
  546.     drm_for_each_plane(plane, dev)
  547.     {
  548.         drm_plane_helper_disable(plane);
  549.     };
  550.  
  551.     mutex_lock(&dev->mode_config.mutex);
  552.     ret = choose_config(dev, &connector, &crtc);
  553.     if(ret)
  554.     {
  555.         mutex_unlock(&dev->mode_config.mutex);
  556.         DRM_DEBUG_KMS("No active connectors!\n");
  557.         return -1;
  558.     };
  559.  
  560.     os_display = GetDisplay();
  561.     os_display->ddev = dev;
  562.     os_display->connector = connector;
  563.     os_display->crtc = crtc;
  564.     os_display->supported_modes = count_connector_modes(connector);
  565.     mutex_unlock(&dev->mode_config.mutex);
  566.  
  567.     init_system_cursors(dev);
  568.  
  569.     ret = -1;
  570.  
  571.     if(connector->cmdline_mode.specified == true)
  572.         ret = set_cmdline_mode(dev, connector);
  573.  
  574.     if(ret !=0)
  575.     {
  576.         mutex_lock(&dev->mode_config.mutex);
  577.  
  578.         if( (usermode->width == 0) ||
  579.             (usermode->height == 0))
  580.         {
  581.             if( !get_boot_mode(connector, usermode))
  582.             {
  583.                 struct drm_display_mode *mode;
  584.  
  585.                 mode = list_entry(connector->modes.next, typeof(*mode), head);
  586.                 usermode->width  = mode->hdisplay;
  587.                 usermode->height = mode->vdisplay;
  588.                 usermode->freq   = drm_mode_vrefresh(mode);
  589.             };
  590.         };
  591.         mutex_unlock(&dev->mode_config.mutex);
  592.  
  593.         set_mode(dev, os_display->connector, os_display->crtc, usermode, false);
  594.     };
  595.  
  596.     return ret;
  597. };
  598.  
  599.  
  600. int set_cmdline_mode_ext(struct drm_device *dev, const char *cmdline)
  601. {
  602.     struct drm_connector_helper_funcs *connector_funcs;
  603.     struct drm_connector    *connector;
  604.     struct drm_cmdline_mode cmd_mode = {0};
  605.     struct drm_display_mode *mode;
  606.     char *mode_option;
  607.     int retval = 0;
  608.     char  con_edid[128];
  609.  
  610.     if((cmdline == NULL) || (*cmdline == 0))
  611.         return EINVAL;
  612.  
  613.     mutex_lock(&dev->mode_config.mutex);
  614.     connector = get_cmdline_connector(dev, cmdline);
  615.     mutex_unlock(&dev->mode_config.mutex);
  616.  
  617.     if(connector == NULL)
  618.         return EINVAL;
  619.  
  620.     mode_option = __builtin_strchr(cmdline,':');
  621.     if(mode_option == NULL)
  622.         return EINVAL;
  623.  
  624.     mode_option++;
  625.  
  626.     if( !drm_mode_parse_command_line_for_connector(mode_option, connector, &cmd_mode))
  627.         return EINVAL;
  628.  
  629.     DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
  630.                    connector->name,
  631.                    cmd_mode.xres, cmd_mode.yres,
  632.                    cmd_mode.refresh_specified ? cmd_mode.refresh : 60,
  633.                    cmd_mode.rb ? " reduced blanking" : "",
  634.                    cmd_mode.margins ? " with margins" : "",
  635.                    cmd_mode.interlace ?  " interlaced" : "");
  636.  
  637.     mode = drm_mode_create_from_cmdline_mode(dev, &cmd_mode);
  638.     if(mode == NULL)
  639.         return EINVAL;
  640.  
  641.     memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  642.     DRM_DEBUG_KMS("connector: %s monitor: %s model %x serial number %u\n",
  643.             connector->name,
  644.             manufacturer_name(con_edid + 0x08),
  645.             (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  646.             (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  647.             + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  648.  
  649.     retval = set_mode_ex(dev, connector, mode);
  650.  
  651.     drm_mode_destroy(dev, mode);
  652.  
  653.     return retval;
  654. }
  655.  
  656. void list_connectors(struct drm_device *dev)
  657. {
  658.     struct drm_connector *connector;
  659.     char  con_edid[128];
  660.  
  661.     mutex_lock(&dev->mode_config.mutex);
  662.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  663.     {
  664.         if( connector->status != connector_status_connected)
  665.             continue;
  666.  
  667.         memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  668.  
  669.         if(connector ==  os_display->connector)
  670.         {
  671.             printf("%s mode %dx%d connected %s model %x serial number %u\n",
  672.                    connector->name, os_display->width, os_display->height,
  673.                    manufacturer_name(con_edid + 0x08),
  674.                    (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  675.                    (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  676.                    + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  677.             continue;
  678.         }
  679.         else
  680.         {
  681.             printf("%s connected: %s model %x serial number %u\n",
  682.                 connector->name, manufacturer_name(con_edid + 0x08),
  683.                 (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  684.                 (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  685.                 + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  686.         }
  687.     };
  688.     mutex_unlock(&dev->mode_config.mutex);
  689. }
  690.  
  691. int list_connector_modes(struct drm_device *dev, const char* name)
  692. {
  693.     struct drm_connector *connector;
  694.     struct drm_display_mode  *drmmode;
  695.  
  696.     mutex_lock(&dev->mode_config.mutex);
  697.  
  698.     connector = get_cmdline_connector(dev, name);
  699.     if(connector == NULL)
  700.     {
  701.         mutex_unlock(&dev->mode_config.mutex);
  702.         return EINVAL;
  703.     };
  704.  
  705.     printf("connector %s probed modes :\n", connector->name);
  706.  
  707.     list_for_each_entry(drmmode, &connector->modes, head)
  708.     {
  709.         printf("%dx%d@%d\n", drmmode->hdisplay, drmmode->vdisplay, drm_mode_vrefresh(drmmode));
  710.     };
  711.  
  712.     mutex_unlock(&dev->mode_config.mutex);
  713.     return 0;
  714. };
  715.  
  716. int get_videomodes(videomode_t *mode, int *count)
  717. {
  718.     int err = -1;
  719.  
  720. //    dbgprintf("mode %x count %d\n", mode, *count);
  721.  
  722.     if( *count == 0 )
  723.     {
  724.         *count = os_display->supported_modes;
  725.         err = 0;
  726.     }
  727.     else if( mode != NULL )
  728.     {
  729.         struct drm_display_mode  *drmmode;
  730.         int i = 0;
  731.  
  732.         if( *count > os_display->supported_modes)
  733.             *count = os_display->supported_modes;
  734.  
  735.         list_for_each_entry(drmmode, &os_display->connector->modes, head)
  736.         {
  737.             if( i < *count)
  738.             {
  739.                 mode->width  = drmmode->hdisplay;
  740.                 mode->height = drmmode->vdisplay;
  741.                 mode->bpp    = 32;
  742.                 mode->freq   = drm_mode_vrefresh(drmmode);
  743.                 i++;
  744.                 mode++;
  745.             }
  746.             else break;
  747.         };
  748.         *count = i;
  749.         err = 0;
  750.     };
  751.     return err;
  752. };
  753.  
  754. int set_user_mode(videomode_t *mode)
  755. {
  756.  
  757. //    dbgprintf("width %d height %d vrefresh %d\n",
  758. //               mode->width, mode->height, mode->freq);
  759.  
  760.     if( (mode->width  != 0)  &&
  761.         (mode->height != 0)  &&
  762.         (mode->freq   != 0 ) &&
  763.         ( (mode->width   != os_display->width)  ||
  764.           (mode->height  != os_display->height) ||
  765.           (mode->freq    != os_display->vrefresh) ) )
  766.     {
  767.         return set_mode(os_display->ddev, os_display->connector, os_display->crtc, mode, true);
  768.     };
  769.  
  770.     return -1;
  771. };
  772.  
  773. void i915_dpms(struct drm_device *dev, int mode)
  774. {
  775.     const struct drm_connector_funcs *f = os_display->connector->funcs;
  776.  
  777.     f->dpms(os_display->connector, mode);
  778. };
  779.  
  780.  
  781. int i915_fbinfo(struct drm_i915_fb_info *fb)
  782. {
  783.     u32 ifl;
  784.  
  785.     ifl = safe_cli();
  786.     {
  787.         struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  788.         struct intel_crtc *crtc = to_intel_crtc(os_display->crtc);
  789.         struct kos_framebuffer *kfb = os_display->current_lfb;
  790.         struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)kfb->private;
  791.         struct drm_i915_gem_object *obj = intel_fb->obj;
  792.  
  793.         fb->name   = obj->base.name;
  794.         fb->width  = os_display->width;
  795.         fb->height = os_display->height;
  796.         fb->pitch  = os_display->lfb_pitch;
  797.         fb->tiling = obj->tiling_mode;
  798.         fb->crtc   = crtc->base.base.id;
  799.         fb->pipe   = crtc->pipe;
  800.     }
  801.     safe_sti(ifl);
  802.  
  803.     return 0;
  804. }
  805.  
  806.  
  807. typedef struct
  808. {
  809.     int left;
  810.     int top;
  811.     int right;
  812.     int bottom;
  813. }rect_t;
  814.  
  815.  
  816. #define CURRENT_TASK             (0x80003000)
  817.  
  818. void  FASTCALL GetWindowRect(rect_t *rc)__asm__("GetWindowRect");
  819.  
  820. int i915_mask_update(struct drm_device *dev, void *data,
  821.             struct drm_file *file)
  822. {
  823.     struct drm_i915_mask *mask = data;
  824.     struct drm_gem_object *obj;
  825.     static unsigned int mask_seqno[256];
  826.     rect_t winrc;
  827.     u32    slot;
  828.     int    ret=0;
  829.  
  830.     obj = drm_gem_object_lookup(dev, file, mask->handle);
  831.     if (obj == NULL)
  832.         return -ENOENT;
  833.  
  834.     if (!obj->filp) {
  835.         drm_gem_object_unreference_unlocked(obj);
  836.         return -EINVAL;
  837.     }
  838.  
  839.     GetWindowRect(&winrc);
  840.     {
  841. //        static warn_count;
  842.  
  843.         mask->width    = winrc.right - winrc.left + 1;
  844.         mask->height   = winrc.bottom - winrc.top + 1;
  845.         mask->bo_pitch = (mask->width+15) & ~15;
  846.  
  847. #if 0
  848.         if(warn_count < 1)
  849.         {
  850.             printf("left %d top %d right %d bottom %d\n",
  851.                     winrc.left, winrc.top, winrc.right, winrc.bottom);
  852.             printf("mask pitch %d data %p\n", mask->bo_pitch, mask->bo_map);
  853.             warn_count++;
  854.         };
  855. #endif
  856.  
  857.      };
  858.  
  859.  
  860.     slot = *((u8*)CURRENT_TASK);
  861.  
  862.     if( mask_seqno[slot] != os_display->mask_seqno)
  863.     {
  864.         u8* src_offset;
  865.         u8* dst_offset;
  866.         u32 ifl;
  867.  
  868.         ret = i915_mutex_lock_interruptible(dev);
  869.         if (ret)
  870.             goto err1;
  871.  
  872.         ret = i915_gem_object_set_to_cpu_domain(to_intel_bo(obj), true);
  873.         if(ret != 0 )
  874.         {
  875.             dbgprintf("%s: i915_gem_object_set_to_cpu_domain failed\n", __FUNCTION__);
  876.             goto err2;
  877.         };
  878.  
  879. //        printf("width %d height %d\n", winrc.right, winrc.bottom);
  880.  
  881. //        slot = 0x01;
  882.  
  883.         src_offset = os_display->win_map;
  884.         src_offset+= winrc.top*os_display->width + winrc.left;
  885.  
  886.         dst_offset = (u8*)mask->bo_map;
  887.  
  888.         u32 tmp_h = mask->height;
  889.  
  890.         ifl = safe_cli();
  891.         {
  892.             mask_seqno[slot] = os_display->mask_seqno;
  893.  
  894.             slot|= (slot<<8)|(slot<<16)|(slot<<24);
  895.  
  896.             __asm__ __volatile__ (
  897.             "movd       %[slot],   %%xmm6         \n"
  898.             "punpckldq  %%xmm6, %%xmm6            \n"
  899.             "punpcklqdq %%xmm6, %%xmm6            \n"
  900.             :: [slot]  "m" (slot)
  901.             :"xmm6");
  902.  
  903.             while( tmp_h--)
  904.             {
  905.                 int tmp_w = mask->width;
  906.  
  907.                 u8* tmp_src = src_offset;
  908.                 u8* tmp_dst = dst_offset;
  909.  
  910.                 src_offset+= os_display->width;
  911.                 dst_offset+= mask->bo_pitch;
  912.  
  913.                 while(tmp_w >= 64)
  914.                 {
  915.                     __asm__ __volatile__ (
  916.                     "movdqu     (%0),   %%xmm0            \n"
  917.                     "movdqu   16(%0),   %%xmm1            \n"
  918.                     "movdqu   32(%0),   %%xmm2            \n"
  919.                     "movdqu   48(%0),   %%xmm3            \n"
  920.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  921.                     "pcmpeqb    %%xmm6, %%xmm1            \n"
  922.                     "pcmpeqb    %%xmm6, %%xmm2            \n"
  923.                     "pcmpeqb    %%xmm6, %%xmm3            \n"
  924.                     "movdqa     %%xmm0,   (%%edi)         \n"
  925.                     "movdqa     %%xmm1, 16(%%edi)         \n"
  926.                     "movdqa     %%xmm2, 32(%%edi)         \n"
  927.                     "movdqa     %%xmm3, 48(%%edi)         \n"
  928.  
  929.                     :: "r" (tmp_src), "D" (tmp_dst)
  930.                     :"xmm0","xmm1","xmm2","xmm3");
  931.                     tmp_w -= 64;
  932.                     tmp_src += 64;
  933.                     tmp_dst += 64;
  934.                 }
  935.  
  936.                 if( tmp_w >= 32 )
  937.                 {
  938.                     __asm__ __volatile__ (
  939.                     "movdqu     (%0),   %%xmm0            \n"
  940.                     "movdqu   16(%0),   %%xmm1            \n"
  941.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  942.                     "pcmpeqb    %%xmm6, %%xmm1            \n"
  943.                     "movdqa     %%xmm0,   (%%edi)         \n"
  944.                     "movdqa     %%xmm1, 16(%%edi)         \n"
  945.  
  946.                     :: "r" (tmp_src), "D" (tmp_dst)
  947.                     :"xmm0","xmm1");
  948.                     tmp_w -= 32;
  949.                     tmp_src += 32;
  950.                     tmp_dst += 32;
  951.                 }
  952.  
  953.                 if( tmp_w >= 16 )
  954.                 {
  955.                     __asm__ __volatile__ (
  956.                     "movdqu     (%0),   %%xmm0            \n"
  957.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  958.                     "movdqa     %%xmm0,   (%%edi)         \n"
  959.                     :: "r" (tmp_src), "D" (tmp_dst)
  960.                     :"xmm0");
  961.                     tmp_w -= 16;
  962.                     tmp_src += 16;
  963.                     tmp_dst += 16;
  964.                 }
  965.  
  966.                 if( tmp_w >= 8 )
  967.                 {
  968.                     __asm__ __volatile__ (
  969.                     "movq       (%0),   %%xmm0            \n"
  970.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  971.                     "movq       %%xmm0,   (%%edi)         \n"
  972.                     :: "r" (tmp_src), "D" (tmp_dst)
  973.                     :"xmm0");
  974.                     tmp_w -= 8;
  975.                     tmp_src += 8;
  976.                     tmp_dst += 8;
  977.                 }
  978.                 if( tmp_w >= 4 )
  979.                 {
  980.                     __asm__ __volatile__ (
  981.                     "movd       (%0),   %%xmm0            \n"
  982.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  983.                     "movd       %%xmm0,   (%%edi)         \n"
  984.                     :: "r" (tmp_src), "D" (tmp_dst)
  985.                     :"xmm0");
  986.                     tmp_w -= 4;
  987.                     tmp_src += 4;
  988.                     tmp_dst += 4;
  989.                 }
  990.                 while(tmp_w--)
  991.                     *tmp_dst++ = (*tmp_src++ == (u8)slot) ? 0xFF:0x00;
  992.             };
  993.         };
  994.         safe_sti(ifl);
  995.  
  996.         ret = i915_gem_object_set_to_gtt_domain(to_intel_bo(obj), false);
  997.     }
  998.  
  999. err2:
  1000.     mutex_unlock(&dev->struct_mutex);
  1001. err1:
  1002.     drm_gem_object_unreference(obj);
  1003.  
  1004.     return ret;
  1005. }
  1006.  
  1007. int i915_mask_update_ex(struct drm_device *dev, void *data,
  1008.             struct drm_file *file)
  1009. {
  1010.     struct drm_i915_mask_update *mask = data;
  1011.     struct drm_gem_object *obj;
  1012.     static unsigned int mask_seqno[256];
  1013.     static int warn_count;
  1014.  
  1015.     rect_t win;
  1016.     u32    winw,winh;
  1017.     u32    ml,mt,mr,mb;
  1018.     u32    slot;
  1019.     int    ret = 0;
  1020.     slot = *((u8*)CURRENT_TASK);
  1021.  
  1022.     if( mask->forced == 0 && mask_seqno[slot] == os_display->mask_seqno)
  1023.         return 0;
  1024.  
  1025.     if(mask->forced)
  1026.         memset((void*)mask->bo_map,0,mask->width * mask->height);
  1027.  
  1028.     GetWindowRect(&win);
  1029.     win.right+= 1;
  1030.     win.bottom+=  1;
  1031.  
  1032.     winw = win.right - win.left;
  1033.     winh = win.bottom - win.top;
  1034.  
  1035.     if(mask->dx >= winw ||
  1036.        mask->dy >= winh)
  1037.        return 1;
  1038.  
  1039.     ml = win.left + mask->dx;
  1040.     mt = win.top  + mask->dy;
  1041.     mr = ml + mask->width;
  1042.     mb = mt + mask->height;
  1043.  
  1044.     if( ml >= win.right || mt >= win.bottom ||
  1045.         mr < win.left   || mb < win.top )
  1046.         return 1;
  1047.  
  1048.     if( mr > win.right )
  1049.         mr = win.right;
  1050.  
  1051.     if( mb > win.bottom )
  1052.         mb = win.bottom;
  1053.  
  1054.     mask->width  = mr - ml;
  1055.     mask->height = mb - mt;
  1056.  
  1057.     if( mask->width == 0 ||
  1058.         mask->height== 0 )
  1059.         return 1;
  1060.  
  1061.     ret = i915_mutex_lock_interruptible(dev);
  1062.     if (ret)
  1063.         return ret;
  1064.  
  1065.     obj = drm_gem_object_lookup(dev, file, mask->handle);
  1066.     if (obj == NULL)
  1067.     {
  1068.         ret = -ENOENT;
  1069.         goto unlock;
  1070.     }
  1071.  
  1072.     if (!obj->filp)
  1073.     {
  1074.         ret = -ENOENT;
  1075.         goto out;
  1076.     }
  1077.  
  1078. #if 0
  1079.     if(warn_count < 100)
  1080.     {
  1081.         printf("left %d top %d right %d bottom %d\n",
  1082.                 ml, mt, mr, mb);
  1083.         warn_count++;
  1084.     };
  1085. #endif
  1086.  
  1087.  
  1088. #if 1
  1089.  
  1090.     {
  1091.         u8* src_offset;
  1092.         u8* dst_offset;
  1093.         u32 ifl;
  1094.  
  1095.         i915_gem_object_set_to_cpu_domain(to_intel_bo(obj), true);
  1096.  
  1097.         src_offset = os_display->win_map;
  1098.         src_offset+= mt*os_display->width + ml;
  1099.         dst_offset = (u8*)mask->bo_map;
  1100.  
  1101.         u32 tmp_h = mask->height;
  1102.  
  1103.         ifl = safe_cli();
  1104.         {
  1105.             mask_seqno[slot] = os_display->mask_seqno;
  1106.  
  1107.             slot|= (slot<<8)|(slot<<16)|(slot<<24);
  1108.  
  1109.             __asm__ __volatile__ (
  1110.             "movd       %[slot],   %%xmm6         \n"
  1111.             "punpckldq  %%xmm6, %%xmm6            \n"
  1112.             "punpcklqdq %%xmm6, %%xmm6            \n"
  1113.             :: [slot]  "m" (slot)
  1114.             :"xmm6");
  1115.  
  1116.             while( tmp_h--)
  1117.             {
  1118.                 int tmp_w = mask->width;
  1119.  
  1120.                 u8* tmp_src = src_offset;
  1121.                 u8* tmp_dst = dst_offset;
  1122.  
  1123.                 src_offset+= os_display->width;
  1124.                 dst_offset+= mask->bo_pitch;
  1125.  
  1126.                 while(tmp_w >= 64)
  1127.                 {
  1128.                     __asm__ __volatile__ (
  1129.                     "movdqu     (%0),   %%xmm0            \n"
  1130.                     "movdqu   16(%0),   %%xmm1            \n"
  1131.                     "movdqu   32(%0),   %%xmm2            \n"
  1132.                     "movdqu   48(%0),   %%xmm3            \n"
  1133.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  1134.                     "pcmpeqb    %%xmm6, %%xmm1            \n"
  1135.                     "pcmpeqb    %%xmm6, %%xmm2            \n"
  1136.                     "pcmpeqb    %%xmm6, %%xmm3            \n"
  1137.                     "movdqa     %%xmm0,   (%%edi)         \n"
  1138.                     "movdqa     %%xmm1, 16(%%edi)         \n"
  1139.                     "movdqa     %%xmm2, 32(%%edi)         \n"
  1140.                     "movdqa     %%xmm3, 48(%%edi)         \n"
  1141.  
  1142.                     :: "r" (tmp_src), "D" (tmp_dst)
  1143.                     :"xmm0","xmm1","xmm2","xmm3");
  1144.                     tmp_w -= 64;
  1145.                     tmp_src += 64;
  1146.                     tmp_dst += 64;
  1147.                 }
  1148.  
  1149.                 if( tmp_w >= 32 )
  1150.                 {
  1151.                     __asm__ __volatile__ (
  1152.                     "movdqu     (%0),   %%xmm0            \n"
  1153.                     "movdqu   16(%0),   %%xmm1            \n"
  1154.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  1155.                     "pcmpeqb    %%xmm6, %%xmm1            \n"
  1156.                     "movdqa     %%xmm0,   (%%edi)         \n"
  1157.                     "movdqa     %%xmm1, 16(%%edi)         \n"
  1158.  
  1159.                     :: "r" (tmp_src), "D" (tmp_dst)
  1160.                     :"xmm0","xmm1");
  1161.                     tmp_w -= 32;
  1162.                     tmp_src += 32;
  1163.                     tmp_dst += 32;
  1164.                 }
  1165.  
  1166.                 if( tmp_w >= 16 )
  1167.                 {
  1168.                     __asm__ __volatile__ (
  1169.                     "movdqu     (%0),   %%xmm0            \n"
  1170.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  1171.                     "movdqa     %%xmm0,   (%%edi)         \n"
  1172.                     :: "r" (tmp_src), "D" (tmp_dst)
  1173.                     :"xmm0");
  1174.                     tmp_w -= 16;
  1175.                     tmp_src += 16;
  1176.                     tmp_dst += 16;
  1177.                 }
  1178.  
  1179.                 if( tmp_w >= 8 )
  1180.                 {
  1181.                     __asm__ __volatile__ (
  1182.                     "movq       (%0),   %%xmm0            \n"
  1183.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  1184.                     "movq       %%xmm0,   (%%edi)         \n"
  1185.                     :: "r" (tmp_src), "D" (tmp_dst)
  1186.                     :"xmm0");
  1187.                     tmp_w -= 8;
  1188.                     tmp_src += 8;
  1189.                     tmp_dst += 8;
  1190.                 }
  1191.                 if( tmp_w >= 4 )
  1192.                 {
  1193.                     __asm__ __volatile__ (
  1194.                     "movd       (%0),   %%xmm0            \n"
  1195.                     "pcmpeqb    %%xmm6, %%xmm0            \n"
  1196.                     "movd       %%xmm0,   (%%edi)         \n"
  1197.                     :: "r" (tmp_src), "D" (tmp_dst)
  1198.                     :"xmm0");
  1199.                     tmp_w -= 4;
  1200.                     tmp_src += 4;
  1201.                     tmp_dst += 4;
  1202.                 }
  1203.                 while(tmp_w--)
  1204.                     *tmp_dst++ = (*tmp_src++ == (u8)slot) ? 0xFF:0x00;
  1205.             };
  1206.         };
  1207.         safe_sti(ifl);
  1208.  
  1209.         i915_gem_object_set_to_gtt_domain(to_intel_bo(obj), false);
  1210.     }
  1211. #endif
  1212.  
  1213. out:
  1214.     drm_gem_object_unreference(obj);
  1215.  
  1216. unlock:
  1217.     mutex_unlock(&dev->struct_mutex);
  1218.  
  1219.     return ret;
  1220. }
  1221.  
  1222.  
  1223.  
  1224.  
  1225. #define NSEC_PER_SEC    1000000000L
  1226.  
  1227. void getrawmonotonic(struct timespec *ts)
  1228. {
  1229.     u32 tmp = GetTimerTicks();
  1230.  
  1231.     ts->tv_sec  = tmp/100;
  1232.     ts->tv_nsec = (tmp - ts->tv_sec*100)*10000000;
  1233. }
  1234.  
  1235. void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
  1236. {
  1237.     unsigned long flags;
  1238.  
  1239. //    wait->flags &= ~WQ_FLAG_EXCLUSIVE;
  1240.     spin_lock_irqsave(&q->lock, flags);
  1241.     if (list_empty(&wait->task_list))
  1242.             __add_wait_queue(q, wait);
  1243.     spin_unlock_irqrestore(&q->lock, flags);
  1244. }
  1245.  
  1246. /**
  1247.  * finish_wait - clean up after waiting in a queue
  1248.  * @q: waitqueue waited on
  1249.  * @wait: wait descriptor
  1250.  *
  1251.  * Sets current thread back to running state and removes
  1252.  * the wait descriptor from the given waitqueue if still
  1253.  * queued.
  1254.  */
  1255. void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
  1256. {
  1257.     unsigned long flags;
  1258.  
  1259. //    __set_current_state(TASK_RUNNING);
  1260.     /*
  1261.      * We can check for list emptiness outside the lock
  1262.      * IFF:
  1263.      *  - we use the "careful" check that verifies both
  1264.      *    the next and prev pointers, so that there cannot
  1265.      *    be any half-pending updates in progress on other
  1266.      *    CPU's that we haven't seen yet (and that might
  1267.      *    still change the stack area.
  1268.      * and
  1269.      *  - all other users take the lock (ie we can only
  1270.      *    have _one_ other CPU that looks at or modifies
  1271.      *    the list).
  1272.      */
  1273.     if (!list_empty_careful(&wait->task_list)) {
  1274.             spin_lock_irqsave(&q->lock, flags);
  1275.             list_del_init(&wait->task_list);
  1276.             spin_unlock_irqrestore(&q->lock, flags);
  1277.     }
  1278.  
  1279.     DestroyEvent(wait->evnt);
  1280. }
  1281.  
  1282. int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
  1283. {
  1284.     list_del_init(&wait->task_list);
  1285.     return 1;
  1286. }
  1287.