Subversion Repositories Kolibri OS

Rev

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