Subversion Repositories Kolibri OS

Rev

Rev 2360 | Rev 3031 | 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 "drmP.h"
  5. #include "drm.h"
  6. #include "i915_drm.h"
  7. #include "i915_drv.h"
  8. #include "intel_drv.h"
  9.  
  10. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #include <linux/mod_devicetable.h>
  13. #include <errno-base.h>
  14. #include <linux/pci.h>
  15.  
  16. #include <syscall.h>
  17.  
  18. #include "bitmap.h"
  19.  
  20. extern struct drm_device *main_device;
  21.  
  22.  
  23. typedef struct
  24. {
  25.     kobj_t     header;
  26.  
  27.     uint32_t  *data;
  28.     uint32_t   hot_x;
  29.     uint32_t   hot_y;
  30.  
  31.     struct list_head   list;
  32.     struct drm_i915_gem_object  *cobj;
  33. }cursor_t;
  34.  
  35. #define CURSOR_WIDTH 64
  36. #define CURSOR_HEIGHT 64
  37.  
  38.  
  39. struct tag_display
  40. {
  41.     int  x;
  42.     int  y;
  43.     int  width;
  44.     int  height;
  45.     int  bpp;
  46.     int  vrefresh;
  47.     int  pitch;
  48.     int  lfb;
  49.  
  50.     int  supported_modes;
  51.     struct drm_device    *ddev;
  52.     struct drm_connector *connector;
  53.     struct drm_crtc      *crtc;
  54.  
  55.     struct list_head   cursors;
  56.  
  57.     cursor_t   *cursor;
  58.     int       (*init_cursor)(cursor_t*);
  59.     cursor_t* (__stdcall *select_cursor)(cursor_t*);
  60.     void      (*show_cursor)(int show);
  61.     void      (__stdcall *move_cursor)(cursor_t *cursor, int x, int y);
  62.     void      (__stdcall *restore_cursor)(int x, int y);
  63.     void      (*disable_mouse)(void);
  64.     u32  mask_seqno;
  65. };
  66.  
  67.  
  68. static display_t *os_display;
  69.  
  70. u32_t cmd_buffer;
  71. u32_t cmd_offset;
  72.  
  73. void init_render();
  74. int  sna_init();
  75.  
  76. int init_cursor(cursor_t *cursor);
  77. static cursor_t*  __stdcall select_cursor_kms(cursor_t *cursor);
  78. static void       __stdcall move_cursor_kms(cursor_t *cursor, int x, int y);
  79.  
  80. void __stdcall restore_cursor(int x, int y)
  81. {};
  82.  
  83. void disable_mouse(void)
  84. {};
  85.  
  86. static int count_connector_modes(struct drm_connector* connector)
  87. {
  88.     struct drm_display_mode  *mode;
  89.     int count = 0;
  90.  
  91.     list_for_each_entry(mode, &connector->modes, head)
  92.     {
  93.         count++;
  94.     };
  95.     return count;
  96. };
  97.  
  98. int init_display_kms(struct drm_device *dev)
  99. {
  100.     struct drm_connector    *connector;
  101.     struct drm_connector_helper_funcs *connector_funcs;
  102.     struct drm_encoder      *encoder;
  103.     struct drm_crtc         *crtc = NULL;
  104.     struct drm_framebuffer  *fb;
  105.  
  106.     cursor_t  *cursor;
  107.     u32_t      ifl;
  108.  
  109.     ENTER();
  110.  
  111.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  112.     {
  113.         if( connector->status != connector_status_connected)
  114.             continue;
  115.  
  116.         connector_funcs = connector->helper_private;
  117.         encoder = connector_funcs->best_encoder(connector);
  118.         if( encoder == NULL)
  119.         {
  120.             dbgprintf("CONNECTOR %x ID: %d no active encoders\n",
  121.                       connector, connector->base.id);
  122.             continue;
  123.         }
  124.         connector->encoder = encoder;
  125.  
  126.         dbgprintf("CONNECTOR %x ID:  %d status %d encoder %x\n crtc %x\n",
  127.                connector, connector->base.id,
  128.                connector->status, connector->encoder,
  129.                encoder->crtc);
  130.  
  131.         crtc = encoder->crtc;
  132.         break;
  133.     };
  134.  
  135.     if(connector == NULL)
  136.     {
  137.         dbgprintf("No active connectors!\n");
  138.         return -1;
  139.     };
  140.  
  141.     if(crtc == NULL)
  142.     {
  143.         struct drm_crtc *tmp_crtc;
  144.         int crtc_mask = 1;
  145.  
  146.         list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head)
  147.         {
  148.             if (encoder->possible_crtcs & crtc_mask)
  149.             {
  150.                 crtc = tmp_crtc;
  151.                 encoder->crtc = crtc;
  152.                 break;
  153.             };
  154.             crtc_mask <<= 1;
  155.         };
  156.     };
  157.  
  158.     if(crtc == NULL)
  159.     {
  160.         dbgprintf("No CRTC for encoder %d\n", encoder->base.id);
  161.         return -1;
  162.     };
  163.  
  164.  
  165.     DRM_DEBUG_KMS("[Select CRTC:%d]\n", crtc->base.id);
  166.  
  167.     os_display = GetDisplay();
  168.  
  169.     os_display->ddev = dev;
  170.     os_display->connector = connector;
  171.     os_display->crtc = crtc;
  172.  
  173.     os_display->supported_modes = count_connector_modes(connector);
  174.  
  175.  
  176.     ifl = safe_cli();
  177.     {
  178.         struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  179.  
  180.         list_for_each_entry(cursor, &os_display->cursors, list)
  181.         {
  182.             init_cursor(cursor);
  183.         };
  184.  
  185.         os_display->restore_cursor(0,0);
  186.         os_display->init_cursor    = init_cursor;
  187.         os_display->select_cursor  = select_cursor_kms;
  188.         os_display->show_cursor    = NULL;
  189.         os_display->move_cursor    = move_cursor_kms;
  190.         os_display->restore_cursor = restore_cursor;
  191.         os_display->disable_mouse  = disable_mouse;
  192.  
  193.         intel_crtc->cursor_x = os_display->width/2;
  194.         intel_crtc->cursor_y = os_display->height/2;
  195.  
  196.         select_cursor_kms(os_display->cursor);
  197.     };
  198.     safe_sti(ifl);
  199.  
  200. #define XY_COLOR_BLT        ((2<<29)|(0x50<<22)|(0x4))
  201. #define BLT_WRITE_ALPHA     (1<<21)
  202. #define BLT_WRITE_RGB       (1<<20)
  203.  
  204. #if 1
  205.     {
  206.  
  207.         drm_i915_private_t *dev_priv = dev->dev_private;
  208.         struct drm_i915_gem_object *obj;
  209.         struct intel_ring_buffer *ring;
  210.  
  211.         obj = i915_gem_alloc_object(dev, 4096);
  212.         i915_gem_object_pin(obj, 4096, true);
  213.  
  214.         cmd_buffer = MapIoMem((addr_t)obj->pages[0], 4096, PG_SW|PG_NOCACHE);
  215.         cmd_offset = obj->gtt_offset;
  216.     };
  217. #endif
  218.  
  219.     main_device = dev;
  220.  
  221.     int err;
  222.  
  223.     err = init_bitmaps();
  224.     if( !err )
  225.     {
  226.         printf("Initialize bitmap manager\n");
  227.     };
  228.  
  229.     sna_init();
  230.  
  231.     LEAVE();
  232.  
  233.     return 0;
  234. };
  235.  
  236.  
  237. bool set_mode(struct drm_device *dev, struct drm_connector *connector,
  238.               videomode_t *reqmode, bool strict)
  239. {
  240.     struct drm_display_mode  *mode = NULL, *tmpmode;
  241.     drm_i915_private_t *dev_priv = dev->dev_private;
  242.     struct drm_fb_helper *fb_helper = &dev_priv->fbdev->helper;
  243.  
  244.     bool ret = false;
  245.  
  246.     ENTER();
  247.  
  248.     dbgprintf("width %d height %d vrefresh %d\n",
  249.                reqmode->width, reqmode->height, reqmode->freq);
  250.  
  251.     list_for_each_entry(tmpmode, &connector->modes, head)
  252.     {
  253.         if( (drm_mode_width(tmpmode)    == reqmode->width)  &&
  254.             (drm_mode_height(tmpmode)   == reqmode->height) &&
  255.             (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
  256.         {
  257.             mode = tmpmode;
  258.             goto do_set;
  259.         }
  260.     };
  261.  
  262.     if( (mode == NULL) && (strict == false) )
  263.     {
  264.         list_for_each_entry(tmpmode, &connector->modes, head)
  265.         {
  266.             if( (drm_mode_width(tmpmode)  == reqmode->width)  &&
  267.                 (drm_mode_height(tmpmode) == reqmode->height) )
  268.             {
  269.                 mode = tmpmode;
  270.                 goto do_set;
  271.             }
  272.         };
  273.     };
  274.  
  275. do_set:
  276.  
  277.     if( mode != NULL )
  278.     {
  279.         struct drm_framebuffer   *fb;
  280.         struct drm_encoder       *encoder;
  281.         struct drm_crtc          *crtc;
  282.  
  283.         char *con_name;
  284.         char *enc_name;
  285.  
  286.         encoder = connector->encoder;
  287.         crtc = encoder->crtc;
  288.  
  289.         con_name = drm_get_connector_name(connector);
  290.         enc_name = drm_get_encoder_name(encoder);
  291.  
  292.         dbgprintf("set mode %d %d connector %s encoder %s\n",
  293.                    reqmode->width, reqmode->height, con_name, enc_name);
  294.  
  295.         fb = fb_helper->fb;
  296.  
  297.         fb->width  = reqmode->width;
  298.         fb->height = reqmode->height;
  299.         fb->pitches[0]  = ALIGN(reqmode->width * 4, 64);
  300.         fb->pitches[1]  = ALIGN(reqmode->width * 4, 64);
  301.         fb->pitches[2]  = ALIGN(reqmode->width * 4, 64);
  302.         fb->pitches[3]  = ALIGN(reqmode->width * 4, 64);
  303.  
  304.         fb->bits_per_pixel = 32;
  305.         fb->depth == 24;
  306.  
  307.         crtc->fb = fb;
  308.         crtc->enabled = true;
  309.         os_display->crtc = crtc;
  310.  
  311.         ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
  312.  
  313. //        select_cursor_kms(rdisplay->cursor);
  314. //        radeon_show_cursor_kms(crtc);
  315.  
  316.         if (ret == true)
  317.         {
  318.             os_display->width    = fb->width;
  319.             os_display->height   = fb->height;
  320.             os_display->pitch    = fb->pitches[0];
  321.             os_display->vrefresh = drm_mode_vrefresh(mode);
  322.  
  323.             sysSetScreen(fb->width, fb->height, fb->pitches[0]);
  324.  
  325.             dbgprintf("new mode %d x %d pitch %d\n",
  326.                        fb->width, fb->height, fb->pitches[0]);
  327.         }
  328.         else
  329.             DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  330.                        fb->width, fb->height, crtc);
  331.     }
  332.  
  333.     LEAVE();
  334.     return ret;
  335. };
  336.  
  337.  
  338.  
  339. int get_videomodes(videomode_t *mode, int *count)
  340. {
  341.     int err = -1;
  342.  
  343.     ENTER();
  344.  
  345.     dbgprintf("mode %x count %d\n", mode, *count);
  346.  
  347.     if( *count == 0 )
  348.     {
  349.         *count = os_display->supported_modes;
  350.         err = 0;
  351.     }
  352.     else if( mode != NULL )
  353.     {
  354.         struct drm_display_mode  *drmmode;
  355.         int i = 0;
  356.  
  357.         if( *count > os_display->supported_modes)
  358.             *count = os_display->supported_modes;
  359.  
  360.         list_for_each_entry(drmmode, &os_display->connector->modes, head)
  361.         {
  362.             if( i < *count)
  363.             {
  364.                 mode->width  = drm_mode_width(drmmode);
  365.                 mode->height = drm_mode_height(drmmode);
  366.                 mode->bpp    = 32;
  367.                 mode->freq   = drm_mode_vrefresh(drmmode);
  368.                 i++;
  369.                 mode++;
  370.             }
  371.             else break;
  372.         };
  373.         *count = i;
  374.         err = 0;
  375.     };
  376.     LEAVE();
  377.     return err;
  378. };
  379.  
  380. int set_user_mode(videomode_t *mode)
  381. {
  382.     int err = -1;
  383.  
  384.     ENTER();
  385.  
  386.     dbgprintf("width %d height %d vrefresh %d\n",
  387.                mode->width, mode->height, mode->freq);
  388.  
  389.     if( (mode->width  != 0)  &&
  390.         (mode->height != 0)  &&
  391.         (mode->freq   != 0 ) &&
  392.         ( (mode->width   != os_display->width)  ||
  393.           (mode->height  != os_display->height) ||
  394.           (mode->freq    != os_display->vrefresh) ) )
  395.     {
  396.         if( set_mode(os_display->ddev, os_display->connector, mode, true) )
  397.             err = 0;
  398.     };
  399.  
  400.     LEAVE();
  401.     return err;
  402. };
  403.  
  404. void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor)
  405. {
  406. /*  FIXME    synchronization */
  407.  
  408.     list_del(&cursor->list);
  409. //    radeon_bo_unpin(cursor->robj);
  410. //    KernelFree(cursor->data);
  411.     __DestroyObject(cursor);
  412. };
  413.  
  414. int init_cursor(cursor_t *cursor)
  415. {
  416.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  417.     struct drm_i915_gem_object *obj;
  418.     uint32_t *bits;
  419.     uint32_t *src;
  420.  
  421.     int       i,j;
  422.     int       ret;
  423.  
  424.     ENTER();
  425.  
  426.     if (dev_priv->info->cursor_needs_physical)
  427.     {
  428.         bits = (uint32_t*)KernelAlloc(CURSOR_WIDTH*CURSOR_HEIGHT*4);
  429.         if (unlikely(bits == NULL))
  430.             return ENOMEM;
  431.         cursor->cobj = (struct drm_i915_gem_object *)GetPgAddr(bits);
  432.     }
  433.     else
  434.     {
  435.         obj = i915_gem_alloc_object(os_display->ddev, CURSOR_WIDTH*CURSOR_HEIGHT*4);
  436.         if (unlikely(obj == NULL))
  437.             return -ENOMEM;
  438.  
  439.         ret = i915_gem_object_pin(obj, CURSOR_WIDTH*CURSOR_HEIGHT*4, true);
  440.         if (ret) {
  441.             drm_gem_object_unreference(&obj->base);
  442.             return ret;
  443.         }
  444.  
  445. /* You don't need to worry about fragmentation issues.
  446.  * GTT space is continuous. I guarantee it.                           */
  447.  
  448.         bits = (u32*)MapIoMem(get_bus_addr() + obj->gtt_offset,
  449.                     CURSOR_WIDTH*CURSOR_HEIGHT*4, PG_SW);
  450.  
  451.         if (unlikely(bits == NULL))
  452.         {
  453.             i915_gem_object_unpin(obj);
  454.             drm_gem_object_unreference(&obj->base);
  455.             return -ENOMEM;
  456.         };
  457.         cursor->cobj = obj;
  458.     };
  459.  
  460.     src = cursor->data;
  461.  
  462.     for(i = 0; i < 32; i++)
  463.     {
  464.         for(j = 0; j < 32; j++)
  465.             *bits++ = *src++;
  466.         for(j = 32; j < CURSOR_WIDTH; j++)
  467.             *bits++ = 0;
  468.     }
  469.     for(i = 0; i < CURSOR_WIDTH*(CURSOR_HEIGHT-32); i++)
  470.         *bits++ = 0;
  471.  
  472. // release old cursor
  473.  
  474.     KernelFree(cursor->data);
  475.  
  476.     cursor->data = bits;
  477.  
  478.     cursor->header.destroy = destroy_cursor;
  479.     LEAVE();
  480.  
  481.     return 0;
  482. }
  483.  
  484.  
  485. static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
  486. {
  487.     struct drm_device *dev = crtc->dev;
  488.     struct drm_i915_private *dev_priv = dev->dev_private;
  489.     struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  490.     int pipe = intel_crtc->pipe;
  491.     bool visible = base != 0;
  492.  
  493.     if (intel_crtc->cursor_visible != visible) {
  494.         uint32_t cntl = I915_READ(CURCNTR(pipe));
  495.         if (base) {
  496.             cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
  497.             cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
  498.             cntl |= pipe << 28; /* Connect to correct pipe */
  499.         } else {
  500.             cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
  501.             cntl |= CURSOR_MODE_DISABLE;
  502.         }
  503.         I915_WRITE(CURCNTR(pipe), cntl);
  504.  
  505.         intel_crtc->cursor_visible = visible;
  506.     }
  507.     /* and commit changes on next vblank */
  508.     I915_WRITE(CURBASE(pipe), base);
  509. }
  510.  
  511. void __stdcall move_cursor_kms(cursor_t *cursor, int x, int y)
  512. {
  513.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  514.     struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  515.     u32 base, pos;
  516.     bool visible;
  517.  
  518.     int pipe = intel_crtc->pipe;
  519.  
  520.     intel_crtc->cursor_x = x;
  521.     intel_crtc->cursor_y = y;
  522.  
  523.     x = x - cursor->hot_x;
  524.     y = y - cursor->hot_y;
  525.  
  526.  
  527.     pos = 0;
  528.  
  529.     base = intel_crtc->cursor_addr;
  530.     if (x >= os_display->width)
  531.         base = 0;
  532.  
  533.     if (y >= os_display->height)
  534.         base = 0;
  535.  
  536.     if (x < 0)
  537.     {
  538.         if (x + intel_crtc->cursor_width < 0)
  539.             base = 0;
  540.  
  541.         pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
  542.         x = -x;
  543.     }
  544.     pos |= x << CURSOR_X_SHIFT;
  545.  
  546.     if (y < 0)
  547.     {
  548.         if (y + intel_crtc->cursor_height < 0)
  549.             base = 0;
  550.  
  551.         pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
  552.         y = -y;
  553.     }
  554.     pos |= y << CURSOR_Y_SHIFT;
  555.  
  556.     visible = base != 0;
  557.     if (!visible && !intel_crtc->cursor_visible)
  558.         return;
  559.  
  560.     I915_WRITE(CURPOS(pipe), pos);
  561. //    if (IS_845G(dev) || IS_I865G(dev))
  562. //        i845_update_cursor(crtc, base);
  563. //    else
  564.         i9xx_update_cursor(os_display->crtc, base);
  565.  
  566. };
  567.  
  568.  
  569. cursor_t* __stdcall select_cursor_kms(cursor_t *cursor)
  570. {
  571.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  572.     struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  573.     cursor_t *old;
  574.  
  575.     old = os_display->cursor;
  576.     os_display->cursor = cursor;
  577.  
  578.     if (!dev_priv->info->cursor_needs_physical)
  579.        intel_crtc->cursor_addr = cursor->cobj->gtt_offset;
  580.     else
  581.         intel_crtc->cursor_addr = (addr_t)cursor->cobj;
  582.  
  583.     intel_crtc->cursor_width = 32;
  584.     intel_crtc->cursor_height = 32;
  585.  
  586.     move_cursor_kms(cursor, intel_crtc->cursor_x, intel_crtc->cursor_y);
  587.     return old;
  588. };
  589.  
  590.  
  591. #define XY_SRC_COPY_BLT_CMD     ((2<<29)|(0x53<<22)|6)
  592.  
  593.  
  594. typedef struct
  595. {
  596.     int left;
  597.     int top;
  598.     int right;
  599.     int bottom;
  600. }rect_t;
  601.  
  602.  
  603. #include "clip.inc"
  604.  
  605. void  FASTCALL GetWindowRect(rect_t *rc)__asm__("GetWindowRect");
  606.  
  607. #define CURRENT_TASK             (0x80003000)
  608.  
  609. static u32_t get_display_map()
  610. {
  611.     u32_t   addr;
  612.  
  613.     addr = (u32_t)os_display;
  614.     addr+= sizeof(display_t);            /*  shoot me  */
  615.     return *(u32_t*)addr;
  616. }
  617.  
  618. #define XY_SRC_COPY_CHROMA_CMD     ((2<<29)|(0x73<<22)|8)
  619. #define ROP_COPY_SRC               0xCC
  620. #define FORMAT8888                 3
  621.  
  622. typedef int v4si __attribute__ ((vector_size (16)));
  623.  
  624.  
  625. int blit_video(u32 hbitmap, int  dst_x, int dst_y,
  626.                int src_x, int src_y, u32 w, u32 h)
  627. {
  628.     drm_i915_private_t *dev_priv = main_device->dev_private;
  629.     struct intel_ring_buffer *ring;
  630.  
  631.     bitmap_t  *bitmap;
  632.     rect_t     winrc;
  633.     clip_t     dst_clip;
  634.     clip_t     src_clip;
  635.     u32_t      width;
  636.     u32_t      height;
  637.  
  638.     u32_t      br13, cmd, slot_mask, *b;
  639.     u32_t      offset;
  640.     u8         slot;
  641.     int      n=0;
  642.  
  643.     if(unlikely(hbitmap==0))
  644.         return -1;
  645.  
  646.     bitmap = (bitmap_t*)hman_get_data(&bm_man, hbitmap);
  647.  
  648.     if(unlikely(bitmap==NULL))
  649.         return -1;
  650.  
  651.  
  652.     GetWindowRect(&winrc);
  653.  
  654.     dst_clip.xmin   = 0;
  655.     dst_clip.ymin   = 0;
  656.     dst_clip.xmax   = winrc.right-winrc.left-1;
  657.     dst_clip.ymax   = winrc.bottom -winrc.top -1;
  658.  
  659.     src_clip.xmin   = 0;
  660.     src_clip.ymin   = 0;
  661.     src_clip.xmax   = bitmap->width  - 1;
  662.     src_clip.ymax   = bitmap->height - 1;
  663.  
  664.     width  = w;
  665.     height = h;
  666.  
  667.     if( blit_clip(&dst_clip, &dst_x, &dst_y,
  668.                   &src_clip, &src_x, &src_y,
  669.                   &width, &height) )
  670.         return 0;
  671.  
  672.     dst_x+= winrc.left;
  673.     dst_y+= winrc.top;
  674.  
  675.     slot = *((u8*)CURRENT_TASK);
  676.  
  677.     slot_mask = (u32_t)slot<<24;
  678.  
  679.     {
  680. #if 0
  681.         static v4si write_mask = {0xFF000000, 0xFF000000,
  682.                                   0xFF000000, 0xFF000000};
  683.  
  684.         u8* src_offset;
  685.         u8* dst_offset;
  686.  
  687.         src_offset = (u8*)(src_y*bitmap->pitch + src_x*4);
  688.         src_offset += (u32)bitmap->uaddr;
  689.  
  690.         dst_offset = (u8*)(dst_y*os_display->width + dst_x);
  691.         dst_offset+= get_display_map();
  692.  
  693.         u32_t tmp_h = height;
  694.  
  695.         __asm__ __volatile__ (
  696.         "movdqa     %[write_mask],  %%xmm7    \n"
  697.         "movd       %[slot_mask],   %%xmm6    \n"
  698.         "punpckldq  %%xmm6, %%xmm6            \n"
  699.         "punpcklqdq %%xmm6, %%xmm6            \n"
  700.         :: [write_mask] "m" (write_mask),
  701.            [slot_mask]  "g" (slot_mask)
  702.         :"xmm7", "xmm6");
  703.  
  704.         while( tmp_h--)
  705.         {
  706.             u32_t tmp_w = width;
  707.  
  708.             u8* tmp_src = src_offset;
  709.             u8* tmp_dst = dst_offset;
  710.  
  711.             src_offset+= bitmap->pitch;
  712.             dst_offset+= os_display->width;
  713.  
  714.             while( tmp_w >= 8 )
  715.             {
  716.                 __asm__ __volatile__ (
  717.                 "movq       (%0),   %%xmm0            \n"
  718.                 "punpcklbw  %%xmm0, %%xmm0            \n"
  719.                 "movdqa     %%xmm0, %%xmm1            \n"
  720.                 "punpcklwd  %%xmm0, %%xmm0            \n"
  721.                 "punpckhwd  %%xmm1, %%xmm1            \n"
  722.                 "pcmpeqb    %%xmm6, %%xmm0            \n"
  723.                 "pcmpeqb    %%xmm6, %%xmm1            \n"
  724.                 "maskmovdqu %%xmm7, %%xmm0            \n"
  725.                 "addl       $16, %%edi                \n"
  726.                 "maskmovdqu %%xmm7, %%xmm1            \n"
  727.                 :: "r" (tmp_dst), "D" (tmp_src)
  728.                 :"xmm0", "xmm1");
  729.                 __asm__ __volatile__ ("":::"edi");
  730.                 tmp_w -= 8;
  731.                 tmp_src += 32;
  732.                 tmp_dst += 8;
  733.             };
  734.  
  735.             if( tmp_w >= 4 )
  736.             {
  737.                 __asm__ __volatile__ (
  738.                 "movd       (%0),   %%xmm0            \n"
  739.                 "punpcklbw  %%xmm0, %%xmm0            \n"
  740.                 "punpcklwd  %%xmm0, %%xmm0            \n"
  741.                 "pcmpeqb    %%xmm6, %%xmm0            \n"
  742.                 "maskmovdqu %%xmm7, %%xmm0            \n"
  743.                 :: "r" (tmp_dst), "D" (tmp_src)
  744.                 :"xmm0");
  745.                 tmp_w -= 4;
  746.                 tmp_src += 16;
  747.                 tmp_dst += 4;
  748.             };
  749.  
  750.             while( tmp_w--)
  751.             {
  752.                 *(tmp_src+3) = (*tmp_dst==slot)?0xFF:0x00;
  753.                 tmp_src+=4;
  754.                 tmp_dst++;
  755.             };
  756.         };
  757. #else
  758.         u8* src_offset;
  759.         u8* dst_offset;
  760.         u32 ifl;
  761.  
  762.         src_offset = (u8*)(src_y*bitmap->pitch + src_x*4);
  763.         src_offset += (u32)bitmap->uaddr;
  764.  
  765.         dst_offset = (u8*)(dst_y*os_display->width + dst_x);
  766.         dst_offset+= get_display_map();
  767.  
  768.         u32_t tmp_h = height;
  769.  
  770.       ifl = safe_cli();
  771.         while( tmp_h--)
  772.         {
  773.             u32_t tmp_w = width;
  774.  
  775.             u8* tmp_src = src_offset;
  776.             u8* tmp_dst = dst_offset;
  777.  
  778.             src_offset+= bitmap->pitch;
  779.             dst_offset+= os_display->width;
  780.  
  781.             while( tmp_w--)
  782.             {
  783.                 *(tmp_src+3) = (*tmp_dst==slot)?0xFF:0x00;
  784.                 tmp_src+=4;
  785.                 tmp_dst++;
  786.             };
  787.         };
  788.       safe_sti(ifl);
  789.     }
  790. #endif
  791.  
  792.     if((cmd_buffer & 0xFC0)==0xFC0)
  793.         cmd_buffer&= 0xFFFFF000;
  794.  
  795.     b = (u32_t*)ALIGN(cmd_buffer,16);
  796.  
  797.     offset = cmd_offset + ((u32_t)b & 0xFFF);
  798.  
  799.     cmd = XY_SRC_COPY_CHROMA_CMD | BLT_WRITE_RGB | BLT_WRITE_ALPHA;
  800.     cmd |= 3 << 17;
  801.  
  802.     br13 = os_display->pitch;
  803.     br13|= ROP_COPY_SRC << 16;
  804.     br13|= FORMAT8888   << 24;
  805.  
  806.     b[n++] = cmd;
  807.     b[n++] = br13;
  808.     b[n++] = (dst_y << 16) | dst_x;                   // left, top
  809.     b[n++] = ((dst_y+height-1)<< 16)|(dst_x+width-1); // bottom, right
  810.     b[n++] = 0;                          // destination
  811.     b[n++] = (src_y << 16) | src_x;      // source left & top
  812.     b[n++] = bitmap->pitch;              // source pitch
  813.     b[n++] = bitmap->gaddr;              // source
  814.  
  815.     b[n++] = 0;                          // Transparency Color Low
  816.     b[n++] = 0x00FFFFFF;                 // Transparency Color High
  817.  
  818.     b[n++] = MI_BATCH_BUFFER_END;
  819.     if( n & 1)
  820.         b[n++] = MI_NOOP;
  821.  
  822.     i915_gem_object_set_to_gtt_domain(bitmap->obj, false);
  823.  
  824.     if (HAS_BLT(main_device))
  825.     {
  826.         int ret;
  827.  
  828.         ring = &dev_priv->ring[BCS];
  829.         ring->dispatch_execbuffer(ring, cmd_offset, n*4);
  830.  
  831.         ret = intel_ring_begin(ring, 4);
  832.         if (ret)
  833.             return ret;
  834.  
  835.         intel_ring_emit(ring, MI_FLUSH_DW);
  836.         intel_ring_emit(ring, 0);
  837.         intel_ring_emit(ring, 0);
  838.         intel_ring_emit(ring, MI_NOOP);
  839.         intel_ring_advance(ring);
  840.     }
  841.     else
  842.     {
  843.         ring = &dev_priv->ring[RCS];
  844.         ring->dispatch_execbuffer(ring, cmd_offset, n*4);
  845.         ring->flush(ring, 0, I915_GEM_DOMAIN_RENDER);
  846.     };
  847.  
  848.     bitmap->obj->base.read_domains = I915_GEM_DOMAIN_CPU;
  849.     bitmap->obj->base.write_domain = I915_GEM_DOMAIN_CPU;
  850.  
  851.     return 0;
  852. fail:
  853.     return -1;
  854. };
  855.  
  856.  
  857. /* For display hotplug interrupt */
  858. static void
  859. ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
  860. {
  861.     if ((dev_priv->irq_mask & mask) != 0) {
  862.         dev_priv->irq_mask &= ~mask;
  863.         I915_WRITE(DEIMR, dev_priv->irq_mask);
  864.         POSTING_READ(DEIMR);
  865.     }
  866. }
  867.  
  868. static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
  869. {
  870.     drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
  871.     unsigned long irqflags;
  872.  
  873. //    if (!i915_pipe_enabled(dev, pipe))
  874. //        return -EINVAL;
  875.  
  876.     spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
  877.     ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
  878.                     DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
  879.     spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  880.  
  881.     return 0;
  882. }
  883.  
  884.  
  885.  
  886. static int i915_interrupt_info(struct drm_device *dev)
  887. {
  888.     drm_i915_private_t *dev_priv = dev->dev_private;
  889.     int ret, i, pipe;
  890.  
  891.     if (!HAS_PCH_SPLIT(dev)) {
  892.         dbgprintf("Interrupt enable:    %08x\n",
  893.                I915_READ(IER));
  894.         dbgprintf("Interrupt identity:  %08x\n",
  895.                I915_READ(IIR));
  896.         dbgprintf("Interrupt mask:      %08x\n",
  897.                I915_READ(IMR));
  898.         for_each_pipe(pipe)
  899.             dbgprintf("Pipe %c stat:         %08x\n",
  900.                    pipe_name(pipe),
  901.                    I915_READ(PIPESTAT(pipe)));
  902.     } else {
  903.         dbgprintf("North Display Interrupt enable:      %08x\n",
  904.            I915_READ(DEIER));
  905.         dbgprintf("North Display Interrupt identity:    %08x\n",
  906.            I915_READ(DEIIR));
  907.         dbgprintf("North Display Interrupt mask:        %08x\n",
  908.            I915_READ(DEIMR));
  909.         dbgprintf("South Display Interrupt enable:      %08x\n",
  910.            I915_READ(SDEIER));
  911.         dbgprintf("South Display Interrupt identity:    %08x\n",
  912.            I915_READ(SDEIIR));
  913.         dbgprintf("South Display Interrupt mask:        %08x\n",
  914.            I915_READ(SDEIMR));
  915.         dbgprintf("Graphics Interrupt enable:           %08x\n",
  916.            I915_READ(GTIER));
  917.         dbgprintf("Graphics Interrupt identity:         %08x\n",
  918.            I915_READ(GTIIR));
  919.         dbgprintf("Graphics Interrupt mask:             %08x\n",
  920.                I915_READ(GTIMR));
  921.     }
  922.     dbgprintf("Interrupts received: %d\n",
  923.            atomic_read(&dev_priv->irq_received));
  924.     for (i = 0; i < I915_NUM_RINGS; i++) {
  925.         if (IS_GEN6(dev) || IS_GEN7(dev)) {
  926.             printf("Graphics Interrupt mask (%s):       %08x\n",
  927.                    dev_priv->ring[i].name,
  928.                    I915_READ_IMR(&dev_priv->ring[i]));
  929.         }
  930. //        i915_ring_seqno_info(m, &dev_priv->ring[i]);
  931.     }
  932.  
  933.     return 0;
  934. }
  935.  
  936. void execute_buffer (struct drm_i915_gem_object *buffer, uint32_t offset,
  937.                      int size)
  938. {
  939.     struct intel_ring_buffer *ring;
  940.     drm_i915_private_t *dev_priv = main_device->dev_private;
  941.     u32 invalidate;
  942.     u32 seqno = 2;
  943.  
  944.     offset += buffer->gtt_offset;
  945. //    dbgprintf("execute %x size %d\n", offset, size);
  946.  
  947. //    asm volatile(
  948. //    "mfence \n"
  949. //    "wbinvd \n"
  950. //    "mfence  \n"
  951. //    :::"memory");
  952.  
  953.     ring = &dev_priv->ring[RCS];
  954.     ring->dispatch_execbuffer(ring, offset, size);
  955.  
  956.     invalidate = I915_GEM_DOMAIN_COMMAND;
  957.     if (INTEL_INFO(main_device)->gen >= 4)
  958.         invalidate |= I915_GEM_DOMAIN_SAMPLER;
  959.     if (ring->flush(ring, invalidate, 0))
  960.         i915_gem_next_request_seqno(ring);
  961.  
  962.     ring->irq_get(ring);
  963.  
  964.     ring->add_request(ring, &seqno);
  965.  
  966. //    i915_interrupt_info(main_device);
  967.  
  968. };
  969.  
  970.  
  971. int blit_textured(u32 hbitmap, int  dst_x, int dst_y,
  972.                int src_x, int src_y, u32 w, u32 h)
  973. {
  974.     drm_i915_private_t *dev_priv = main_device->dev_private;
  975.  
  976.     bitmap_t  *src_bitmap, *dst_bitmap;
  977.     bitmap_t   screen;
  978.  
  979.     rect_t     winrc;
  980.  
  981. //    dbgprintf("  handle: %d dx %d dy %d sx %d sy %d w %d h %d\n",
  982. //              hbitmap, dst_x, dst_y, src_x, src_y, w, h);
  983.  
  984.     if(unlikely(hbitmap==0))
  985.         return -1;
  986.  
  987.     src_bitmap = (bitmap_t*)hman_get_data(&bm_man, hbitmap);
  988. //    dbgprintf("bitmap %x\n", src_bitmap);
  989.  
  990.     if(unlikely(src_bitmap==NULL))
  991.         return -1;
  992.  
  993.     GetWindowRect(&winrc);
  994.  
  995.     screen.pitch  = os_display->pitch;
  996.     screen.gaddr  = 0;
  997.     screen.width  = os_display->width;
  998.     screen.height = os_display->height;
  999.     screen.obj    = (void*)-1;
  1000.  
  1001.     dst_bitmap = &screen;
  1002.  
  1003.     dst_x+= winrc.left;
  1004.     dst_y+= winrc.top;
  1005.  
  1006.     sna_blit_copy(dst_bitmap, dst_x, dst_y, w, h, src_bitmap, src_x, src_y);
  1007.  
  1008. };
  1009.  
  1010. int sna_blit_tex(bitmap_t *dst_bitmap, int dst_x, int dst_y,
  1011.                   int w, int h, bitmap_t *src_bitmap, int src_x, int src_y,
  1012.                   bitmap_t *mask_bitmap);
  1013.  
  1014. int create_context();
  1015. struct context *get_context();
  1016.  
  1017. int blit_tex(u32 hbitmap, int  dst_x, int dst_y,
  1018.              int src_x, int src_y, u32 w, u32 h)
  1019. {
  1020.     drm_i915_private_t *dev_priv = main_device->dev_private;
  1021.     struct context *ctx;
  1022.  
  1023.     bitmap_t  *src_bitmap, *dst_bitmap;
  1024.     bitmap_t   screen;
  1025.     int        ret;
  1026.  
  1027.     bitmap_t *mask_bitmap;
  1028.     rect_t     winrc;
  1029.  
  1030. //    dbgprintf("  handle: %d dx %d dy %d sx %d sy %d w %d h %d\n",
  1031. //              hbitmap, dst_x, dst_y, src_x, src_y, w, h);
  1032.  
  1033.     if(unlikely(hbitmap==0))
  1034.         return -1;
  1035.  
  1036.     src_bitmap = (bitmap_t*)hman_get_data(&bm_man, hbitmap);
  1037. //    dbgprintf("bitmap %x\n", src_bitmap);
  1038.  
  1039.     if(unlikely(src_bitmap==NULL))
  1040.         return -1;
  1041.  
  1042.     ctx = get_context();
  1043.     if(unlikely(ctx==NULL))
  1044.     {
  1045.         ret = create_context();
  1046.         if(ret!=0)
  1047.             return -1;
  1048.  
  1049.         ctx = get_context();
  1050.     };
  1051.  
  1052.     mask_bitmap = ctx->mask;
  1053.  
  1054.     GetWindowRect(&winrc);
  1055.     dst_x+= winrc.left;
  1056.     dst_y+= winrc.top;
  1057.  
  1058.  
  1059.     if(ctx->seqno != os_display->mask_seqno)
  1060.     {
  1061.         u8* src_offset;
  1062.         u8* dst_offset;
  1063.         u32 slot = *((u8*)CURRENT_TASK);
  1064.         u32 ifl;
  1065.  
  1066.         ret = gem_object_lock(mask_bitmap->obj);
  1067.         if(ret !=0 )
  1068.         {
  1069.             dbgprintf("%s fail\n", __FUNCTION__);
  1070.             return ret;
  1071.         };
  1072.  
  1073.         printf("width %d height %d\n", winrc.right, winrc.bottom);
  1074.  
  1075.         mask_bitmap->width  = winrc.right;
  1076.         mask_bitmap->height = winrc.bottom;
  1077.         mask_bitmap->pitch =  ALIGN(w,64);
  1078.  
  1079.         slot|= (slot<<8)|(slot<<16)|(slot<<24);
  1080.  
  1081.  
  1082.         __asm__ __volatile__ (
  1083.         "movd       %[slot],   %%xmm6    \n"
  1084.         "punpckldq  %%xmm6, %%xmm6            \n"
  1085.         "punpcklqdq %%xmm6, %%xmm6            \n"
  1086.         :: [slot]  "g" (slot)
  1087.         :"xmm6");
  1088.  
  1089.         src_offset = mask_bitmap->uaddr;
  1090.  
  1091.         dst_offset = (u8*)(dst_y*os_display->width + dst_x);
  1092.         dst_offset+= get_display_map();
  1093.  
  1094.         u32_t tmp_h = mask_bitmap->height;
  1095.  
  1096.       ifl = safe_cli();
  1097.         while( tmp_h--)
  1098.         {
  1099.             int tmp_w = mask_bitmap->width;
  1100.  
  1101.             u8* tmp_src = src_offset;
  1102.             u8* tmp_dst = dst_offset;
  1103.  
  1104.             src_offset+= mask_bitmap->pitch;
  1105.             dst_offset+= os_display->width;
  1106.  
  1107. //            while( tmp_w--)
  1108. //            {
  1109. //                *(tmp_src) = (*tmp_dst==slot)?0x1:0x00;
  1110. //                tmp_src++;
  1111. //                tmp_dst++;
  1112. //            };
  1113.             while(tmp_w >= 64)
  1114.             {
  1115.                 __asm__ __volatile__ (
  1116.                 "movdqu     (%0),   %%xmm0            \n"
  1117.                 "movdqu   16(%0),   %%xmm1            \n"
  1118.                 "movdqu   32(%0),   %%xmm2            \n"
  1119.                 "movdqu   48(%0),   %%xmm3            \n"
  1120.                 "pcmpeqb    %%xmm6, %%xmm0            \n"
  1121.                 "pcmpeqb    %%xmm6, %%xmm1            \n"
  1122.                 "pcmpeqb    %%xmm6, %%xmm2            \n"
  1123.                 "pcmpeqb    %%xmm6, %%xmm3            \n"
  1124.                 "movdqa     %%xmm0,   (%%edi)         \n"
  1125.                 "movdqa     %%xmm1, 16(%%edi)         \n"
  1126.                 "movdqa     %%xmm2, 32(%%edi)         \n"
  1127.                 "movdqa     %%xmm3, 48(%%edi)         \n"
  1128.  
  1129.                 :: "r" (tmp_dst), "D" (tmp_src)
  1130.                 :"xmm0","xmm1","xmm2","xmm3");
  1131.                 tmp_w -= 64;
  1132.                 tmp_src += 64;
  1133.                 tmp_dst += 64;
  1134.             }
  1135.  
  1136.             if( tmp_w >= 32 )
  1137.             {
  1138.                 __asm__ __volatile__ (
  1139.                 "movdqu     (%0),   %%xmm0            \n"
  1140.                 "movdqu   16(%0),   %%xmm1            \n"
  1141.                 "pcmpeqb    %%xmm6, %%xmm0            \n"
  1142.                 "pcmpeqb    %%xmm6, %%xmm1            \n"
  1143.                 "movdqa     %%xmm0,   (%%edi)         \n"
  1144.                 "movdqa     %%xmm1, 16(%%edi)         \n"
  1145.  
  1146.                 :: "r" (tmp_dst), "D" (tmp_src)
  1147.                 :"xmm0","xmm1");
  1148.                 tmp_w -= 32;
  1149.                 tmp_src += 32;
  1150.                 tmp_dst += 32;
  1151.             }
  1152.  
  1153.             while( tmp_w > 0 )
  1154.             {
  1155.                 __asm__ __volatile__ (
  1156.                 "movdqu     (%0),   %%xmm0            \n"
  1157.                 "pcmpeqb    %%xmm6, %%xmm0            \n"
  1158.                 "movdqa     %%xmm0,   (%%edi)         \n"
  1159.                 :: "r" (tmp_dst), "D" (tmp_src)
  1160.                 :"xmm0");
  1161.                 tmp_w -= 16;
  1162.                 tmp_src += 16;
  1163.                 tmp_dst += 16;
  1164.             }
  1165.         };
  1166.       safe_sti(ifl);
  1167.       ctx->seqno = os_display->mask_seqno;
  1168.     }
  1169.  
  1170.     screen.pitch  = os_display->pitch;
  1171.     screen.gaddr  = 0;
  1172.     screen.width  = os_display->width;
  1173.     screen.height = os_display->height;
  1174.     screen.obj    = (void*)-1;
  1175.  
  1176.     dst_bitmap = &screen;
  1177.  
  1178.  
  1179.     sna_blit_tex(dst_bitmap, dst_x, dst_y, w, h, src_bitmap, src_x, src_y,
  1180.                  mask_bitmap);
  1181.  
  1182. //    asm volatile ("int3");
  1183. };
  1184.  
  1185.  
  1186. struct context *context_map[256];
  1187.  
  1188. void __attribute__((regparm(1))) destroy_context(struct context *context)
  1189. {
  1190.     printf("destroy context %x\n", context);
  1191.  
  1192.     context_map[context->slot] = NULL;
  1193.     __DestroyObject(context);
  1194. };
  1195.  
  1196.  
  1197. int create_context()
  1198. {
  1199.     struct context *context;
  1200.  
  1201.     bitmap_t  *mask;
  1202.     int        slot;
  1203.  
  1204.     struct io_call_10 io_10;
  1205.     int    ret;
  1206.  
  1207.     slot = *((u8*)CURRENT_TASK);
  1208.  
  1209.     if(context_map[slot] != NULL)
  1210.         return 0;
  1211.  
  1212.     context = CreateObject(GetPid(), sizeof(*context));
  1213. //    printf("context %x\n", coontext);
  1214.     if( context == NULL)
  1215.         goto err1;
  1216.     context->header.destroy = destroy_context;
  1217.  
  1218.     dbgprintf("Create mask surface\n");
  1219.  
  1220.     io_10.width  = os_display->width/4;     /* need bitmap format here */
  1221.     io_10.height = os_display->height+1;
  1222.     io_10.max_width  = os_display->width/4;
  1223.     io_10.max_height = os_display->height+1;
  1224.  
  1225.     ret = create_surface(&io_10);
  1226.     if(ret)
  1227.         goto err2;
  1228.  
  1229.     mask= (bitmap_t*)hman_get_data(&bm_man, io_10.handle);
  1230.     if(unlikely(mask == NULL)) /* something really terrible happend */
  1231.         goto err2;
  1232.     dbgprintf("done\n");
  1233.  
  1234.     context->mask  = mask;
  1235.     context->seqno = os_display->mask_seqno-1;
  1236.     context->slot  = slot;
  1237.  
  1238.     context_map[slot] = context;
  1239.     return 0;
  1240.  
  1241. err2:
  1242.     __DestroyObject(context);
  1243. err1:
  1244.     return -1;
  1245. };
  1246.  
  1247. struct context *get_context()
  1248. {
  1249.  
  1250.     int slot = *((u8*)CURRENT_TASK);
  1251.  
  1252.     return context_map[slot];
  1253. }
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261.  
  1262.  
  1263.  
  1264. void __stdcall run_workqueue(struct workqueue_struct *cwq)
  1265. {
  1266.     unsigned long irqflags;
  1267.  
  1268. //    dbgprintf("wq: %x head %x, next %x\n",
  1269. //               cwq, &cwq->worklist, cwq->worklist.next);
  1270.  
  1271.     spin_lock_irqsave(&cwq->lock, irqflags);
  1272.  
  1273.     while (!list_empty(&cwq->worklist))
  1274.     {
  1275.         struct work_struct *work = list_entry(cwq->worklist.next,
  1276.                                         struct work_struct, entry);
  1277.         work_func_t f = work->func;
  1278.         list_del_init(cwq->worklist.next);
  1279. //        dbgprintf("head %x, next %x\n",
  1280. //                  &cwq->worklist, cwq->worklist.next);
  1281.  
  1282.         spin_unlock_irqrestore(&cwq->lock, irqflags);
  1283.         f(work);
  1284.         spin_lock_irqsave(&cwq->lock, irqflags);
  1285.     }
  1286.  
  1287.     spin_unlock_irqrestore(&cwq->lock, irqflags);
  1288. }
  1289.  
  1290.  
  1291. static inline
  1292. int __queue_work(struct workqueue_struct *wq,
  1293.                          struct work_struct *work)
  1294. {
  1295.     unsigned long flags;
  1296. //    ENTER();
  1297.  
  1298. //    dbgprintf("wq: %x, work: %x\n",
  1299. //               wq, work );
  1300.  
  1301.     if(!list_empty(&work->entry))
  1302.         return 0;
  1303.  
  1304.     spin_lock_irqsave(&wq->lock, flags);
  1305.  
  1306.     if(list_empty(&wq->worklist))
  1307.         TimerHs(0,0, run_workqueue, wq);
  1308.  
  1309.     list_add_tail(&work->entry, &wq->worklist);
  1310.  
  1311.     spin_unlock_irqrestore(&wq->lock, flags);
  1312. //    dbgprintf("wq: %x head %x, next %x\n",
  1313. //               wq, &wq->worklist, wq->worklist.next);
  1314.  
  1315. //    LEAVE();
  1316.     return 1;
  1317. };
  1318.  
  1319. void __stdcall delayed_work_timer_fn(unsigned long __data)
  1320. {
  1321. //    ENTER();
  1322.     struct delayed_work *dwork = (struct delayed_work *)__data;
  1323.     struct workqueue_struct *wq = dwork->work.data;
  1324.  
  1325. //    dbgprintf("wq: %x, work: %x\n",
  1326. //               wq, &dwork->work );
  1327.  
  1328.     __queue_work(wq, &dwork->work);
  1329. //    LEAVE();
  1330. }
  1331.  
  1332.  
  1333. int queue_delayed_work_on(struct workqueue_struct *wq,
  1334.                         struct delayed_work *dwork, unsigned long delay)
  1335. {
  1336.     struct work_struct *work = &dwork->work;
  1337.  
  1338.     work->data = wq;
  1339.     TimerHs(0,0, delayed_work_timer_fn, dwork);
  1340.     return 1;
  1341. }
  1342.  
  1343. int queue_delayed_work(struct workqueue_struct *wq,
  1344.                         struct delayed_work *dwork, unsigned long delay)
  1345. {
  1346.     u32  flags;
  1347. //    ENTER();
  1348.  
  1349. //    dbgprintf("wq: %x, work: %x\n",
  1350. //               wq, &dwork->work );
  1351.  
  1352.     if (delay == 0)
  1353.         return __queue_work(wq, &dwork->work);
  1354.  
  1355.     return queue_delayed_work_on(wq, dwork, delay);
  1356. }
  1357.  
  1358.  
  1359. struct workqueue_struct *alloc_workqueue(const char *fmt,
  1360.                            unsigned int flags,
  1361.                            int max_active)
  1362. {
  1363.     struct workqueue_struct *wq;
  1364.  
  1365.     wq = kzalloc(sizeof(*wq),0);
  1366.     if (!wq)
  1367.         goto err;
  1368.  
  1369.     INIT_LIST_HEAD(&wq->worklist);
  1370.  
  1371.     return wq;
  1372. err:
  1373.     return NULL;
  1374. }
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.