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

📄 cpqphp_ctrl.c

📁 audio driver for hotplug pci on linux 2.6.27
💻 C
📖 第 1 页 / 共 5 页
字号:
	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. * @func: PCI device/function information * @ctrl: hotplug controller * * 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 rc = 0;	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 {		mutex_lock(&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);		mutex_unlock(&ctrl->crit_sect);		if (rc)			return rc;		mutex_lock(&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);		mutex_unlock(&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 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. */			mutex_lock(&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);			mutex_unlock(&ctrl->crit_sect);			if (rc)				return rc;			else				return 1;		} 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. */			mutex_lock(&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);			mutex_unlock(&ctrl->crit_sect);		}	}	return rc;}/** * board_added - Called after a board has been added to the system. * @func: PCI device/function info * @ctrl: hotplug controller * * 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",	    __func__, func->device, ctrl->slot_device_offset, hp_slot);	mutex_lock(&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);	mutex_unlock(&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", __func__);	mutex_lock(&ctrl->crit_sect);	dbg("%s: after down\n", __func__);	dbg("%s: before slot_enable\n", __func__);	slot_enable (ctrl, hp_slot);	dbg("%s: before green_LED_blink\n", __func__);	green_LED_blink (ctrl, hp_slot);	dbg("%s: before amber_LED_blink\n", __func__);	amber_LED_off (ctrl, hp_slot);	dbg("%s: before set_SOGO\n", __func__);	set_SOGO(ctrl);	/* Wait for SOBS to be unset */	dbg("%s: before wait_for_ctrl_irq\n", __func__);	wait_for_ctrl_irq (ctrl);	dbg("%s: after wait_for_ctrl_irq\n", __func__);	dbg("%s: before up\n", __func__);	mutex_unlock(&ctrl->crit_sect);	dbg("%s: after up\n", __func__);	/* Wait for ~1 second because of hot plug spec */	dbg("%s: before long_delay\n", __func__);	long_delay(1*HZ);	dbg("%s: after long_delay\n", __func__);	dbg("%s: func status = %x\n", __func__, 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", __func__, 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);		dbg("%s: pci_read_config_dword returns %d\n", __func__, rc);		dbg("%s: temp_register is %x\n", __func__, temp_register);		if (rc != 0) {			/* Something's wrong here */			temp_register = 0xFFFFFFFF;			dbg("%s: temp register set to %x by error\n", __func__, 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("%s: back from configure_new_device\n", __func__);		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) {			mutex_lock(&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);

⌨️ 快捷键说明

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