Subversion Repositories Kolibri OS

Rev

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