⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpqphp_ctrl.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct pci_func *next;	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;		goto out;	}	while ((next->next != bridge) && (next->next != NULL))		next = next->next;	if (next->next != bridge)		return 2;	next->next = bridge->next;out:	kfree(bridge);	return 0;}/** * 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. * FIXME */static int is_bridge(struct pci_func * func){	/* Check the header type */	if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)		return 1;	else		return 0;}/** * set_controller_speed - set the frequency and/or mode of a specific * controller segment. * * @ctrl: controller to change frequency/mode for. * @adapter_speed: the speed of the adapter we want to match. * @hp_slot: the slot number where the adapter is installed. * * Returns 0 if we successfully change frequency and/or mode to match the * adapter speed. *  */static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot){	struct slot *slot;	u8 reg;	u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);	u16 reg16;	u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);		if (ctrl->speed == adapter_speed)		return 0;		/* We don't allow freq/mode changes if we find another adapter running	 * in another slot on this controller */	for(slot = ctrl->slot; slot; slot = slot->next) {		if (slot->device == (hp_slot + ctrl->slot_device_offset)) 			continue;		if (!slot->hotplug_slot && !slot->hotplug_slot->info) 			continue;		if (slot->hotplug_slot->info->adapter_status == 0) 			continue;		/* If another adapter is running on the same segment but at a		 * lower speed/mode, we allow the new adapter to function at		 * this rate if supported */		if (ctrl->speed < adapter_speed) 			return 0;		return 1;	}		/* If the controller doesn't support freq/mode changes and the	 * controller is running at a higher mode, we bail */	if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))		return 1;		/* But we allow the adapter to run at a lower rate if possible */	if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))		return 0;	/* We try to set the max speed supported by both the adapter and	 * controller */	if (ctrl->speed_capability < adapter_speed) {		if (ctrl->speed == ctrl->speed_capability)			return 0;		adapter_speed = ctrl->speed_capability;	}	writel(0x0L, ctrl->hpc_reg + LED_CONTROL);	writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);		set_SOGO(ctrl); 	wait_for_ctrl_irq(ctrl);		if (adapter_speed != PCI_SPEED_133MHz_PCIX)		reg = 0xF5;	else		reg = 0xF4;		pci_write_config_byte(ctrl->pci_dev, 0x41, reg);		reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);	reg16 &= ~0x000F;	switch(adapter_speed) {		case(PCI_SPEED_133MHz_PCIX): 			reg = 0x75;			reg16 |= 0xB; 			break;		case(PCI_SPEED_100MHz_PCIX):			reg = 0x74;			reg16 |= 0xA;			break;		case(PCI_SPEED_66MHz_PCIX):			reg = 0x73;			reg16 |= 0x9;			break;		case(PCI_SPEED_66MHz):			reg = 0x73;			reg16 |= 0x1;			break;		default: /* 33MHz PCI 2.2 */			reg = 0x71;			break;				}	reg16 |= 0xB << 12;	writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);		mdelay(5); 		/* Reenable interrupts */	writel(0, ctrl->hpc_reg + INT_MASK);	pci_write_config_byte(ctrl->pci_dev, 0x41, reg); 		/* Restart state machine */	reg = ~0xF;	pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);	pci_write_config_byte(ctrl->pci_dev, 0x43, reg);		/* Only if mode change...*/	if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||		((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 			set_SOGO(ctrl);		wait_for_ctrl_irq(ctrl);	mdelay(1100);		/* Restore LED/Slot state */	writel(leds, ctrl->hpc_reg + LED_CONTROL);	writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);		set_SOGO(ctrl);	wait_for_ctrl_irq(ctrl);	ctrl->speed = adapter_speed;	slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);	info("Successfully changed frequency/mode for adapter in slot %d\n", 			slot->number);	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;	u8 adapter_speed;	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 {		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);				adapter_speed = get_adapter_speed(ctrl, hp_slot);		if (ctrl->speed != adapter_speed)			if (set_controller_speed(ctrl, adapter_speed, 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);		up(&ctrl->crit_sect);		if (rc)			return rc;		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);		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. */				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);				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. */				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);				up(&ctrl->crit_sect);				return rc;			}			/* Done configuring so turn LED on full time */			down(&ctrl->crit_sect);			green_LED_on (ctrl, hp_slot);			set_SOGO(ctrl);			/* Wait for SOBS to be unset */			wait_for_ctrl_irq (ctrl);			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. */			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);			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;	u8 adapter_speed;	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("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",	    __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);	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);		adapter_speed = get_adapter_speed(ctrl, hp_slot);	if (ctrl->speed != adapter_speed)		if (set_controller_speed(ctrl, adapter_speed, 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);	up(&ctrl->crit_sect);	if (rc)		return rc;		p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);	/* turn on board and blink green LED */	dbg("%s: before down\n", __FUNCTION__);	down(&ctrl->crit_sect);	dbg("%s: after down\n", __FUNCTION__);	dbg("%s: before slot_enable\n", __FUNCTION__);	slot_enable (ctrl, hp_slot);	dbg("%s: before green_LED_blink\n", __FUNCTION__);	green_LED_blink (ctrl, hp_slot);	dbg("%s: before amber_LED_blink\n", __FUNCTION__);	amber_LED_off (ctrl, hp_slot);	dbg("%s: before set_SOGO\n", __FUNCTION__);	set_SOGO(ctrl);	/* Wait for SOBS to be unset */	dbg("%s: before wait_for_ctrl_irq\n", __FUNCTION__);	wait_for_ctrl_irq (ctrl);	dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__);	dbg("%s: before up\n", __FUNCTION__);	up(&ctrl->crit_sect);	dbg("%s: after up\n", __FUNCTION__);	/* Wait for ~1 second because of hot plug spec */	dbg("%s: before long_delay\n", __FUNCTION__);	long_delay(1*HZ);	dbg("%s: after long_delay\n", __FUNCTION__);	dbg("%s: func status = %x\n", __FUNCTION__, func->status);	/* Check for a power fault */	if (func->status == 0xFF) {		/* power fault occurred, but it was benign */		temp_register = 0xFFFFFFFF;		dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);		rc = POWER_FAILURE;		func->status = 0;	} else {		/* Get vendor/device ID u32 */		ctrl->pci_bus->number = func->bus;		rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -