Subversion Repositories Kolibri OS

Rev

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

  1. #include <drm/drmP.h>
  2. #include <drm/i915_drm.h>
  3. #include "i915_drv.h"
  4.  
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/mod_devicetable.h>
  8. #include <errno-base.h>
  9. #include <linux/pci.h>
  10. #include <syscall.h>
  11.  
  12. #include "bitmap.h"
  13.  
  14. #define I915_DEV_CLOSE 0
  15. #define I915_DEV_INIT  1
  16. #define I915_DEV_READY 2
  17.  
  18.  
  19. struct pci_device {
  20.     uint16_t    domain;
  21.     uint8_t     bus;
  22.     uint8_t     dev;
  23.     uint8_t     func;
  24.     uint16_t    vendor_id;
  25.     uint16_t    device_id;
  26.     uint16_t    subvendor_id;
  27.     uint16_t    subdevice_id;
  28.     uint32_t    device_class;
  29.     uint8_t     revision;
  30. };
  31.  
  32. struct drm_device *main_device;
  33. struct drm_file   *drm_file_handlers[256];
  34. videomode_t usermode;
  35.  
  36. void cpu_detect();
  37.  
  38. int _stdcall display_handler(ioctl_t *io);
  39. int init_agp(void);
  40.  
  41. int srv_blit_bitmap(u32 hbitmap, int  dst_x, int dst_y,
  42.                int src_x, int src_y, u32 w, u32 h);
  43.  
  44. int blit_textured(u32 hbitmap, int  dst_x, int dst_y,
  45.                int src_x, int src_y, u32 w, u32 h);
  46.  
  47. int blit_tex(u32 hbitmap, int  dst_x, int dst_y,
  48.              int src_x, int src_y, u32 w, u32 h);
  49.  
  50. void get_pci_info(struct pci_device *dev);
  51. int i915_getparam(struct drm_device *dev, void *data,
  52.              struct drm_file *file_priv);
  53.  
  54. int i915_mask_update(struct drm_device *dev, void *data,
  55.             struct drm_file *file);
  56.  
  57. struct cmdtable cmdtable[]= {
  58. //    CMDENTRY("-pm=", i915_powersave),
  59. //    CMDENTRY("-rc6=", i915_enable_rc6),
  60. //    CMDENTRY("-fbc=", i915_enable_fbc),
  61. //    CMDENTRY("-ppgt=", i915_enable_ppgtt),
  62. //    CMDENTRY("-pc8=", i915_enable_pc8),
  63.     {NULL, 0}
  64. };
  65.  
  66.  
  67. static char  log[256];
  68.  
  69. unsigned long volatile jiffies;
  70.  
  71. struct workqueue_struct *system_wq;
  72. int driver_wq_state;
  73.  
  74. int x86_clflush_size;
  75. unsigned int tsc_khz;
  76.  
  77. int i915_modeset = 1;
  78.  
  79. typedef union __attribute__((packed))
  80. {
  81.     uint32_t val;
  82.     struct
  83.     {
  84.         uint8_t   state;
  85.         uint8_t   code;
  86.         uint16_t  ctrl_key;
  87.     };
  88. }oskey_t;
  89.  
  90. static inline oskey_t get_key(void)
  91. {
  92.     oskey_t val;
  93.     asm volatile("int $0x40":"=a"(val):"a"(2));
  94.     return val;
  95. };
  96.  
  97. void i915_dpms(struct drm_device *dev, int mode);
  98.  
  99. void i915_driver_thread()
  100. {
  101.     struct drm_i915_private *dev_priv = NULL;
  102.     struct workqueue_struct *cwq = NULL;
  103.     static int dpms = 1;
  104.     static int dpms_lock = 0;
  105.     oskey_t   key;
  106.     unsigned long irqflags;
  107.     int tmp;
  108.  
  109.     printf("%s\n",__FUNCTION__);
  110.  
  111.     while(driver_wq_state == I915_DEV_INIT)
  112.     {
  113.         jiffies = GetTimerTicks();
  114.         delay(1);
  115.     };
  116.  
  117.     dev_priv = main_device->dev_private;
  118.     cwq = dev_priv->wq;
  119.  
  120.     asm volatile("int $0x40":"=a"(tmp):"a"(66),"b"(1),"c"(1));
  121.     asm volatile("int $0x40":"=a"(tmp):"a"(66),"b"(4),"c"(0x46),"d"(0x330));
  122.     asm volatile("int $0x40":"=a"(tmp):"a"(66),"b"(4),"c"(0xC6),"d"(0x330));
  123.  
  124.     while(driver_wq_state != I915_DEV_CLOSE)
  125.     {
  126.         jiffies = GetTimerTicks();
  127.  
  128.         key = get_key();
  129.  
  130.         if( (key.val != 1) && (key.state == 0x02))
  131.         {
  132.             if(key.code == 0x46 && dpms_lock == 0)
  133.             {
  134.                 dpms_lock = 1;
  135.                 if(dpms == 1)
  136.                 {
  137.                     i915_dpms(main_device, DRM_MODE_DPMS_OFF);
  138.                     printf("dpms off\n");
  139.                 }
  140.                 else
  141.                 {
  142.                     i915_dpms(main_device, DRM_MODE_DPMS_ON);
  143.                     printf("dpms on\n");
  144.                 };
  145.                 dpms ^= 1;
  146.                 }
  147.             else if(key.code == 0xC6)
  148.                 dpms_lock = 0;
  149.         };
  150.  
  151.         spin_lock_irqsave(&cwq->lock, irqflags);
  152.  
  153.         while (!list_empty(&cwq->worklist))
  154.         {
  155.             struct work_struct *work = list_entry(cwq->worklist.next,
  156.                                         struct work_struct, entry);
  157.             work_func_t f = work->func;
  158.             list_del_init(cwq->worklist.next);
  159.  
  160.             spin_unlock_irqrestore(&cwq->lock, irqflags);
  161.             f(work);
  162.             spin_lock_irqsave(&cwq->lock, irqflags);
  163.         }
  164.  
  165.         spin_unlock_irqrestore(&cwq->lock, irqflags);
  166.  
  167.         delay(1);
  168.     };
  169.  
  170.     asm volatile ("int $0x40"::"a"(-1));
  171. }
  172.  
  173. u32_t  __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
  174. {
  175.     static pci_dev_t device;
  176.     const struct pci_device_id  *ent;
  177.  
  178.     int err = 0;
  179.  
  180.     if(action != 1)
  181.     {
  182.         driver_wq_state = I915_DEV_CLOSE;
  183.         return 0;
  184.     };
  185.  
  186.     if( GetService("DISPLAY") != 0 )
  187.         return 0;
  188.  
  189.     printf("\ni915 v3.17-rc3 build %s %s\nusage: i915 [options]\n"
  190.            "-pm=<0,1>     Enable powersavings, fbc, downclocking, etc. (default: 1 - true)\n",
  191.            __DATE__, __TIME__);
  192.     printf("-rc6=<-1,0-7> Enable power-saving render C-state 6.\n"
  193.            "              Different stages can be selected via bitmask values\n"
  194.            "              (0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6).\n"
  195.            "              For example, 3 would enable rc6 and deep rc6, and 7 would enable everything.\n"
  196.            "              default: -1 (use per-chip default)\n");
  197.     printf("-fbc=<-1,0,1> Enable frame buffer compression for power savings\n"
  198.            "              (default: -1 (use per-chip default))\n");
  199.     printf("-ppgt=<0,1>   Enable PPGTT (default: true)\n");
  200.     printf("-pc8=<0,1>    Enable support for low power package C states (PC8+) (default: 0 - false)\n");
  201.     printf("-l<path>      path to log file\n");
  202.     printf("-m<WxHxHz>    set videomode\n");
  203.  
  204.     if( cmdline && *cmdline )
  205.         parse_cmdline(cmdline, cmdtable, log, &usermode);
  206.  
  207.     if( *log && !dbg_open(log))
  208.         {
  209.             printf("Can't open %s\nExit\n", log);
  210.             return 0;
  211.     }
  212.  
  213.     cpu_detect();
  214. //    dbgprintf("\ncache line size %d\n", x86_clflush_size);
  215.  
  216.     err = enum_pci_devices();
  217.     if( unlikely(err != 0) )
  218.     {
  219.         dbgprintf("Device enumeration failed\n");
  220.         return 0;
  221.     }
  222.  
  223.     dmi_scan_machine();
  224.  
  225.     driver_wq_state = I915_DEV_INIT;
  226.     CreateKernelThread(i915_driver_thread);
  227.  
  228.     err = i915_init();
  229.     if(unlikely(err!= 0))
  230.     {
  231.         driver_wq_state = I915_DEV_CLOSE;
  232.         dbgprintf("Epic Fail :(\n");
  233.         return 0;
  234.     };
  235.  
  236.     driver_wq_state = I915_DEV_READY;
  237.  
  238.     init_display_kms(main_device, &usermode);
  239.  
  240.     err = RegService("DISPLAY", display_handler);
  241.  
  242.     if( err != 0)
  243.         dbgprintf("Set DISPLAY handler\n");
  244.  
  245.  
  246.     return err;
  247. };
  248.  
  249.  
  250. #define CURRENT_API     0x0200      /*      2.00     */
  251. #define COMPATIBLE_API  0x0100      /*      1.00     */
  252.  
  253. #define API_VERSION     (COMPATIBLE_API << 16) | CURRENT_API
  254. #define DISPLAY_VERSION  API_VERSION
  255.  
  256.  
  257. #define SRV_GETVERSION          0
  258. #define SRV_ENUM_MODES          1
  259. #define SRV_SET_MODE            2
  260. #define SRV_GET_CAPS            3
  261.  
  262. #define SRV_CREATE_SURFACE      10
  263. #define SRV_DESTROY_SURFACE     11
  264. #define SRV_LOCK_SURFACE        12
  265. #define SRV_UNLOCK_SURFACE      13
  266. #define SRV_RESIZE_SURFACE      14
  267. #define SRV_BLIT_BITMAP         15
  268. #define SRV_BLIT_TEXTURE        16
  269. #define SRV_BLIT_VIDEO          17
  270.  
  271.  
  272. #define SRV_GET_PCI_INFO            20
  273. #define SRV_I915_GET_PARAM              21
  274. #define SRV_I915_GEM_CREATE         22
  275. #define SRV_DRM_GEM_CLOSE           23
  276. #define SRV_DRM_GEM_FLINK               24
  277. #define SRV_DRM_GEM_OPEN                25
  278. #define SRV_I915_GEM_PIN                26
  279. #define SRV_I915_GEM_UNPIN              27
  280. #define SRV_I915_GEM_SET_CACHING        28
  281. #define SRV_I915_GEM_PWRITE             29
  282. #define SRV_I915_GEM_BUSY               30
  283. #define SRV_I915_GEM_SET_DOMAIN         31
  284. #define SRV_I915_GEM_MMAP               32
  285. #define SRV_I915_GEM_SET_TILING         33
  286. #define SRV_I915_GEM_GET_TILING         34
  287. #define SRV_I915_GEM_GET_APERTURE       35
  288. #define SRV_I915_GEM_MMAP_GTT           36
  289. #define SRV_I915_GEM_THROTTLE           37
  290. #define SRV_I915_GEM_EXECBUFFER2        38
  291. #define SRV_I915_GEM_WAIT               39
  292. #define SRV_I915_GEM_CONTEXT_CREATE     40
  293. #define SRV_I915_GEM_CONTEXT_DESTROY    41
  294. #define SRV_I915_REG_READ               42
  295.  
  296. #define SRV_FBINFO                      43
  297. #define SRV_MASK_UPDATE                 44
  298. #define SRV_MASK_UPDATE_EX              45
  299.  
  300. #define check_input(size) \
  301.     if( unlikely((inp==NULL)||(io->inp_size != (size))) )   \
  302.         break;
  303.  
  304. #define check_output(size) \
  305.     if( unlikely((outp==NULL)||(io->out_size != (size))) )   \
  306.         break;
  307.  
  308. int _stdcall display_handler(ioctl_t *io)
  309. {
  310.     struct drm_file *file;
  311.  
  312.     int    retval = -1;
  313.     u32_t *inp;
  314.     u32_t *outp;
  315.  
  316.     inp = io->input;
  317.     outp = io->output;
  318.  
  319.     file = drm_file_handlers[0];
  320.  
  321.     switch(io->io_code)
  322.     {
  323.         case SRV_GETVERSION:
  324.             check_output(4);
  325.             *outp  = DISPLAY_VERSION;
  326.             retval = 0;
  327.             break;
  328.  
  329.         case SRV_ENUM_MODES:
  330. //            dbgprintf("SRV_ENUM_MODES inp %x inp_size %x out_size %x\n",
  331. //                       inp, io->inp_size, io->out_size );
  332.             check_output(4);
  333. //            check_input(*outp * sizeof(videomode_t));
  334.             if( i915_modeset)
  335.                 retval = get_videomodes((videomode_t*)inp, outp);
  336.             break;
  337.  
  338.         case SRV_SET_MODE:
  339. //            dbgprintf("SRV_SET_MODE inp %x inp_size %x\n",
  340. //                       inp, io->inp_size);
  341.             check_input(sizeof(videomode_t));
  342.             if( i915_modeset )
  343.                 retval = set_user_mode((videomode_t*)inp);
  344.             break;
  345.  
  346.         case SRV_GET_CAPS:
  347.             retval = get_driver_caps((hwcaps_t*)inp);
  348.             break;
  349.  
  350.         case SRV_GET_PCI_INFO:
  351.             get_pci_info((struct pci_device *)inp);
  352.             retval = 0;
  353.             break;
  354.  
  355.         case SRV_I915_GET_PARAM:
  356.             retval = i915_getparam(main_device, inp, file);
  357.             break;
  358.  
  359.         case SRV_I915_GEM_CREATE:
  360.             retval = i915_gem_create_ioctl(main_device, inp, file);
  361.             break;
  362.  
  363.         case SRV_DRM_GEM_CLOSE:
  364.             retval = drm_gem_close_ioctl(main_device, inp, file);
  365.             break;
  366.  
  367.         case SRV_DRM_GEM_FLINK:
  368.             retval = drm_gem_flink_ioctl(main_device, inp, file);
  369.             break;
  370.  
  371.         case SRV_DRM_GEM_OPEN:
  372.             retval = drm_gem_open_ioctl(main_device, inp, file);
  373.             break;
  374.  
  375.         case SRV_I915_GEM_PIN:
  376.             retval = i915_gem_pin_ioctl(main_device, inp, file);
  377.             break;
  378.  
  379.         case SRV_I915_GEM_UNPIN:
  380.             retval = i915_gem_unpin_ioctl(main_device, inp, file);
  381.             break;
  382.  
  383.         case SRV_I915_GEM_SET_CACHING:
  384.             retval = i915_gem_set_caching_ioctl(main_device, inp, file);
  385.             break;
  386.  
  387.         case SRV_I915_GEM_PWRITE:
  388.             retval = i915_gem_pwrite_ioctl(main_device, inp, file);
  389.             break;
  390.  
  391.         case SRV_I915_GEM_BUSY:
  392.             retval = i915_gem_busy_ioctl(main_device, inp, file);
  393.             break;
  394.  
  395.         case SRV_I915_GEM_SET_DOMAIN:
  396.             retval = i915_gem_set_domain_ioctl(main_device, inp, file);
  397.             break;
  398.  
  399.         case SRV_I915_GEM_MMAP:
  400.             retval = i915_gem_mmap_ioctl(main_device, inp, file);
  401.             break;
  402.  
  403.         case SRV_I915_GEM_SET_TILING:
  404.             retval = i915_gem_set_tiling(main_device, inp, file);
  405.             break;
  406.  
  407.         case SRV_I915_GEM_GET_TILING:
  408.             retval = i915_gem_get_tiling(main_device, inp, file);
  409.             break;
  410.  
  411.         case SRV_I915_GEM_GET_APERTURE:
  412. //            printf("SRV_I915_GEM_GET_APERTURE ");
  413.             retval = i915_gem_get_aperture_ioctl(main_device, inp, file);
  414. //            printf(" retval=%d\n", retval);
  415.             break;
  416.  
  417.         case SRV_I915_GEM_MMAP_GTT:
  418.             retval = i915_gem_mmap_gtt_ioctl(main_device, inp, file);
  419.             break;
  420.  
  421.         case SRV_I915_GEM_THROTTLE:
  422.             retval = i915_gem_throttle_ioctl(main_device, inp, file);
  423.             break;
  424.  
  425.         case SRV_I915_GEM_EXECBUFFER2:
  426. //            printf("SRV_I915_GEM_EXECBUFFER2\n");
  427.             retval = i915_gem_execbuffer2(main_device, inp, file);
  428.             break;
  429.  
  430.         case SRV_I915_GEM_WAIT:
  431.             retval = i915_gem_wait_ioctl(main_device, inp, file);
  432.             break;
  433.  
  434.         case SRV_I915_GEM_CONTEXT_CREATE:
  435.             retval = i915_gem_context_create_ioctl(main_device, inp, file);
  436.             break;
  437.  
  438.         case SRV_I915_GEM_CONTEXT_DESTROY:
  439.             retval = i915_gem_context_destroy_ioctl(main_device, inp, file);
  440.             break;
  441.  
  442.         case SRV_I915_REG_READ:
  443.             retval = i915_reg_read_ioctl(main_device, inp, file);
  444.             break;
  445.  
  446.         case SRV_FBINFO:
  447.             retval = i915_fbinfo(inp);
  448.             break;
  449.  
  450.         case SRV_MASK_UPDATE:
  451.             retval = i915_mask_update(main_device, inp, file);
  452.             break;
  453.  
  454.         case SRV_MASK_UPDATE_EX:
  455.             retval = i915_mask_update_ex(main_device, inp, file);
  456.             break;
  457.     };
  458.  
  459.     return retval;
  460. }
  461.  
  462.  
  463. #define PCI_CLASS_REVISION      0x08
  464. #define PCI_CLASS_DISPLAY_VGA   0x0300
  465. #define PCI_CLASS_BRIDGE_HOST   0x0600
  466. #define PCI_CLASS_BRIDGE_ISA    0x0601
  467.  
  468. int pci_scan_filter(u32_t id, u32_t busnr, u32_t devfn)
  469. {
  470.     u16_t vendor, device;
  471.     u32_t class;
  472.     int   ret = 0;
  473.  
  474.     vendor   = id & 0xffff;
  475.     device   = (id >> 16) & 0xffff;
  476.  
  477.     if(vendor == 0x8086)
  478.     {
  479.         class = PciRead32(busnr, devfn, PCI_CLASS_REVISION);
  480.         class >>= 16;
  481.  
  482.         if( (class == PCI_CLASS_DISPLAY_VGA) ||
  483.             (class == PCI_CLASS_BRIDGE_HOST) ||
  484.             (class == PCI_CLASS_BRIDGE_ISA))
  485.             ret = 1;
  486.     }
  487.     return ret;
  488. };
  489.  
  490.  
  491.  
  492.  
  493. static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
  494.                 unsigned int *ecx, unsigned int *edx)
  495. {
  496.     /* ecx is often an input as well as an output. */
  497.     asm volatile("cpuid"
  498.         : "=a" (*eax),
  499.           "=b" (*ebx),
  500.           "=c" (*ecx),
  501.           "=d" (*edx)
  502.         : "0" (*eax), "2" (*ecx)
  503.         : "memory");
  504. }
  505.  
  506.  
  507.  
  508. static inline void cpuid(unsigned int op,
  509.                          unsigned int *eax, unsigned int *ebx,
  510.                          unsigned int *ecx, unsigned int *edx)
  511. {
  512.         *eax = op;
  513.         *ecx = 0;
  514.         __cpuid(eax, ebx, ecx, edx);
  515. }
  516.  
  517. struct mtrr
  518. {
  519.     u64_t  base;
  520.     u64_t  mask;
  521. };
  522.  
  523. struct cpuinfo
  524. {
  525.     u64_t  caps;
  526.     u64_t  def_mtrr;
  527.     u64_t  mtrr_cap;
  528.     int    var_mtrr_count;
  529.     int    fix_mtrr_count;
  530.     struct mtrr var_mtrr[9];
  531.     char   model_name[64];
  532. };
  533.  
  534. #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
  535. #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
  536.  
  537. #define MSR_MTRRdefType                 0x000002ff
  538.  
  539. #define IA32_MTRRCAP            0xFE
  540. #define IA32_CR_PAT_MSR         0x277
  541.  
  542. #define PAT_TYPE_UC             0
  543. #define PAT_TYPE_WC             1
  544. #define PAT_TYPE_WB             6
  545. #define PAT_TYPE_UCM            7
  546.  
  547.  
  548. #define MTRR_UC                 0
  549. #define MTRR_WC                 1
  550. #define MTRR_WB                 6
  551.  
  552. static inline u64_t read_msr(u32_t msr)
  553. {
  554.     union {
  555.         u64_t  val;
  556.         struct {
  557.             u32_t low;
  558.             u32_t high;
  559.         };
  560.     }tmp;
  561.  
  562.     asm volatile (
  563.     "rdmsr"
  564.     : "=a" (tmp.low), "=d" (tmp.high)
  565.     : "c" (msr));
  566.     return tmp.val;
  567. }
  568.  
  569. static inline void write_msr(u32_t msr, u64_t val)
  570. {
  571.     union {
  572.         u64_t  val;
  573.         struct {
  574.             u32_t low;
  575.             u32_t high;
  576.         };
  577.     }tmp;
  578.  
  579.     tmp.val = val;
  580.  
  581.     asm volatile (
  582.     "wrmsr"
  583.     :: "a" (tmp.low), "d" (tmp.high), "c" (msr));
  584. }
  585.  
  586. #define rdmsr(msr, low, high)                                   \
  587. do {                                                            \
  588.        u64 __val = read_msr((msr));                     \
  589.        (void)((low) = (u32)__val);                             \
  590.        (void)((high) = (u32)(__val >> 32));                    \
  591. } while (0)
  592.  
  593. static inline void native_write_msr(unsigned int msr,
  594.                                     unsigned low, unsigned high)
  595. {
  596.     asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory");
  597. }
  598.  
  599. static inline void wbinvd(void)
  600. {
  601.     asm volatile("wbinvd": : :"memory");
  602. }
  603.  
  604. #define SIZE_OR_MASK_BITS(n)  (~((1ULL << ((n) - PAGE_SHIFT)) - 1))
  605.  
  606. static void set_mtrr(unsigned int reg, unsigned long base,
  607.                  unsigned long size, int type)
  608. {
  609.     unsigned int base_lo, base_hi, mask_lo, mask_hi;
  610.     u64 size_or_mask, size_and_mask;
  611.  
  612.     size_or_mask = SIZE_OR_MASK_BITS(36);
  613.     size_and_mask = 0x00f00000;
  614.  
  615.     if (size == 0) {
  616.         /*
  617.          * The invalid bit is kept in the mask, so we simply
  618.          * clear the relevant mask register to disable a range.
  619.          */
  620.         native_write_msr(MTRRphysMask_MSR(reg), 0, 0);
  621.     }
  622.     else {
  623.         base_lo = base << PAGE_SHIFT | type;
  624.         base_hi = (base & size_and_mask) >> (32 - PAGE_SHIFT);
  625.         mask_lo = -size << PAGE_SHIFT | 0x800;
  626.         mask_hi = (-size & size_and_mask) >> (32 - PAGE_SHIFT);
  627.  
  628.         native_write_msr(MTRRphysBase_MSR(reg), base_lo, base_hi);
  629.         native_write_msr(MTRRphysMask_MSR(reg), mask_lo, mask_hi);
  630.     };
  631. }
  632.  
  633. static unsigned long __force_order;
  634.  
  635. static inline unsigned long read_cr0(void)
  636. {
  637.     unsigned long val;
  638.     asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
  639.     return val;
  640. }
  641.  
  642. static inline void write_cr0(unsigned long val)
  643. {
  644.     asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
  645. }
  646.  
  647. static inline unsigned long read_cr4(void)
  648. {
  649.     unsigned long val;
  650.     asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
  651.     return val;
  652. }
  653.  
  654. static inline void write_cr4(unsigned long val)
  655. {
  656.     asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
  657. }
  658.  
  659. static inline unsigned long read_cr3(void)
  660. {
  661.     unsigned long val;
  662.     asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
  663.     return val;
  664. }
  665.  
  666. static inline void write_cr3(unsigned long val)
  667. {
  668.     asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
  669. }
  670.  
  671. static u32 deftype_lo, deftype_hi;
  672.  
  673. void cpu_detect()
  674. {
  675.     struct cpuinfo cpuinfo;
  676.  
  677.     u32 junk, tfms, cap0, misc;
  678.     int i;
  679. #if 0
  680.     cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
  681.  
  682.     if (cap0 & (1<<19))
  683.     {
  684.         x86_clflush_size = ((misc >> 8) & 0xff) * 8;
  685.     }
  686.  
  687.     cpuid(0x80000002, (unsigned int*)&cpuinfo.model_name[0], (unsigned int*)&cpuinfo.model_name[4],
  688.           (unsigned int*)&cpuinfo.model_name[8], (unsigned int*)&cpuinfo.model_name[12]);
  689.     cpuid(0x80000003, (unsigned int*)&cpuinfo.model_name[16], (unsigned int*)&cpuinfo.model_name[20],
  690.           (unsigned int*)&cpuinfo.model_name[24], (unsigned int*)&cpuinfo.model_name[28]);
  691.     cpuid(0x80000004, (unsigned int*)&cpuinfo.model_name[32], (unsigned int*)&cpuinfo.model_name[36],
  692.           (unsigned int*)&cpuinfo.model_name[40], (unsigned int*)&cpuinfo.model_name[44]);
  693.  
  694.     printf("\n%s\n\n",cpuinfo.model_name);
  695.  
  696.     cpuinfo.def_mtrr = read_msr(MSR_MTRRdefType);
  697.     cpuinfo.mtrr_cap = read_msr(IA32_MTRRCAP);
  698.  
  699.     printf("MSR_MTRRdefType %016llx\n\n", cpuinfo.def_mtrr);
  700.  
  701.     cpuinfo.var_mtrr_count = (u8_t)cpuinfo.mtrr_cap;
  702.  
  703.     for(i = 0; i < cpuinfo.var_mtrr_count; i++)
  704.     {
  705.         u64_t mtrr_base;
  706.         u64_t mtrr_mask;
  707.  
  708.         cpuinfo.var_mtrr[i].base = read_msr(MTRRphysBase_MSR(i));
  709.         cpuinfo.var_mtrr[i].mask = read_msr(MTRRphysMask_MSR(i));
  710.  
  711.         printf("MTRR_%d base: %016llx mask: %016llx\n", i,
  712.                cpuinfo.var_mtrr[i].base,
  713.                cpuinfo.var_mtrr[i].mask);
  714.     };
  715.  
  716.     unsigned int cr0, cr3, cr4, eflags;
  717.  
  718.     eflags = safe_cli();
  719.  
  720.     /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
  721.     cr0 = read_cr0() | (1<<30);
  722.     write_cr0(cr0);
  723.     wbinvd();
  724.  
  725.     cr4 = read_cr4();
  726.     write_cr4(cr4 & ~(1<<7));
  727.  
  728.     cr3 = read_cr3();
  729.     write_cr3(cr3);
  730.  
  731.     /* Save MTRR state */
  732.     rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
  733.  
  734.     /* Disable MTRRs, and set the default type to uncached */
  735.     native_write_msr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
  736.     wbinvd();
  737.  
  738.     i = 0;
  739.     set_mtrr(i++,0,0x80000000>>12,MTRR_WB);
  740.     set_mtrr(i++,0x80000000>>12,0x40000000>>12,MTRR_WB);
  741.     set_mtrr(i++,0xC0000000>>12,0x20000000>>12,MTRR_WB);
  742.     set_mtrr(i++,0xdb800000>>12,0x00800000>>12,MTRR_UC);
  743.     set_mtrr(i++,0xdc000000>>12,0x04000000>>12,MTRR_UC);
  744.     set_mtrr(i++,0xE0000000>>12,0x10000000>>12,MTRR_WC);
  745.  
  746.     for(; i < cpuinfo.var_mtrr_count; i++)
  747.         set_mtrr(i,0,0,0);
  748.  
  749.     write_cr3(cr3);
  750.  
  751.     /* Intel (P6) standard MTRRs */
  752.     native_write_msr(MSR_MTRRdefType, deftype_lo, deftype_hi);
  753.  
  754.     /* Enable caches */
  755.     write_cr0(read_cr0() & ~(1<<30));
  756.  
  757.     /* Restore value of CR4 */
  758.     write_cr4(cr4);
  759.  
  760.     safe_sti(eflags);
  761.  
  762.     printf("\nnew MTRR map\n\n");
  763.  
  764.     for(i = 0; i < cpuinfo.var_mtrr_count; i++)
  765.     {
  766.         u64_t mtrr_base;
  767.         u64_t mtrr_mask;
  768.  
  769.         cpuinfo.var_mtrr[i].base = read_msr(MTRRphysBase_MSR(i));
  770.         cpuinfo.var_mtrr[i].mask = read_msr(MTRRphysMask_MSR(i));
  771.  
  772.         printf("MTRR_%d base: %016llx mask: %016llx\n", i,
  773.                cpuinfo.var_mtrr[i].base,
  774.                cpuinfo.var_mtrr[i].mask);
  775.     };
  776. #endif
  777.  
  778.     tsc_khz = (unsigned int)(GetCpuFreq()/1000);
  779. }
  780.  
  781.  
  782. int get_driver_caps(hwcaps_t *caps)
  783. {
  784.     int ret = 0;
  785.  
  786.     switch(caps->idx)
  787.     {
  788.         case 0:
  789.             caps->opt[0] = 0;
  790.             caps->opt[1] = 0;
  791.             break;
  792.  
  793.         case 1:
  794.             caps->cap1.max_tex_width  = 4096;
  795.             caps->cap1.max_tex_height = 4096;
  796.             break;
  797.         default:
  798.             ret = 1;
  799.     };
  800.     caps->idx = 1;
  801.     return ret;
  802. }
  803.  
  804.  
  805. void get_pci_info(struct pci_device *dev)
  806. {
  807.     struct pci_dev *pdev = main_device->pdev;
  808.  
  809.     memset(dev, sizeof(*dev), 0);
  810.  
  811.     dev->domain     = 0;
  812.     dev->bus        = pdev->busnr;
  813.     dev->dev        = pdev->devfn >> 3;
  814.     dev->func       = pdev->devfn & 7;
  815.     dev->vendor_id  = pdev->vendor;
  816.     dev->device_id  = pdev->device;
  817.     dev->revision   = pdev->revision;
  818. };
  819.  
  820.  
  821.  
  822. char *strstr(const char *cs, const char *ct);
  823.  
  824. static int my_atoi(char **cmd)
  825. {
  826.     char* p = *cmd;
  827.     int val = 0;
  828.     int sign = 1;
  829.  
  830.     if(*p == '-')
  831.     {
  832.         sign = -1;
  833.         p++;
  834.     };
  835.  
  836.     for (;; *p++) {
  837.         switch (*p) {
  838.         case '0' ... '9':
  839.             val = 10*val+(*p-'0');
  840.             break;
  841.         default:
  842.             *cmd = p;
  843.             return val*sign;
  844.         }
  845.     }
  846. }
  847.  
  848. char* parse_mode(char *p, videomode_t *mode)
  849. {
  850.     char c;
  851.  
  852.     while( (c = *p++) == ' ');
  853.  
  854.     if( c )
  855.     {
  856.         p--;
  857.  
  858.         mode->width = my_atoi(&p);
  859.         if(*p == 'x') p++;
  860.  
  861.         mode->height = my_atoi(&p);
  862.         if(*p == 'x') p++;
  863.  
  864.         mode->bpp = 32;
  865.  
  866.         mode->freq = my_atoi(&p);
  867.  
  868.         if( mode->freq == 0 )
  869.             mode->freq = 60;
  870.     }
  871.  
  872.     return p;
  873. };
  874.  
  875.  
  876. static char* parse_path(char *p, char *log)
  877. {
  878.     char  c;
  879.  
  880.     while( (c = *p++) == ' ');
  881.         p--;
  882.     while((c = *p++) && (c != ' '))
  883.         *log++ = c;
  884.  
  885.     *log = 0;
  886.  
  887.     return p;
  888. };
  889.  
  890. void parse_cmdline(char *cmdline, struct cmdtable *table, char *log, videomode_t *mode)
  891. {
  892.     char *p = cmdline;
  893.     char *p1;
  894.     int val;
  895.     char c = *p++;
  896.  
  897.     if( table )
  898.     {
  899.         while(table->key)
  900.         {
  901.             if(p1 = strstr(cmdline, table->key))
  902.             {
  903.                 p1+= table->size;
  904.                 *table->val = my_atoi(&p1);
  905.             }
  906.             table++;
  907.         }
  908.     }
  909.  
  910.     while( c )
  911.     {
  912.         if( c == '-')
  913.         {
  914.             switch(*p++)
  915.             {
  916.                 case 'l':
  917.                     p = parse_path(p, log);
  918.                     break;
  919.  
  920.                 case 'm':
  921.                     p = parse_mode(p, mode);
  922.                     break;
  923.             };
  924.         };
  925.         c = *p++;
  926.     };
  927. };
  928.  
  929. char *strstr(const char *cs, const char *ct)
  930. {
  931. int d0, d1;
  932. register char *__res;
  933. __asm__ __volatile__(
  934.     "movl %6,%%edi\n\t"
  935.     "repne\n\t"
  936.     "scasb\n\t"
  937.     "notl %%ecx\n\t"
  938.     "decl %%ecx\n\t"    /* NOTE! This also sets Z if searchstring='' */
  939.     "movl %%ecx,%%edx\n"
  940.     "1:\tmovl %6,%%edi\n\t"
  941.     "movl %%esi,%%eax\n\t"
  942.     "movl %%edx,%%ecx\n\t"
  943.     "repe\n\t"
  944.     "cmpsb\n\t"
  945.     "je 2f\n\t"     /* also works for empty string, see above */
  946.     "xchgl %%eax,%%esi\n\t"
  947.     "incl %%esi\n\t"
  948.     "cmpb $0,-1(%%eax)\n\t"
  949.     "jne 1b\n\t"
  950.     "xorl %%eax,%%eax\n\t"
  951.     "2:"
  952.     : "=a" (__res), "=&c" (d0), "=&S" (d1)
  953.     : "0" (0), "1" (0xffffffff), "2" (cs), "g" (ct)
  954.     : "dx", "di");
  955. return __res;
  956. }
  957.  
  958.  
  959.