Print this page
4804 apix & pcplusmp are nearly warning free already
Tentatively Reviewed by: Robert Mustacchi <rm@joyent.com>


  37 
  38 static int hpet_init_proxy(int *hpet_vect, iflag_t *hpet_flags);
  39 static boolean_t hpet_install_proxy(void);
  40 static boolean_t hpet_callback(int code);
  41 static boolean_t hpet_cpr(int code);
  42 static boolean_t hpet_resume(void);
  43 static void hpet_cst_callback(uint32_t code);
  44 static boolean_t hpet_deep_idle_config(int code);
  45 static int hpet_validate_table(ACPI_TABLE_HPET *hpet_table);
  46 static boolean_t hpet_checksum_table(unsigned char *table, unsigned int len);
  47 static void *hpet_memory_map(ACPI_TABLE_HPET *hpet_table);
  48 static int hpet_start_main_counter(hpet_info_t *hip);
  49 static int hpet_stop_main_counter(hpet_info_t *hip);
  50 static uint64_t hpet_read_main_counter_value(hpet_info_t *hip);
  51 static uint64_t hpet_set_leg_rt_cnf(hpet_info_t *hip, uint32_t new_value);
  52 static uint64_t hpet_read_gen_cap(hpet_info_t *hip);
  53 static uint64_t hpet_read_gen_config(hpet_info_t *hip);
  54 static uint64_t hpet_read_gen_intrpt_stat(hpet_info_t *hip);
  55 static uint64_t hpet_read_timer_N_config(hpet_info_t *hip, uint_t n);
  56 static hpet_TN_conf_cap_t hpet_convert_timer_N_config(uint64_t conf);
  57 /* LINTED E_STATIC_UNUSED */
  58 static uint64_t hpet_read_timer_N_comp(hpet_info_t *hip, uint_t n);
  59 /* LINTED E_STATIC_UNUSED */
  60 static void hpet_write_gen_cap(hpet_info_t *hip, uint64_t l);
  61 static void hpet_write_gen_config(hpet_info_t *hip, uint64_t l);
  62 static void hpet_write_gen_intrpt_stat(hpet_info_t *hip, uint64_t l);
  63 static void hpet_write_timer_N_config(hpet_info_t *hip, uint_t n, uint64_t l);
  64 static void hpet_write_timer_N_comp(hpet_info_t *hip, uint_t n, uint64_t l);
  65 static void hpet_disable_timer(hpet_info_t *hip, uint32_t timer_n);
  66 static void hpet_enable_timer(hpet_info_t *hip, uint32_t timer_n);
  67 /* LINTED E_STATIC_UNUSED */
  68 static void hpet_write_main_counter_value(hpet_info_t *hip, uint64_t l);
  69 static int hpet_get_IOAPIC_intr_capable_timer(hpet_info_t *hip);
  70 static int hpet_timer_available(uint32_t allocated_timers, uint32_t n);
  71 static void hpet_timer_alloc(uint32_t *allocated_timers, uint32_t n);
  72 static void hpet_timer_set_up(hpet_info_t *hip, uint32_t timer_n,
  73     uint32_t interrupt);
  74 static uint_t hpet_isr(char *arg);
  75 static uint32_t hpet_install_interrupt_handler(uint_t (*func)(char *),
  76     int vector);
  77 static void hpet_uninstall_interrupt_handler(void);
  78 static void hpet_expire_all(void);
  79 static boolean_t hpet_guaranteed_schedule(hrtime_t required_wakeup_time);
  80 static boolean_t hpet_use_hpet_timer(hrtime_t *expire);
  81 static void hpet_use_lapic_timer(hrtime_t expire);
  82 static void hpet_init_proxy_data(void);
  83 
  84 /*
  85  * hpet_state_lock is used to synchronize disabling/enabling deep c-states
  86  * and to synchronize suspend/resume.
  87  */
  88 static kmutex_t         hpet_state_lock;


 509 hpet_convert_timer_N_config(uint64_t conf)
 510 {
 511         hpet_TN_conf_cap_t cc = { 0 };
 512 
 513         cc.int_route_cap = HPET_TIMER_N_INT_ROUTE_CAP(conf);
 514         cc.fsb_int_del_cap = HPET_TIMER_N_FSB_INT_DEL_CAP(conf);
 515         cc.fsb_int_en_cnf = HPET_TIMER_N_FSB_EN_CNF(conf);
 516         cc.int_route_cnf = HPET_TIMER_N_INT_ROUTE_CNF(conf);
 517         cc.mode32_cnf = HPET_TIMER_N_MODE32_CNF(conf);
 518         cc.val_set_cnf = HPET_TIMER_N_VAL_SET_CNF(conf);
 519         cc.size_cap = HPET_TIMER_N_SIZE_CAP(conf);
 520         cc.per_int_cap = HPET_TIMER_N_PER_INT_CAP(conf);
 521         cc.type_cnf = HPET_TIMER_N_TYPE_CNF(conf);
 522         cc.int_enb_cnf = HPET_TIMER_N_INT_ENB_CNF(conf);
 523         cc.int_type_cnf = HPET_TIMER_N_INT_TYPE_CNF(conf);
 524 
 525         return (cc);
 526 }
 527 
 528 static uint64_t
 529 hpet_read_timer_N_comp(hpet_info_t *hip, uint_t n)
 530 {
 531         if (hip->timer_n_config[n].size_cap == 1)
 532                 return (*(uint64_t *)
 533                     HPET_TIMER_N_COMP_ADDRESS(hip->logical_address, n));
 534         else
 535                 return (*(uint32_t *)
 536                     HPET_TIMER_N_COMP_ADDRESS(hip->logical_address, n));
 537 }
 538 
 539 static uint64_t
 540 hpet_read_main_counter_value(hpet_info_t *hip)
 541 {
 542         uint64_t        value;
 543         uint32_t        *counter;
 544         uint32_t        high1, high2, low;
 545 
 546         counter = (uint32_t *)HPET_MAIN_COUNTER_ADDRESS(hip->logical_address);
 547 
 548         /*
 549          * 32-bit main counters
 550          */
 551         if (hip->gen_cap.count_size_cap == 0) {
 552                 value = (uint64_t)*counter;
 553                 hip->main_counter_value = value;
 554                 return (value);
 555         }
 556 
 557         /*
 558          * HPET spec claims a 64-bit read can be split into two 32-bit reads
 559          * by the hardware connection to the HPET.
 560          */
 561         high2 = counter[1];
 562         do {
 563                 high1 = high2;
 564                 low = counter[0];
 565                 high2 = counter[1];
 566         } while (high2 != high1);
 567 
 568         value = ((uint64_t)high1 << 32) | low;
 569         hip->main_counter_value = value;
 570         return (value);
 571 }
 572 
 573 static void
 574 hpet_write_gen_cap(hpet_info_t *hip, uint64_t l)
 575 {
 576         *(uint64_t *)HPET_GEN_CAP_ADDRESS(hip->logical_address) = l;
 577 }
 578 
 579 static void
 580 hpet_write_gen_config(hpet_info_t *hip, uint64_t l)
 581 {
 582         *(uint64_t *)HPET_GEN_CONFIG_ADDRESS(hip->logical_address) = l;
 583 }
 584 
 585 static void
 586 hpet_write_gen_intrpt_stat(hpet_info_t *hip, uint64_t l)
 587 {
 588         *(uint64_t *)HPET_GEN_INTR_STAT_ADDRESS(hip->logical_address) = l;
 589 }
 590 
 591 static void
 592 hpet_write_timer_N_config(hpet_info_t *hip, uint_t n, uint64_t l)
 593 {
 594         if (hip->timer_n_config[n].size_cap == 1)
 595                 *(uint64_t *)HPET_TIMER_N_CONF_ADDRESS(
 596                     hip->logical_address, n) = l;
 597         else
 598                 *(uint32_t *)HPET_TIMER_N_CONF_ADDRESS(
 599                     hip->logical_address, n) = (uint32_t)(0xFFFFFFFF & l);


 608 static void
 609 hpet_disable_timer(hpet_info_t *hip, uint32_t timer_n)
 610 {
 611         uint64_t l;
 612 
 613         l = hpet_read_timer_N_config(hip, timer_n);
 614         l &= ~HPET_TIMER_N_INT_ENB_CNF_BIT;
 615         hpet_write_timer_N_config(hip, timer_n, l);
 616 }
 617 
 618 static void
 619 hpet_enable_timer(hpet_info_t *hip, uint32_t timer_n)
 620 {
 621         uint64_t l;
 622 
 623         l = hpet_read_timer_N_config(hip, timer_n);
 624         l |= HPET_TIMER_N_INT_ENB_CNF_BIT;
 625         hpet_write_timer_N_config(hip, timer_n, l);
 626 }
 627 
 628 static void
 629 hpet_write_main_counter_value(hpet_info_t *hip, uint64_t l)
 630 {
 631         uint32_t        *address;
 632 
 633         /*
 634          * HPET spec 1.0a states main counter register should be halted before
 635          * it is written to.
 636          */
 637         ASSERT(!(hpet_read_gen_config(hip) & HPET_GCFR_ENABLE_CNF));
 638 
 639         if (hip->gen_cap.count_size_cap == 1) {
 640                 *(uint64_t *)HPET_MAIN_COUNTER_ADDRESS(hip->logical_address)
 641                     = l;
 642         } else {
 643                 address = (uint32_t *)HPET_MAIN_COUNTER_ADDRESS(
 644                     hip->logical_address);
 645 
 646                 address[0] = (uint32_t)(l & 0xFFFFFFFF);
 647         }
 648 }
 649 
 650 /*
 651  * Add the interrupt handler for I/O APIC interrupt number (interrupt line).
 652  *
 653  * The I/O APIC line (vector) is programmed in ioapic_init_intr() called
 654  * from apic_picinit() psm_ops apic_ops entry point after we return from
 655  * apic_init() psm_ops entry point.
 656  */
 657 static uint32_t
 658 hpet_install_interrupt_handler(uint_t (*func)(char *), int vector)
 659 {
 660         uint32_t retval;
 661 
 662         retval = add_avintr(NULL, CBE_HIGH_PIL, (avfunc)func, "HPET Timer",
 663             vector, NULL, NULL, NULL, NULL);
 664         if (retval == 0) {
 665                 cmn_err(CE_WARN, "!hpet_acpi: add_avintr() failed");
 666                 return (AE_BAD_PARAMETER);
 667         }
 668         return (AE_OK);
 669 }




  37 
  38 static int hpet_init_proxy(int *hpet_vect, iflag_t *hpet_flags);
  39 static boolean_t hpet_install_proxy(void);
  40 static boolean_t hpet_callback(int code);
  41 static boolean_t hpet_cpr(int code);
  42 static boolean_t hpet_resume(void);
  43 static void hpet_cst_callback(uint32_t code);
  44 static boolean_t hpet_deep_idle_config(int code);
  45 static int hpet_validate_table(ACPI_TABLE_HPET *hpet_table);
  46 static boolean_t hpet_checksum_table(unsigned char *table, unsigned int len);
  47 static void *hpet_memory_map(ACPI_TABLE_HPET *hpet_table);
  48 static int hpet_start_main_counter(hpet_info_t *hip);
  49 static int hpet_stop_main_counter(hpet_info_t *hip);
  50 static uint64_t hpet_read_main_counter_value(hpet_info_t *hip);
  51 static uint64_t hpet_set_leg_rt_cnf(hpet_info_t *hip, uint32_t new_value);
  52 static uint64_t hpet_read_gen_cap(hpet_info_t *hip);
  53 static uint64_t hpet_read_gen_config(hpet_info_t *hip);
  54 static uint64_t hpet_read_gen_intrpt_stat(hpet_info_t *hip);
  55 static uint64_t hpet_read_timer_N_config(hpet_info_t *hip, uint_t n);
  56 static hpet_TN_conf_cap_t hpet_convert_timer_N_config(uint64_t conf);




  57 static void hpet_write_gen_config(hpet_info_t *hip, uint64_t l);
  58 static void hpet_write_gen_intrpt_stat(hpet_info_t *hip, uint64_t l);
  59 static void hpet_write_timer_N_config(hpet_info_t *hip, uint_t n, uint64_t l);
  60 static void hpet_write_timer_N_comp(hpet_info_t *hip, uint_t n, uint64_t l);
  61 static void hpet_disable_timer(hpet_info_t *hip, uint32_t timer_n);
  62 static void hpet_enable_timer(hpet_info_t *hip, uint32_t timer_n);


  63 static int hpet_get_IOAPIC_intr_capable_timer(hpet_info_t *hip);
  64 static int hpet_timer_available(uint32_t allocated_timers, uint32_t n);
  65 static void hpet_timer_alloc(uint32_t *allocated_timers, uint32_t n);
  66 static void hpet_timer_set_up(hpet_info_t *hip, uint32_t timer_n,
  67     uint32_t interrupt);
  68 static uint_t hpet_isr(char *arg);
  69 static uint32_t hpet_install_interrupt_handler(uint_t (*func)(char *),
  70     int vector);
  71 static void hpet_uninstall_interrupt_handler(void);
  72 static void hpet_expire_all(void);
  73 static boolean_t hpet_guaranteed_schedule(hrtime_t required_wakeup_time);
  74 static boolean_t hpet_use_hpet_timer(hrtime_t *expire);
  75 static void hpet_use_lapic_timer(hrtime_t expire);
  76 static void hpet_init_proxy_data(void);
  77 
  78 /*
  79  * hpet_state_lock is used to synchronize disabling/enabling deep c-states
  80  * and to synchronize suspend/resume.
  81  */
  82 static kmutex_t         hpet_state_lock;


 503 hpet_convert_timer_N_config(uint64_t conf)
 504 {
 505         hpet_TN_conf_cap_t cc = { 0 };
 506 
 507         cc.int_route_cap = HPET_TIMER_N_INT_ROUTE_CAP(conf);
 508         cc.fsb_int_del_cap = HPET_TIMER_N_FSB_INT_DEL_CAP(conf);
 509         cc.fsb_int_en_cnf = HPET_TIMER_N_FSB_EN_CNF(conf);
 510         cc.int_route_cnf = HPET_TIMER_N_INT_ROUTE_CNF(conf);
 511         cc.mode32_cnf = HPET_TIMER_N_MODE32_CNF(conf);
 512         cc.val_set_cnf = HPET_TIMER_N_VAL_SET_CNF(conf);
 513         cc.size_cap = HPET_TIMER_N_SIZE_CAP(conf);
 514         cc.per_int_cap = HPET_TIMER_N_PER_INT_CAP(conf);
 515         cc.type_cnf = HPET_TIMER_N_TYPE_CNF(conf);
 516         cc.int_enb_cnf = HPET_TIMER_N_INT_ENB_CNF(conf);
 517         cc.int_type_cnf = HPET_TIMER_N_INT_TYPE_CNF(conf);
 518 
 519         return (cc);
 520 }
 521 
 522 static uint64_t











 523 hpet_read_main_counter_value(hpet_info_t *hip)
 524 {
 525         uint64_t        value;
 526         uint32_t        *counter;
 527         uint32_t        high1, high2, low;
 528 
 529         counter = (uint32_t *)HPET_MAIN_COUNTER_ADDRESS(hip->logical_address);
 530 
 531         /*
 532          * 32-bit main counters
 533          */
 534         if (hip->gen_cap.count_size_cap == 0) {
 535                 value = (uint64_t)*counter;
 536                 hip->main_counter_value = value;
 537                 return (value);
 538         }
 539 
 540         /*
 541          * HPET spec claims a 64-bit read can be split into two 32-bit reads
 542          * by the hardware connection to the HPET.
 543          */
 544         high2 = counter[1];
 545         do {
 546                 high1 = high2;
 547                 low = counter[0];
 548                 high2 = counter[1];
 549         } while (high2 != high1);
 550 
 551         value = ((uint64_t)high1 << 32) | low;
 552         hip->main_counter_value = value;
 553         return (value);
 554 }
 555 
 556 static void






 557 hpet_write_gen_config(hpet_info_t *hip, uint64_t l)
 558 {
 559         *(uint64_t *)HPET_GEN_CONFIG_ADDRESS(hip->logical_address) = l;
 560 }
 561 
 562 static void
 563 hpet_write_gen_intrpt_stat(hpet_info_t *hip, uint64_t l)
 564 {
 565         *(uint64_t *)HPET_GEN_INTR_STAT_ADDRESS(hip->logical_address) = l;
 566 }
 567 
 568 static void
 569 hpet_write_timer_N_config(hpet_info_t *hip, uint_t n, uint64_t l)
 570 {
 571         if (hip->timer_n_config[n].size_cap == 1)
 572                 *(uint64_t *)HPET_TIMER_N_CONF_ADDRESS(
 573                     hip->logical_address, n) = l;
 574         else
 575                 *(uint32_t *)HPET_TIMER_N_CONF_ADDRESS(
 576                     hip->logical_address, n) = (uint32_t)(0xFFFFFFFF & l);


 585 static void
 586 hpet_disable_timer(hpet_info_t *hip, uint32_t timer_n)
 587 {
 588         uint64_t l;
 589 
 590         l = hpet_read_timer_N_config(hip, timer_n);
 591         l &= ~HPET_TIMER_N_INT_ENB_CNF_BIT;
 592         hpet_write_timer_N_config(hip, timer_n, l);
 593 }
 594 
 595 static void
 596 hpet_enable_timer(hpet_info_t *hip, uint32_t timer_n)
 597 {
 598         uint64_t l;
 599 
 600         l = hpet_read_timer_N_config(hip, timer_n);
 601         l |= HPET_TIMER_N_INT_ENB_CNF_BIT;
 602         hpet_write_timer_N_config(hip, timer_n, l);
 603 }
 604 






















 605 /*
 606  * Add the interrupt handler for I/O APIC interrupt number (interrupt line).
 607  *
 608  * The I/O APIC line (vector) is programmed in ioapic_init_intr() called
 609  * from apic_picinit() psm_ops apic_ops entry point after we return from
 610  * apic_init() psm_ops entry point.
 611  */
 612 static uint32_t
 613 hpet_install_interrupt_handler(uint_t (*func)(char *), int vector)
 614 {
 615         uint32_t retval;
 616 
 617         retval = add_avintr(NULL, CBE_HIGH_PIL, (avfunc)func, "HPET Timer",
 618             vector, NULL, NULL, NULL, NULL);
 619         if (retval == 0) {
 620                 cmn_err(CE_WARN, "!hpet_acpi: add_avintr() failed");
 621                 return (AE_BAD_PARAMETER);
 622         }
 623         return (AE_OK);
 624 }