📄 cpqphp_ctrl.c
字号:
return(2);}/** * bridge_slot_remove - Removes a node from the linked list of slots. * @bridge: bridge to remove * * Returns 0 if successful, !0 otherwise. */static int bridge_slot_remove(struct pci_func *bridge){ u8 subordinateBus, secondaryBus; u8 tempBus; struct pci_func *next; if (bridge == NULL) return(1); secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { next = cpqhp_slot_list[tempBus]; while (!slot_remove(next)) { next = cpqhp_slot_list[tempBus]; } } next = cpqhp_slot_list[bridge->bus]; if (next == NULL) { return(1); } if (next == bridge) { cpqhp_slot_list[bridge->bus] = bridge->next; kfree(bridge); return(0); } while ((next->next != bridge) && (next->next != NULL)) { next = next->next; } if (next->next == bridge) { next->next = bridge->next; kfree(bridge); return(0); } else return(2);}/** * cpqhp_slot_find - Looks for a node by bus, and device, multiple functions accessed * @bus: bus to find * @device: device to find * @index: is 0 for first function found, 1 for the second... * * Returns pointer to the node if successful, %NULL otherwise. */struct pci_func *cpqhp_slot_find(u8 bus, u8 device, u8 index){ int found = -1; struct pci_func *func; func = cpqhp_slot_list[bus]; if ((func == NULL) || ((func->device == device) && (index == 0))) return(func); if (func->device == device) found++; while (func->next != NULL) { func = func->next; if (func->device == device) found++; if (found == index) return(func); } return(NULL);}// DJZ: I don't think is_bridge will work as is.//FIXMEstatic int is_bridge(struct pci_func * func){ // Check the header type if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) return 1; else return 0;}/* the following routines constitute the bulk of the hotplug controller logic *//** * board_replaced - Called after a board has been replaced in the system. * * This is only used if we don't have resources for hot add * Turns power on for the board * Checks to see if board is the same * If board is same, reconfigures it * If board isn't same, turns it back off. * */static u32 board_replaced(struct pci_func * func, struct controller * ctrl){ u8 hp_slot; u8 temp_byte; u32 index; u32 rc = 0; u32 src = 8; hp_slot = func->device - ctrl->slot_device_offset; if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)) { //********************************* // The switch is open. //********************************* rc = INTERLOCK_OPEN; } else if (is_slot_enabled (ctrl, hp_slot)) { //********************************* // The board is already on //********************************* rc = CARD_FUNCTIONING; } else { if (ctrl->speed == 1) { // Wait for exclusive access to hardware down(&ctrl->crit_sect); // turn on board without attaching to the bus enable_slot_power (ctrl, hp_slot); set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); // Change bits in slot power register to force another shift out // NOTE: this is to work around the timer bug temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); writeb(0x00, ctrl->hpc_reg + SLOT_POWER); writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { rc = WRONG_BUS_FREQUENCY; } // turn off board without attaching to the bus disable_slot_power (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); if (rc) return(rc); } // Wait for exclusive access to hardware down(&ctrl->crit_sect); slot_enable (ctrl, hp_slot); green_LED_blink (ctrl, hp_slot); 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); // Wait for ~1 second because of hot plug spec long_delay(1*HZ); // Check for a power fault if (func->status == 0xFF) { // power fault occurred, but it was benign rc = POWER_FAILURE; func->status = 0; } else rc = cpqhp_valid_replace(ctrl, func); if (!rc) { // It must be the same board rc = cpqhp_configure_board(ctrl, func); if (rc || src) { // If configuration fails, turn it off // Get slot won't work for devices behind bridges, but // in this case it will always be called for the "base" // bus/dev/func of an adapter. // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); slot_disable (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); if (rc) return(rc); else return(1); } func->status = 0; func->switch_save = 0x10; index = 1; while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) { rc |= cpqhp_configure_board(ctrl, func); index++; } if (rc) { // If configuration fails, turn it off // Get slot won't work for devices behind bridges, but // in this case it will always be called for the "base" // bus/dev/func of an adapter. // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); slot_disable (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); return(rc); } // Done configuring so turn LED on full time // Wait for exclusive access to hardware down(&ctrl->crit_sect); green_LED_on (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); rc = 0; } else { // Something is wrong // Get slot won't work for devices behind bridges, but // in this case it will always be called for the "base" // bus/dev/func of an adapter. // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); slot_disable (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); } } return(rc);}/** * board_added - Called after a board has been added to the system. * * Turns power on for the board * Configures board * */static u32 board_added(struct pci_func * func, struct controller * ctrl){ u8 hp_slot; u8 temp_byte; int index; u32 temp_register = 0xFFFFFFFF; u32 rc = 0; struct pci_func *new_slot = NULL; struct slot *p_slot; struct resource_lists res_lists; hp_slot = func->device - ctrl->slot_device_offset; dbg(__FUNCTION__": func->device, slot_offset, hp_slot = %d, %d ,%d\n", func->device, ctrl->slot_device_offset, hp_slot); if (ctrl->speed == 1) { // Wait for exclusive access to hardware down(&ctrl->crit_sect); // turn on board without attaching to the bus enable_slot_power (ctrl, hp_slot); set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); // Change bits in slot power register to force another shift out // NOTE: this is to work around the timer bug temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); writeb(0x00, ctrl->hpc_reg + SLOT_POWER); writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { rc = WRONG_BUS_FREQUENCY; } // turn off board without attaching to the bus disable_slot_power (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); if (rc) return(rc); } p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); // turn on board and blink green LED // Wait for exclusive access to hardware dbg(__FUNCTION__": before down\n"); down(&ctrl->crit_sect); dbg(__FUNCTION__": after down\n"); dbg(__FUNCTION__": before slot_enable\n"); slot_enable (ctrl, hp_slot); dbg(__FUNCTION__": before green_LED_blink\n"); green_LED_blink (ctrl, hp_slot); dbg(__FUNCTION__": before amber_LED_blink\n"); amber_LED_off (ctrl, hp_slot); dbg(__FUNCTION__": before set_SOGO\n"); set_SOGO(ctrl); // Wait for SOBS to be unset dbg(__FUNCTION__": before wait_for_ctrl_irq\n"); wait_for_ctrl_irq (ctrl); dbg(__FUNCTION__": after wait_for_ctrl_irq\n"); // Done with exclusive hardware access dbg(__FUNCTION__": before up\n"); up(&ctrl->crit_sect); dbg(__FUNCTION__": after up\n"); // Wait for ~1 second because of hot plug spec dbg(__FUNCTION__": before long_delay\n"); long_delay(1*HZ); dbg(__FUNCTION__": after long_delay\n"); dbg(__FUNCTION__": func status = %x\n", func->status); // Check for a power fault if (func->status == 0xFF) { // power fault occurred, but it was benign temp_register = 0xFFFFFFFF; dbg(__FUNCTION__": temp register set to %x by power fault\n", temp_register); rc = POWER_FAILURE; func->status = 0; } else { // Get vendor/device ID u32 rc = pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_VENDOR_ID, &temp_register); dbg(__FUNCTION__": pci_read_config_dword returns %d\n", rc); dbg(__FUNCTION__": temp_register is %x\n", temp_register); if (rc != 0) { // Something's wrong here temp_register = 0xFFFFFFFF; dbg(__FUNCTION__": temp register set to %x by error\n", temp_register); } // Preset return code. It will be changed later if things go okay. rc = NO_ADAPTER_PRESENT; } // All F's is an empty slot or an invalid board if (temp_register != 0xFFFFFFFF) { // Check for a board in the slot 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; res_lists.irqs = NULL; rc = configure_new_device(ctrl, func, 0, &res_lists); dbg(__FUNCTION__": back from configure_new_device\n"); 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 (rc) { // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); slot_disable (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); return(rc); } else { cpqhp_save_slot_config(ctrl, func); } func->status = 0; func->switch_save = 0x10; func->is_a_board = 0x01; //next, we will instantiate the linux pci_dev structures (with appropriate driver notification, if already present) dbg(__FUNCTION__": configure linux pci_dev structure\n"); index = 0; do { new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++); if (new_slot && !new_slot->pci_dev) { cpqhp_configure_device(ctrl, new_slot); } } while (new_slot); // Wait for exclusive access to hardware down(&ctrl->crit_sect); green_LED_on (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); } else { // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); slot_disable (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); return(rc); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -