📄 h8.c
字号:
case H8_RECAL_PTR: case H8_SET_INT_BATT_PERCENT: case H8_WRT_CFG_INTERFACE_REG: case H8_WRT_EVENT_STATUS_MASK: case H8_ENTER_POST_MODE: case H8_EXIT_POST_MODE: case H8_RD_EEPROM: case H8_WRT_EEPROM: case H8_WRT_TO_STATUS_DISP: printk("H8: Write IO status display command done\n"); break; case H8_DEFINE_SPC_CHAR: case H8_DEFINE_TABLE_STRING_ENTRY: case H8_PERFORM_EMU_CMD: case H8_EMU_RD_REG: case H8_EMU_WRT_REG: case H8_EMU_RD_RAM: case H8_EMU_WRT_RAM: case H8_BQ_RD_REG: case H8_BQ_WRT_REG: case H8_PWR_OFF: printk ("H8: misc command completed\n"); break; } return;}/* * Retrieve the current CPU temperature and case temperature. Provides * the feedback for the thermal control algorithm. Synchcronized via * sleep() for priority so that no other actions in the process will take * place before the data becomes available. */inth8_get_curr_temp(u_char curr_temp[]){ u_char buf[H8_MAX_CMD_SIZE]; unsigned long flags; memset(buf, 0, H8_MAX_CMD_SIZE); buf[0] = H8_RD_CURR_TEMP; h8_q_cmd(buf, 1, 2); save_flags(flags); cli(); while((h8_sync_channel & H8_RD_CURR_TEMP) == 0) sleep_on(&h8_sync_wait); restore_flags(flags); h8_sync_channel &= ~H8_RD_CURR_TEMP; curr_temp[0] = xx.byte[0]; curr_temp[1] = xx.byte[1]; xx.word = 0; if(h8_debug & 0x8) printk("H8: curr CPU temp %d, Sys temp %d\n", curr_temp[0], curr_temp[1]); return 0;}static voidh8_get_max_temp(void){ u_char buf[H8_MAX_CMD_SIZE]; buf[0] = H8_RD_MAX_TEMP; h8_q_cmd(buf, 1, 2);}/* * Assigns an upper limit to the value of the H8 thermal interrupt. * As an example setting a value of 115 F here will cause the * interrupt to trigger when the CPU temperature reaches 115 F. */static voidh8_set_upper_therm_thold(int thold){ u_char buf[H8_MAX_CMD_SIZE]; /* write 0 to reinitialize interrupt */ buf[0] = H8_CTL_UPPER_TEMP; buf[1] = 0x0; buf[2] = 0x0; h8_q_cmd(buf, 3, 1); /* Do it for real */ buf[0] = H8_CTL_UPPER_TEMP; buf[1] = 0x0; buf[2] = thold; h8_q_cmd(buf, 3, 1); }static voidh8_get_upper_therm_thold(void){ u_char buf[H8_MAX_CMD_SIZE]; buf[0] = H8_CTL_UPPER_TEMP; buf[1] = 0xff; buf[2] = 0; h8_q_cmd(buf, 3, 1); }/* * The external status word contains information on keyboard controller, * power button, changes in external batt status, change in DC state, * docking station, etc. General purpose querying use. */inth8_get_ext_status(u_char stat_word[]){ u_char buf[H8_MAX_CMD_SIZE]; unsigned long flags; memset(buf, 0, H8_MAX_CMD_SIZE); buf[0] = H8_RD_EXT_STATUS; h8_q_cmd(buf, 1, 2); save_flags(flags); cli(); while((h8_sync_channel & H8_GET_EXT_STATUS) == 0) sleep_on(&h8_sync_wait); restore_flags(flags); h8_sync_channel &= ~H8_GET_EXT_STATUS; stat_word[0] = xx.byte[0]; stat_word[1] = xx.byte[1]; xx.word = 0; if(h8_debug & 0x8) printk("H8: curr ext status %x, %x\n", stat_word[0], stat_word[1]); return 0;}/* * Thread attached to task 0 manages thermal/physcial state of Alphabook. * When a condition is detected by the interrupt service routine, the * isr does a wakeup() on h8_monitor_wait. The mask value is then * screened for the appropriate action. */inth8_monitor_thread(void * unused){ u_char curr_temp[2]; /* * Need a logic based safety valve here. During boot when this thread is * started and the thermal interrupt is not yet initialized this logic * checks the temperature and acts accordingly. When this path is acted * upon system boot is painfully slow, however, the priority associated * with overheating is high enough to warrant this action. */ h8_get_curr_temp(curr_temp); printk("H8: Initial CPU temp: %d\n", curr_temp[0]); if(curr_temp[0] >= h8_uthermal_threshold) { h8_set_event_mask(H8_MANAGE_UTHERM); h8_manage_therm(); } else { /* * Arm the upper thermal limit of the H8 so that any temp in * excess will trigger the thermal control mechanism. */ h8_set_upper_therm_thold(h8_uthermal_threshold); } for(;;) { sleep_on(&h8_monitor_wait); if(h8_debug & 0x2) printk("h8_monitor_thread awakened, mask:%x\n", h8_event_mask); if (h8_event_mask & (H8_MANAGE_UTHERM|H8_MANAGE_LTHERM)) { h8_manage_therm(); }#if 0 if (h8_event_mask & H8_POWER_BUTTON) { h8_system_down(); } /* * If an external DC supply is removed or added make * appropriate CPU speed adjustments. */ if (h8_event_mask & H8_MANAGE_BATTERY) { h8_run_level_3_manage(H8_RUN); h8_clear_event_mask(H8_MANAGE_BATTERY); }#endif }}/* * Function implements the following policy. When the machine is booted * the system is set to run at full clock speed. When the upper thermal * threshold is reached as a result of full clock a damping factor is * applied to cool off the cpu. The default value is one quarter clock * (57 Mhz). When as a result of this cooling a temperature lower by * hmc_uthermal_window is reached, the machine is reset to a higher * speed, one half clock (115 Mhz). One half clock is maintained until * the upper thermal threshold is again reached restarting the cycle. */inth8_manage_therm(void){ u_char curr_temp[2]; if(h8_event_mask & H8_MANAGE_UTHERM) { /* Upper thermal interrupt received, need to cool down. */ if(h8_debug & 0x10) printk("H8: Thermal threshold %d F reached\n", h8_uthermal_threshold); h8_set_cpu_speed(h8_udamp); h8_clear_event_mask(H8_MANAGE_UTHERM); h8_set_event_mask(H8_MANAGE_LTHERM); /* Check again in 30 seconds for CPU temperature */ h8_start_monitor_timer(H8_TIMEOUT_INTERVAL); } else if (h8_event_mask & H8_MANAGE_LTHERM) { /* See how cool the system has become as a result of the reduction in speed. */ h8_get_curr_temp(curr_temp); last_temp = curr_temp[0]; if (curr_temp[0] < (h8_uthermal_threshold - h8_uthermal_window)) { /* System cooling has progressed to a point that the CPU may be sped up. */ h8_set_upper_therm_thold(h8_uthermal_threshold); h8_set_cpu_speed(h8_ldamp); /* adjustable */ if(h8_debug & 0x10) printk("H8: CPU cool, applying cpu_divisor: %d \n", h8_ldamp); h8_clear_event_mask(H8_MANAGE_LTHERM); } else /* Not cool enough yet, check again in 30 seconds. */ h8_start_monitor_timer(H8_TIMEOUT_INTERVAL); } else { } return 0;}/* * Function conditions the value of global_rpb_counter before * calling the primitive which causes the actual speed change. */voidh8_set_cpu_speed(int speed_divisor){#ifdef NOT_YET/* * global_rpb_counter is consumed by alpha_delay() in determining just * how much time to delay. It is necessary that the number of microseconds * in DELAY(n) be kept consistent over a variety of CPU clock speeds. * To that end global_rpb_counter is here adjusted. */ switch (speed_divisor) { case 0: global_rpb_counter = rpb->rpb_counter * 2L; break; case 1: global_rpb_counter = rpb->rpb_counter * 4L / 3L ; break; case 3: global_rpb_counter = rpb->rpb_counter / 2L; break; case 4: global_rpb_counter = rpb->rpb_counter / 4L; break; case 5: global_rpb_counter = rpb->rpb_counter / 8L; break; /* * This case most commonly needed for cpu_speed_divisor * of 2 which is the value assigned by the firmware. */ default: global_rpb_counter = rpb->rpb_counter; break; }#endif /* NOT_YET */ if(h8_debug & 0x8) printk("H8: Setting CPU speed to %d MHz\n", speed_tab[speed_divisor]); /* Make the actual speed change */ lca_clock_fiddle(speed_divisor);}/* * Gets value stored in rpb representing CPU clock speed and adjusts this * value based on the current clock speed divisor. */u_longh8_get_cpu_speed(void){ u_long speed = 0; u_long counter;#ifdef NOT_YET counter = rpb->rpb_counter / 1000000L; switch (alphabook_get_clock()) { case 0: speed = counter * 2L; break; case 1: speed = counter * 4L / 3L ; break; case 2: speed = counter; break; case 3: speed = counter / 2L; break; case 4: speed = counter / 4L; break; case 5: speed = counter / 8L; break; default: break; } if(h8_debug & 0x8) printk("H8: CPU speed current setting: %d MHz\n", speed); #endif /* NOT_YET */ return speed;}static voidh8_activate_monitor(unsigned long unused){ unsigned long flags; save_flags(flags); cli(); h8_monitor_timer_active = 0; restore_flags(flags); wake_up(&h8_monitor_wait);}static voidh8_start_monitor_timer(unsigned long secs){ unsigned long flags; if (h8_monitor_timer_active) return; save_flags(flags); cli(); h8_monitor_timer_active = 1; restore_flags(flags); init_timer(&h8_monitor_timer); h8_monitor_timer.function = h8_activate_monitor; h8_monitor_timer.expires = secs * HZ + jiffies; add_timer(&h8_monitor_timer);}static void h8_set_event_mask(int mask){ unsigned long flags; save_flags(flags); cli(); h8_event_mask |= mask; restore_flags(flags);}static void h8_clear_event_mask(int mask){ unsigned long flags; save_flags(flags); cli(); h8_event_mask &= (~mask); restore_flags(flags);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -