Subversion Repositories Kolibri OS

Rev

Rev 6296 | Rev 6660 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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