📄 cpqphp_ctrl.c
字号:
/** * remove_board - Turns off slot and LED's * */static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl){ int index; u8 skip = 0; u8 device; u8 hp_slot; u8 temp_byte; u32 rc; struct resource_lists res_lists; struct pci_func *temp_func; if (func == NULL) return(1); if (cpqhp_unconfigure_device(func)) return(1); device = func->device; hp_slot = func->device - ctrl->slot_device_offset; dbg("In "__FUNCTION__", hp_slot = %d\n", hp_slot); // When we get here, it is safe to change base Address Registers. // We will attempt to save the base Address Register Lengths if (replace_flag || !ctrl->add_support) rc = cpqhp_save_base_addr_length(ctrl, func); else if (!func->bus_head && !func->mem_head && !func->p_mem_head && !func->io_head) { // Here we check to see if we've saved any of the board's // resources already. If so, we'll skip the attempt to // determine what's being used. index = 0; temp_func = cpqhp_slot_find(func->bus, func->device, index++); while (temp_func) { if (temp_func->bus_head || temp_func->mem_head || temp_func->p_mem_head || temp_func->io_head) { skip = 1; break; } temp_func = cpqhp_slot_find(temp_func->bus, temp_func->device, index++); } if (!skip) rc = cpqhp_save_used_resources(ctrl, func); } // Change status to shutdown if (func->is_a_board) func->status = 0x01; func->configured = 0; // Wait for exclusive access to hardware down(&ctrl->crit_sect); green_LED_off (ctrl, hp_slot); slot_disable (ctrl, hp_slot); set_SOGO(ctrl); // turn off SERR for slot temp_byte = readb(ctrl->hpc_reg + SLOT_SERR); temp_byte &= ~(0x01 << hp_slot); writeb(temp_byte, ctrl->hpc_reg + SLOT_SERR); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); // Done with exclusive hardware access up(&ctrl->crit_sect); if (!replace_flag && ctrl->add_support) { while (func) { res_lists.io_head = ctrl->io_head; res_lists.mem_head = ctrl->mem_head; res_lists.p_mem_head = ctrl->p_mem_head; res_lists.bus_head = ctrl->bus_head; cpqhp_return_board_resources(func, &res_lists); ctrl->io_head = res_lists.io_head; ctrl->mem_head = res_lists.mem_head; ctrl->p_mem_head = res_lists.p_mem_head; ctrl->bus_head = res_lists.bus_head; cpqhp_resource_sort_and_combine(&(ctrl->mem_head)); cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head)); cpqhp_resource_sort_and_combine(&(ctrl->io_head)); cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); if (is_bridge(func)) { bridge_slot_remove(func); } else slot_remove(func); func = cpqhp_slot_find(ctrl->bus, device, 0); } // Setup slot structure with entry for empty slot func = cpqhp_slot_create(ctrl->bus); if (func == NULL) { // Out of memory return(1); } func->bus = ctrl->bus; func->device = device; func->function = 0; func->configured = 0; func->switch_save = 0x10; func->is_a_board = 0; func->p_task_event = NULL; } return 0;}static void pushbutton_helper_thread (unsigned long data){ pushbutton_pending = data; up(&event_semaphore);}// this is the main worker threadstatic int event_thread(void* data){ struct controller *ctrl; lock_kernel(); daemonize(); // New name strcpy(current->comm, "phpd_event"); unlock_kernel(); while (1) { dbg("!!!!event_thread sleeping\n"); down_interruptible (&event_semaphore); dbg("event_thread woken finished = %d\n", event_finished); if (event_finished) break; /* Do stuff here */ if (pushbutton_pending) cpqhp_pushbutton_thread(pushbutton_pending); else for (ctrl = cpqhp_ctrl_list; ctrl; ctrl=ctrl->next) interrupt_event_handler(ctrl); } dbg("event_thread signals exit\n"); up(&event_exit); return 0;}int cpqhp_event_start_thread (void){ int pid; /* initialize our semaphores */ init_MUTEX(&delay_sem); init_MUTEX_LOCKED(&event_semaphore); init_MUTEX_LOCKED(&event_exit); event_finished=0; pid = kernel_thread(event_thread, 0, 0); if (pid < 0) { err ("Can't start up our event thread\n"); return -1; } dbg("Our event thread pid = %d\n", pid); return 0;}void cpqhp_event_stop_thread (void){ event_finished = 1; dbg("event_thread finish command given\n"); up(&event_semaphore); dbg("wait for event_thread to exit\n"); down(&event_exit);}static int update_slot_info (struct controller *ctrl, struct slot *slot){ struct hotplug_slot_info *info; char buffer[SLOT_NAME_SIZE]; int result; info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); if (!info) return -ENOMEM; make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); info->power_status = get_slot_enabled(ctrl, slot); info->attention_status = cpq_get_attention_status(ctrl, slot); info->latch_status = cpq_get_latch_status(ctrl, slot); info->adapter_status = get_presence_status(ctrl, slot); result = pci_hp_change_slot_info(buffer, info); kfree (info); return result;}static void interrupt_event_handler(struct controller *ctrl){ int loop = 0; int change = 1; struct pci_func *func; u8 hp_slot; struct slot *p_slot; while (change) { change = 0; for (loop = 0; loop < 10; loop++) { //dbg("loop %d\n", loop); if (ctrl->event_queue[loop].event_type != 0) { hp_slot = ctrl->event_queue[loop].hp_slot; func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot); if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { dbg("button pressed\n"); } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { dbg("button cancel\n"); del_timer(&p_slot->task_event); // Wait for exclusive access to hardware down(&ctrl->crit_sect); if (p_slot->state == BLINKINGOFF_STATE) { // slot is on // turn on green LED dbg("turn on green LED\n"); green_LED_on (ctrl, hp_slot); } else if (p_slot->state == BLINKINGON_STATE) { // slot is off // turn off green LED dbg("turn off green LED\n"); green_LED_off (ctrl, hp_slot); } info(msg_button_cancel, p_slot->number); p_slot->state = STATIC_STATE; amber_LED_off (ctrl, hp_slot); set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); // Done with exclusive hardware access up(&ctrl->crit_sect); } // ***********button Released (No action on press...) else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) { dbg("button release\n"); if (is_slot_enabled (ctrl, hp_slot)) { // slot is on dbg("slot is on\n"); p_slot->state = BLINKINGOFF_STATE; info(msg_button_off, p_slot->number); } else { // slot is off dbg("slot is off\n"); p_slot->state = BLINKINGON_STATE; info(msg_button_on, p_slot->number); } // Wait for exclusive access to hardware down(&ctrl->crit_sect); dbg("blink green LED and turn off amber\n"); amber_LED_off (ctrl, hp_slot); green_LED_blink (ctrl, hp_slot); set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); // Done with exclusive hardware access up(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->hp_slot = hp_slot; p_slot->ctrl = ctrl;// p_slot->physical_slot = physical_slot; p_slot->task_event.expires = jiffies + 5 * HZ; // 5 second delay p_slot->task_event.function = pushbutton_helper_thread; p_slot->task_event.data = (u32) p_slot; dbg("add_timer p_slot = %p\n", p_slot); add_timer(&p_slot->task_event); } // ***********POWER FAULT else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { dbg("power fault\n"); } else { /* refresh notification */ if (p_slot) update_slot_info(ctrl, p_slot); } ctrl->event_queue[loop].event_type = 0; change = 1; } } // End of FOR loop } return;}/** * cpqhp_pushbutton_thread * * Scheduled procedure to handle blocking stuff for the pushbuttons * Handles all pending events and exits. * */void cpqhp_pushbutton_thread (unsigned long slot){ u8 hp_slot; u8 device; struct pci_func *func; struct slot *p_slot = (struct slot *) slot; struct controller *ctrl = (struct controller *) p_slot->ctrl; pushbutton_pending = 0; hp_slot = p_slot->hp_slot; device = p_slot->device; if (is_slot_enabled (ctrl, hp_slot)) { p_slot->state = POWEROFF_STATE; // power Down board func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl); if (!func) { dbg("Error! func NULL in "__FUNCTION__"\n"); return ; } if (func != NULL && ctrl != NULL) { if (cpqhp_process_SS(ctrl, func) != 0) { amber_LED_on (ctrl, hp_slot); green_LED_on (ctrl, hp_slot); set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); } } p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; // slot is off func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl); if (!func) { dbg("Error! func NULL in "__FUNCTION__"\n"); return ; } if (func != NULL && ctrl != NULL) { if (cpqhp_process_SI(ctrl, func) != 0) { amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); } } p_slot->state = STATIC_STATE; } return;}int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func){ u8 device, hp_slot; u16 temp_word; u32 tempdword; int rc; struct slot* p_slot; int physical_slot = 0; if (!ctrl) return(1); tempdword = 0; device = func->device; hp_slot = device - ctrl->slot_device_offset; p_slot = find_slot(ctrl, device); if (p_slot) { physical_slot = p_slot->number; } // Check to see if the interlock is closed tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); if (tempdword & (0x01 << hp_slot)) { return(1); } if (func->is_a_board) { rc = board_replaced(func, ctrl); } else { // add board slot_remove(func); func = cpqhp_slot_create(ctrl->bus); if (func == NULL) { return(1); } func->bus = ctrl->bus; func->device = device; func->function = 0; func->configured = 0; func->is_a_board = 1; // We have to save the presence info for these slots temp_word = ctrl->ctrl_int_comp >> 16; func->presence_save = (temp_word >> hp_slot) & 0x01; func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { func->switch_save = 0; } else { func->switch_save = 0x10; } rc = board_added(func, ctrl); if (rc) { if (is_bridge(func)) { bridge_slot_remove(func); } else slot_remove(func); // Setup slot structure with entry for empty slot func = cpqhp_slot_create(ctrl->bus); if (func == NULL) { // Out of memory return(1); } func->bus = ctrl->bus; func->device = device; func->function = 0; func->configured = 0; func->is_a_board = 0; // We have to save the presence info for these slots temp_word = ctrl->ctrl_int_comp >> 16; func->presence_save = (temp_word >> hp_slot) & 0x01; func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { func->switch_save = 0; } else { func->switch_save = 0x10; } } } if (rc) { dbg(__FUNCTION__": rc = %d\n", rc); } if (p_slot) update_slot_info(ctrl, p_slot); return rc;}int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func){ u8 device, class_code, header_type, BCR; u8 index = 0; u8 replace_flag; u32 rc = 0; struct slot* p_slot; int physical_slot=0; device = func->device; func = cpqhp_slot_find(ctrl->bus, device, index++); p_slot = find_slot(ctrl, device); if (p_slot) { physical_slot = p_slot->number; } // Make sure there are no video controllers here while (func && !rc) { // Check the Class Code rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code); if (rc) return rc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -