Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <ddk.h>
  2. #include <syscall.h>
  3. #include <pci.h>
  4.  
  5. #define CPUID_VENDOR_LENGTH     3               /* 3 GPRs hold vendor ID */
  6. #define CPUID_VENDOR_STR_LENGTH (CPUID_VENDOR_LENGTH * sizeof(uint32_t) + 1)
  7. #define CPUID_BRAND_LENGTH      12              /* 12 GPRs hold vendor ID */
  8. #define CPUID_BRAND_STR_LENGTH  (CPUID_BRAND_LENGTH * sizeof(uint32_t) + 1)
  9.  
  10. typedef union {
  11.    unsigned char ch[48];
  12.    uint32_t      uint[12];
  13.    struct {
  14.       uint32_t    fill1:24;      /* Bit 0 */
  15.       uint32_t    l1_i_sz:8;
  16.       uint32_t    fill2:24;
  17.       uint32_t    l1_d_sz:8;
  18.       uint32_t    fill3:16;
  19.       uint32_t    l2_sz:16;
  20.       uint32_t    fill4:18;
  21.       uint32_t    l3_sz:14;
  22.       uint32_t    fill5[8];
  23.    } amd;
  24. } cpuid_cache_info_t;
  25.  
  26. /* Typedef for storing the CPUID Vendor String */
  27. typedef union {
  28.    /* Note: the extra byte in the char array is for '\0'. */
  29.    char           char_array[CPUID_VENDOR_STR_LENGTH];
  30.    uint32_t       uint32_array[CPUID_VENDOR_LENGTH];
  31. } cpuid_vendor_string_t;
  32.  
  33. /* Typedef for storing the CPUID Brand String */
  34. typedef union {
  35.    /* Note: the extra byte in the char array is for '\0'. */
  36.    char           char_array[CPUID_BRAND_STR_LENGTH];
  37.    uint32_t       uint32_array[CPUID_BRAND_LENGTH];
  38. } cpuid_brand_string_t;
  39.  
  40. /* Typedef for storing CPUID Version */
  41. typedef union {
  42.    uint32_t flat;
  43.    struct {
  44.       uint32_t    stepping:4;      /* Bit 0 */
  45.       uint32_t    model:4;
  46.       uint32_t    family:4;
  47.       uint32_t    processorType:2;
  48.       uint32_t    reserved1514:2;
  49.       uint32_t    extendedModel:4;
  50.       uint32_t    extendedFamily:8;
  51.       uint32_t    reserved3128:4;  /* Bit 31 */
  52.    } bits;      
  53. } cpuid_version_t;
  54.  
  55. /* Typedef for storing CPUID Processor Information */
  56. typedef union {
  57.    uint32_t flat;
  58.    struct {
  59.       uint32_t    brandIndex:8;    /* Bit 0 */
  60.       uint32_t    cflushLineSize:8;
  61.       uint32_t    logicalProcessorCount:8;
  62.       uint32_t    apicID:8;        /* Bit 31 */
  63.    } bits;      
  64. } cpuid_proc_info_t;
  65.  
  66. /* Typedef for storing CPUID Feature flags */
  67. typedef union {
  68.    uint32_t flat;
  69.    struct {
  70.       uint32_t    :1;          
  71.    } bits;
  72. } cpuid_custom_features;
  73.  
  74. /* Typedef for storing CPUID Feature flags */
  75. typedef union {
  76.    uint32_t       uint32_array[3];
  77.    struct {
  78.       uint32_t    fpu:1;           /* EDX feature flags, bit 0 */
  79.       uint32_t    vme:1;
  80.       uint32_t    de:1;
  81.       uint32_t    pse:1;
  82.       uint32_t    rdtsc:1;
  83.       uint32_t    msr:1;
  84.       uint32_t    pae:1;
  85.       uint32_t    mce:1;
  86.       uint32_t    cx8:1;
  87.       uint32_t    apic:1;
  88.       uint32_t    bit10:1;
  89.       uint32_t    sep:1;
  90.       uint32_t    mtrr:1;
  91.       uint32_t    pge:1;
  92.       uint32_t    mca:1;
  93.       uint32_t    cmov:1;
  94.       uint32_t    pat:1;
  95.       uint32_t    pse36:1;
  96.       uint32_t    psn:1;
  97.       uint32_t    cflush:1;
  98.       uint32_t    bit20:1;
  99.       uint32_t    ds:1;
  100.       uint32_t    acpi:1;
  101.       uint32_t    mmx:1;
  102.       uint32_t    fxsr:1;
  103.       uint32_t    sse:1;
  104.       uint32_t    sse2:1;
  105.       uint32_t    ss:1;
  106.       uint32_t    htt:1;
  107.       uint32_t    tm:1;
  108.       uint32_t    bit30:1;
  109.       uint32_t    pbe:1;           /* EDX feature flags, bit 31 */
  110.       uint32_t    sse3:1;          /* ECX feature flags, bit 0 */
  111.       uint32_t    mulq:1;
  112.       uint32_t    bit2:1;
  113.       uint32_t    mon:1;
  114.       uint32_t    dscpl:1;
  115.       uint32_t    vmx:1;
  116.         uint32_t    smx:1;             
  117.         uint32_t    eist:1;  
  118.         uint32_t    tm2:1;                                     
  119.       uint32_t    bits_9_31:23;
  120.       uint32_t    bits0_28:29;     /* EDX extended feature flags, bit 0 */
  121.       uint32_t    lm:1;            /* Long Mode */
  122.       uint32_t    bits_30_31:2;    /* EDX extended feature flags, bit 32 */
  123.    } bits;
  124. } cpuid_feature_flags_t;
  125.  
  126. /* An overall structure to cache all of the CPUID information */
  127. struct cpu_ident {
  128.         uint32_t max_cpuid;
  129.         uint32_t max_xcpuid;
  130.         uint32_t dts_pmp;
  131.         cpuid_version_t vers;
  132.         cpuid_proc_info_t info;
  133.         cpuid_feature_flags_t fid;
  134.         cpuid_vendor_string_t vend_id;
  135.         cpuid_brand_string_t brand_id;
  136.         cpuid_cache_info_t cache_info;
  137.         cpuid_custom_features custom;
  138. };
  139.  
  140. struct cpuid4_eax {
  141.         uint32_t        ctype:5;
  142.         uint32_t        level:3;
  143.         uint32_t        is_self_initializing:1;
  144.         uint32_t        is_fully_associative:1;
  145.         uint32_t        reserved:4;
  146.         uint32_t        num_threads_sharing:12;
  147.         uint32_t        num_cores_on_die:6;
  148. };
  149.  
  150. struct cpuid4_ebx {
  151.         uint32_t        coherency_line_size:12;
  152.         uint32_t        physical_line_partition:10;
  153.         uint32_t        ways_of_associativity:10;
  154. };
  155.  
  156. struct cpuid4_ecx {
  157.         uint32_t        number_of_sets:32;
  158. };
  159.  
  160. unsigned imc_type=0;
  161. struct cpu_ident cpu_id;
  162. bool temp_out_disable=false;
  163.  
  164. #define PCI_CONF_TYPE_NONE 0
  165. #define PCI_CONF_TYPE_1    1
  166. #define PCI_CONF_TYPE_2    2
  167.  
  168. extern struct cpu_ident cpu_id;
  169.  
  170. static unsigned char pci_conf_type = PCI_CONF_TYPE_NONE;
  171.  
  172. #define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
  173.         (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
  174.  
  175. #define PCI_CONF2_ADDRESS(dev, reg)     (unsigned short)(0xC000 | (dev << 8) | reg)
  176.  
  177. #define PCI_CONF3_ADDRESS(bus, dev, fn, reg) \
  178.         (0x80000000 | (((reg >> 8) & 0xF) << 24) | (bus << 16) | ((dev & 0x1F) << 11) | (fn << 8) | (reg & 0xFF))
  179.  
  180. int pci_conf_read(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long *value)
  181. {
  182.         int result;
  183.  
  184.         if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255 && pci_conf_type != PCI_CONF_TYPE_1))
  185.                 return -1;
  186.  
  187.         result = -1;
  188.         switch(pci_conf_type) {
  189.         case PCI_CONF_TYPE_1:
  190.                 if(reg < 256){
  191.                         outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
  192.                 }else{
  193.                         outl(PCI_CONF3_ADDRESS(bus, dev, fn, reg), 0xCF8);             
  194.                 }
  195.                 switch(len) {
  196.                 case 1:  *value = inb(0xCFC + (reg & 3)); result = 0; break;
  197.                 case 2:  *value = inw(0xCFC + (reg & 2)); result = 0; break;
  198.                 case 4:  *value = inl(0xCFC); result = 0; break;
  199.                 }
  200.                 break;
  201.         case PCI_CONF_TYPE_2:
  202.                 outb(0xF0 | (fn << 1), 0xCF8);
  203.                 outb(bus, 0xCFA);
  204.  
  205.                 switch(len) {
  206.                 case 1:  *value = inb(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
  207.                 case 2:  *value = inw(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
  208.                 case 4:  *value = inl(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
  209.                 }
  210.                 outb(0, 0xCF8);
  211.                 break;
  212.         }
  213.         return result;
  214. }
  215.  
  216. void detect_imc(void)
  217. {
  218.         // Check AMD IMC
  219.         if(cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.family == 0xF)
  220.                 {
  221.                         printk("extended family = %x\n", cpu_id.vers.bits.extendedFamily);
  222.             switch(cpu_id.vers.bits.extendedFamily)
  223.                                         {
  224.                                                 case 0x0:
  225.                                                         imc_type = 0x0100; // Old K8
  226.                                                         break;
  227.                                                 case 0x1:
  228.                                                 case 0x2:
  229.                                                         imc_type = 0x0101; // K10 (Family 10h & 11h)
  230.                                                         break;
  231.                                                 case 0x3:
  232.                                                         imc_type = 0x0102; // A-Series APU (Family 12h)
  233.                                                         break;
  234.                                                 case 0x5:
  235.                                                         imc_type = 0x0103; // C- / E- / Z- Series APU (Family 14h)
  236.                                                         break; 
  237.                                                 case 0x6:
  238.                                                         imc_type = 0x0104; // FX Series (Family 15h)
  239.                                                         break;                                                         
  240.                                                 case 0x7:
  241.                                                         imc_type = 0x0105; // Kabini & related (Family 16h)
  242.                                                         break;                 
  243.                                         }      
  244.                         return;
  245.                 }
  246.                                        
  247.         // Check Intel IMC     
  248.         if(cpu_id.vend_id.char_array[0] == 'G' && cpu_id.vers.bits.family == 6 && cpu_id.vers.bits.extendedModel)
  249.                 {                                      
  250.                         switch(cpu_id.vers.bits.model)
  251.                         {
  252.                                 case 0x5:
  253.                                         if(cpu_id.vers.bits.extendedModel == 2) { imc_type = 0x0003; } // Core i3/i5 1st Gen 45 nm (NHM)
  254.                                         if(cpu_id.vers.bits.extendedModel == 3) { temp_out_disable=true; } // Atom Clover Trail
  255.                                         if(cpu_id.vers.bits.extendedModel == 4) { imc_type = 0x0007; } // HSW-ULT
  256.                                         break;
  257.                                 case 0x6:
  258.                                         if(cpu_id.vers.bits.extendedModel == 3) {
  259.                                                 imc_type = 0x0009;  // Atom Cedar Trail
  260.                                                 temp_out_disable=true;
  261.                                                 //v->fail_safe |= 4; // Disable Core temp
  262.                                         }
  263.                                         break;
  264.                                 case 0xA:
  265.                                         switch(cpu_id.vers.bits.extendedModel)
  266.                                         {
  267.                                                 case 0x1:
  268.                                                         imc_type = 0x0001; // Core i7 1st Gen 45 nm (NHME)
  269.                                                         break;
  270.                                                 case 0x2:
  271.                                                         imc_type = 0x0004; // Core 2nd Gen (SNB)
  272.                                                         break; 
  273.                                                 case 0x3:
  274.                                                         imc_type = 0x0006; // Core 3nd Gen (IVB)                                               
  275.                                                         break;
  276.                                         }
  277.                                         break;
  278.                                 case 0xC:
  279.                                         switch(cpu_id.vers.bits.extendedModel)
  280.                                         {
  281.                                                 case 0x1:
  282.                                                         if(cpu_id.vers.bits.stepping > 9) { imc_type = 0x0008; } // Atom PineView      
  283.                                                         //v->fail_safe |= 4; // Disable Core temp
  284.                                                         temp_out_disable=true;
  285.                                                         break; 
  286.                                                 case 0x2:
  287.                                                         imc_type = 0x0002; // Core i7 1st Gen 32 nm (WMR)      
  288.                                                         break; 
  289.                                                 case 0x3:
  290.                                                         imc_type = 0x0007; // Core 4nd Gen (HSW)                                               
  291.                                                         break;
  292.                                         }
  293.                                         break;                 
  294.                                 case 0xD:
  295.                                         imc_type = 0x0005; // SNB-E
  296.                                         break;                         
  297.                                 case 0xE:
  298.                                         imc_type = 0x0001; // Core i7 1st Gen 45 nm (NHM)
  299.                                         break;                         
  300.                         }
  301.                
  302.                 //if(imc_type) { tsc_invariable = 1; }
  303.                 return;
  304.                 }
  305. }
  306.  
  307. static int pci_check_direct(void)
  308. {
  309.         unsigned char tmpCFB;
  310.         unsigned int  tmpCF8;
  311.        
  312.         if (cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.family == 0xF) {
  313.                         pci_conf_type = PCI_CONF_TYPE_1;
  314.                         return 0;              
  315.         } else {
  316.                         /* Check if configuration type 1 works. */
  317.                         pci_conf_type = PCI_CONF_TYPE_1;
  318.                         tmpCFB = inb(0xCFB);
  319.                         outb(0x01, 0xCFB);
  320.                         tmpCF8 = inl(0xCF8);
  321.                         outl(0x80000000, 0xCF8);
  322.                         if ((inl(0xCF8) == 0x80000000) && (pci_sanity_check() == 0)) {
  323.                                 outl(tmpCF8, 0xCF8);
  324.                                 outb(tmpCFB, 0xCFB);
  325.                                 return 0;
  326.                         }
  327.                         outl(tmpCF8, 0xCF8);
  328.                
  329.                         /* Check if configuration type 2 works. */
  330.                        
  331.                         pci_conf_type = PCI_CONF_TYPE_2;
  332.                         outb(0x00, 0xCFB);
  333.                         outb(0x00, 0xCF8);
  334.                         outb(0x00, 0xCFA);
  335.                         if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 && (pci_sanity_check() == 0)) {
  336.                                 outb(tmpCFB, 0xCFB);
  337.                                 return 0;
  338.                                
  339.         }
  340.  
  341.         outb(tmpCFB, 0xCFB);
  342.  
  343.         /* Nothing worked return an error */
  344.         pci_conf_type = PCI_CONF_TYPE_NONE;
  345.         return -1;
  346.        
  347.         }
  348. }
  349.  
  350.  
  351. #define PCI_BASE_CLASS_BRIDGE           0x06
  352. #define PCI_CLASS_BRIDGE_HOST           0x0600
  353. #define PCI_CLASS_DEVICE        0x0a    /* Device class */
  354.  
  355. int pci_sanity_check(void)
  356. {
  357.         unsigned long value;
  358.         int result;
  359.         /* Do a trivial check to make certain we can see a host bridge.
  360.          * There are reportedly some buggy chipsets from intel and
  361.          * compaq where this test does not work, I will worry about
  362.          * that when we support them.
  363.          */
  364.         result = pci_conf_read(0, 0, 0, PCI_CLASS_DEVICE, 2, &value);
  365.         if (result == 0) {
  366.                 result = -1;
  367.                 if (value == PCI_CLASS_BRIDGE_HOST) {
  368.                         result = 0;
  369.                 }
  370.         }
  371.         return result;
  372. }
  373.  
  374. int pci_init(void)
  375. {
  376.         int result;
  377.         /* For now just make certain we can directly
  378.          * use the pci functions.
  379.          */
  380.         result = pci_check_direct();
  381.         return result;
  382. }
  383.  
  384.  
  385. void get_cpuid()
  386. {
  387.         unsigned int *v, dummy[3];
  388.         char *p, *q;
  389.  
  390.         /* Get max std cpuid & vendor ID */
  391.         cpuid(0x0, &cpu_id.max_cpuid, &cpu_id.vend_id.uint32_array[0],
  392.             &cpu_id.vend_id.uint32_array[2], &cpu_id.vend_id.uint32_array[1]);
  393.         cpu_id.vend_id.char_array[11] = 0;
  394.  
  395.         /* Get processor family information & feature flags */
  396.         if (cpu_id.max_cpuid >= 1) {
  397.             cpuid(0x00000001, &cpu_id.vers.flat, &cpu_id.info.flat,
  398.                 &cpu_id.fid.uint32_array[1], &cpu_id.fid.uint32_array[0]);
  399.         }
  400.  
  401.         /* Get the digital thermal sensor & power management status bits */
  402.         if(cpu_id.max_cpuid >= 6)       {
  403.                 cpuid(0x00000006, &cpu_id.dts_pmp, &dummy[0], &dummy[1], &dummy[2]);
  404.         }
  405.        
  406.         /* Get the max extended cpuid */
  407.         cpuid(0x80000000, &cpu_id.max_xcpuid, &dummy[0], &dummy[1], &dummy[2]);
  408.  
  409.         /* Get extended feature flags, only save EDX */
  410.         if (cpu_id.max_xcpuid >= 0x80000001) {
  411.             cpuid(0x80000001, &dummy[0], &dummy[1],
  412.                 &dummy[2], &cpu_id.fid.uint32_array[2]);
  413.         }
  414.  
  415.         /* Get the brand ID */
  416.         if (cpu_id.max_xcpuid >= 0x80000004) {
  417.             v = (unsigned int *)&cpu_id.brand_id;
  418.             cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
  419.             cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
  420.             cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
  421.             cpu_id.brand_id.char_array[47] = 0;
  422.         }
  423.         /*
  424.          * Intel chips right-justify this string for some dumb reason;
  425.          * undo that brain damage:
  426.          */
  427.         p = q = &cpu_id.brand_id.char_array[0];
  428.         while (*p == ' ')
  429.                 p++;
  430.         if (p != q) {
  431.                 while (*p)
  432.                         *q++ = *p++;
  433.                 while (q <= &cpu_id.brand_id.char_array[48])
  434.                         *q++ = '\0';    /* Zero-pad the rest */
  435.         }
  436.  
  437.         /* Get cache information */
  438.         switch(cpu_id.vend_id.char_array[0]) {
  439.         case 'A':
  440.             /* AMD Processors */
  441.             /* The cache information is only in ecx and edx so only save
  442.              * those registers */
  443.             if (cpu_id.max_xcpuid >= 0x80000005) {
  444.                 cpuid(0x80000005, &dummy[0], &dummy[1],
  445.                     &cpu_id.cache_info.uint[0], &cpu_id.cache_info.uint[1]);
  446.             }
  447.             if (cpu_id.max_xcpuid >= 0x80000006) {
  448.                 cpuid(0x80000006, &dummy[0], &dummy[1],
  449.                     &cpu_id.cache_info.uint[2], &cpu_id.cache_info.uint[3]);
  450.             }
  451.             break;
  452.         case 'G':
  453.                 /* Intel Processors, Need to do this in init.c */
  454.             break;
  455.         }
  456.  
  457.         /* Turn off mon bit since monitor based spin wait may not be reliable */
  458.         cpu_id.fid.bits.mon = 0;
  459.  
  460. }
  461.  
  462. void coretemp(void)
  463. {
  464.         unsigned int msrl, msrh;
  465.         unsigned int tjunc, tabs, tnow;
  466.         unsigned long rtcr;
  467.         long amd_raw_temp=524322;
  468.        
  469.         // Only enable coretemp if IMC is known
  470.         if(imc_type == 0) { return; }
  471.        
  472.         tnow = 0;
  473.        
  474.         // Intel  CPU
  475.         if(cpu_id.vend_id.char_array[0] == 'G' && cpu_id.max_cpuid >= 6)
  476.         {
  477.                 if(cpu_id.dts_pmp & 1){
  478.                         rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh);
  479.                         tabs = ((msrl >> 16) & 0x7F);
  480.                         rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh);
  481.                         tjunc = ((msrl >> 16) & 0x7F);
  482.                         if(tjunc < 50 || tjunc > 125) { tjunc = 90; } // assume Tjunc = 90°C if boggus value received.
  483.                         tnow = tjunc - tabs;           
  484.                         //dprint(LINE_CPU+1, 30, v->check_temp, 3, 0); 
  485.                         printk("temp=%d\n", tnow);
  486.                 }
  487.                 return;
  488.         }
  489.        
  490.         // AMD CPU
  491.         if(cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.extendedFamily > 0)
  492.         {
  493.                 pci_conf_read(0, 24, 3, 0xA4, 4, &rtcr);
  494.                 amd_raw_temp = ((rtcr >> 21) & 0x7FF);
  495.         printk("temp=%d\n", amd_raw_temp/8);
  496.         }      
  497.                                
  498. }
  499.  
  500. unsigned drvEntry(int action, char *cmdline){
  501.     get_cpuid();
  502.     pci_init();
  503.     detect_imc();
  504.     if(!temp_out_disable){
  505.         coretemp();
  506.     }
  507. }
  508.