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

📄 cpqphp_ctrl.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
		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)				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("%s: rc = %d\n", __FUNCTION__, 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;	unsigned int devfn;	struct slot* p_slot;	struct pci_bus *pci_bus = ctrl->pci_bus;	int physical_slot=0;	device = func->device; 	func = cpqhp_slot_find(ctrl->bus, device, index++);	p_slot = cpqhp_find_slot(ctrl, device);	if (p_slot) {		physical_slot = p_slot->number;	}	/* Make sure there are no video controllers here */	while (func && !rc) {		pci_bus->number = func->bus;		devfn = PCI_DEVFN(func->device, func->function);		/* Check the Class Code */		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);		if (rc)			return rc;		if (class_code == PCI_BASE_CLASS_DISPLAY) {			/* Display/Video adapter (not supported) */			rc = REMOVE_NOT_SUPPORTED;		} else {			/* See if it's a bridge */			rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);			if (rc)				return rc;			/* If it's a bridge, check the VGA Enable bit */			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {				rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);				if (rc)					return rc;				/* If the VGA Enable bit is set, remove isn't				 * supported */				if (BCR & PCI_BRIDGE_CTL_VGA) {					rc = REMOVE_NOT_SUPPORTED;				}			}		}		func = cpqhp_slot_find(ctrl->bus, device, index++);	}	func = cpqhp_slot_find(ctrl->bus, device, 0);	if ((func != NULL) && !rc) {		/* FIXME: Replace flag should be passed into process_SS */		replace_flag = !(ctrl->add_support);		rc = remove_board(func, replace_flag, ctrl);	} else if (!rc) {		rc = 1;	}	if (p_slot)		update_slot_info(ctrl, p_slot);	return rc;}/** * switch_leds: switch the leds, go from one site to the other. * @ctrl: controller to use * @num_of_slots: number of slots to use * @direction: 1 to start from the left side, 0 to start right. */static void switch_leds(struct controller *ctrl, const int num_of_slots,			u32 *work_LED, const int direction){	int loop;	for (loop = 0; loop < num_of_slots; loop++) {		if (direction)			*work_LED = *work_LED >> 1;		else			*work_LED = *work_LED << 1;		writel(*work_LED, ctrl->hpc_reg + LED_CONTROL);		set_SOGO(ctrl);		/* Wait for SOGO interrupt */		wait_for_ctrl_irq(ctrl);		/* Get ready for next iteration */		long_delay((2*HZ)/10);	}}/** * hardware_test - runs hardware tests * * For hot plug ctrl folks to play with. * test_num is the number written to the "test" file in sysfs * */int cpqhp_hardware_test(struct controller *ctrl, int test_num){	u32 save_LED;	u32 work_LED;	int loop;	int num_of_slots;	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0f;	switch (test_num) {		case 1:			/* Do stuff here! */			/* Do that funky LED thing */			/* so we can restore them later */			save_LED = readl(ctrl->hpc_reg + LED_CONTROL);			work_LED = 0x01010101;			switch_leds(ctrl, num_of_slots, &work_LED, 0);			switch_leds(ctrl, num_of_slots, &work_LED, 1);			switch_leds(ctrl, num_of_slots, &work_LED, 0);			switch_leds(ctrl, num_of_slots, &work_LED, 1);			work_LED = 0x01010000;			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);			switch_leds(ctrl, num_of_slots, &work_LED, 0);			switch_leds(ctrl, num_of_slots, &work_LED, 1);			work_LED = 0x00000101;			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);			switch_leds(ctrl, num_of_slots, &work_LED, 0);			switch_leds(ctrl, num_of_slots, &work_LED, 1);			work_LED = 0x01010000;			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);			for (loop = 0; loop < num_of_slots; loop++) {				set_SOGO(ctrl);				/* Wait for SOGO interrupt */				wait_for_ctrl_irq (ctrl);				/* Get ready for next iteration */				long_delay((3*HZ)/10);				work_LED = work_LED >> 16;				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);								set_SOGO(ctrl);				/* Wait for SOGO interrupt */				wait_for_ctrl_irq (ctrl);				/* Get ready for next iteration */				long_delay((3*HZ)/10);				work_LED = work_LED << 16;				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);				work_LED = work_LED << 1;				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);			}			/* put it back the way it was */			writel(save_LED, ctrl->hpc_reg + LED_CONTROL);			set_SOGO(ctrl);			/* Wait for SOBS to be unset */			wait_for_ctrl_irq (ctrl);			break;		case 2:			/* Do other stuff here! */			break;		case 3:			/* and more... */			break;	}	return 0;}/** * configure_new_device - Configures the PCI header information of one board. * * @ctrl: pointer to controller structure * @func: pointer to function structure * @behind_bridge: 1 if this is a recursive call, 0 if not * @resources: pointer to set of resource lists * * Returns 0 if success * */static u32 configure_new_device(struct controller * ctrl, struct pci_func * func,				 u8 behind_bridge, struct resource_lists * resources){	u8 temp_byte, function, max_functions, stop_it;	int rc;	u32 ID;	struct pci_func *new_slot;	int index;	new_slot = func;	dbg("%s\n", __FUNCTION__);	/* Check for Multi-function device */	ctrl->pci_bus->number = func->bus;	rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);	if (rc) {		dbg("%s: rc = %d\n", __FUNCTION__, rc);		return rc;	}	if (temp_byte & 0x80)	/* Multi-function device */		max_functions = 8;	else		max_functions = 1;	function = 0;	do {		rc = configure_new_function(ctrl, new_slot, behind_bridge, resources);		if (rc) {			dbg("configure_new_function failed %d\n",rc);			index = 0;			while (new_slot) {				new_slot = cpqhp_slot_find(new_slot->bus, new_slot->device, index++);				if (new_slot)					cpqhp_return_board_resources(new_slot, resources);			}			return rc;		}		function++;		stop_it = 0;		/* The following loop skips to the next present function		 * and creates a board structure */		while ((function < max_functions) && (!stop_it)) {			pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);			if (ID == 0xFFFFFFFF) {	  /* There's nothing there. */				function++;			} else {  /* There's something there */				/* Setup slot structure. */				new_slot = cpqhp_slot_create(func->bus);				if (new_slot == NULL)					return 1;				new_slot->bus = func->bus;				new_slot->device = func->device;				new_slot->function = function;				new_slot->is_a_board = 1;				new_slot->status = 0;				stop_it++;			}		}	} while (function < max_functions);	dbg("returning from configure_new_device\n");	return 0;}/*  Configuration logic that involves the hotplug data structures and   their bookkeeping *//** * configure_new_function - Configures the PCI header information of one device * * @ctrl: pointer to controller structure * @func: pointer to function structure * @behind_bridge: 1 if this is a recursive call, 0 if not * @resources: pointer to set of resource lists * * Calls itself recursively for bridged devices. * Returns 0 if success * */static int configure_new_function(struct controller *ctrl, struct pci_func *func,				   u8 behind_bridge,				   struct resource_lists *resources){	int cloop;	u8 IRQ = 0;	u8 temp_byte;	u8 device;	u8 class_code;	u16 command;	u16 temp_word;	u32 temp_dword;	u32 rc;	u32 temp_register;	u32 base;	u32 ID;	unsigned int devfn;	struct pci_resource *mem_node;	struct pci_resource *p_mem_node;	struct pci_resource *io_node;	struct pci_resource *bus_node;	struct pci_resource *hold_mem_node;	struct pci_resource *hold_p_mem_node;	struct pci_resource *hold_IO_node;	struct pci_resource *hold_bus_node;	struct irq_mapping irqs;	struct pci_func *new_slot;	struct pci_bus *pci_bus;	struct resource_lists temp_resources;	pci_bus = ctrl->pci_bus;	pci_bus->number = func->bus;	devfn = PCI_DEVFN(func->device, func->function);	/* Check for Bridge */	rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);	if (rc)		return rc;	if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */		/* set Primary bus */		dbg("set Primary bus = %d\n", func->bus);		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);		if (rc)			return rc;		/* find range of busses to use */		dbg("find ranges of buses to use\n");		bus_node = get_max_resource(&(resources->bus_head), 1);		/* If we don't have any busses to allocate, we can't continue */		if (!bus_node)			return -ENOMEM;		/* set Secondary bus */		temp_byte = bus_node->base;		dbg("set Secondary bus = %d\n", bus_node->base);		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);		if (rc)			return rc;		/* set subordinate bus */		temp_byte = bus_node->base + bus_node->length - 1;		dbg("set subordinate bus = %d\n", bus_node->base + bus_node->length - 1);		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);		if (rc)			return rc;		/* set subordinate Latency Timer and base Latency Timer */		temp_byte = 0x40;		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);		if (rc)			return rc;		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);		if (rc)			return rc;		/* set Cache Line size */		temp_byte = 0x08;		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);		if (rc)			return rc;		/* Setup the IO, memory, and prefetchable windows */		io_node = get_max_resource(&(resources->io_head), 0x1000);		if (!io_node)			return -ENOMEM;		mem_node = get_max_resource(&(resources->mem_head), 0x100000);		if (!mem_node)			return -ENOMEM;		p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000);		if (!p_mem_node)			return -ENOMEM;		dbg("Setup the IO, memory, and prefetchable windows\n");		dbg("io_node\n");		dbg("(base, len, next) (%x, %x, %p)\n", io_node->base,					io_node->length, io_node->next);		dbg("mem_node\n");		dbg("(base, len, next) (%x, %x, %p)\n", mem_node->base,					mem_node->length, mem_node->next);		dbg("p_mem_node\n");		dbg("(base, len, next) (%x, %x, %p)\n", p_mem_node->base,					p_mem_node->length, p_mem_node->next);		/* set up the IRQ info */		if (!resources->irqs) {			irqs.barber_pole = 0;			irqs.interrupt[0] = 0;			irqs.interrupt[1] = 0;			irqs.interrupt[2] = 0;			irqs.interrupt[3] = 0;			irqs.valid_INT = 0;		} else {			irqs.barber_pole = resources->irqs->barber_pole;			irqs.interrupt[0] = resources->irqs->interrupt[0];			irqs.interrupt[1] = resources->irqs->interrupt[1];			irqs.interrupt[2] = resources->irqs->interrupt[2];			irqs.interrupt[3] = resources->irqs->interrupt[3];			irqs.valid_INT = resources->irqs->valid_INT;		}		/* set up resource lists that are now aligned on top and bottom		 * for anything behind the bridge. */		temp_resources.bus_head = bus_node;		temp_resources.io_head = io_node;		temp_resources.mem_head = mem_node;		temp_resources.p_mem_head = p_mem_node;		temp_resources.irqs = &irqs;		/* Make copies of the nodes we are going to pass down so that		 * if there is a problem,we can just use these to free resources */		hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);		hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);		hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);		hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL);		if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {			kfree(hold_bus_node);			kfree(hold_IO_node);			kfree(hold_mem_node);			kfree(hold_p_mem_node);			return 1;		}		memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));		bus_node->base += 1;		bus_node->length -= 1;		bus_node->next = NULL;		/* If we have IO resources copy them and fill in the bridge's		 * IO range registers */		if (io_node) {			memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));			io_node->next = NULL;			/* set IO base and Limit registers */			temp_byte = io_node->base >> 8;			rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);			temp_byte = (io_node->base + io_node->length - 1) >> 8;			rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);		} else {			kfree(hold_IO_node);			hold_IO_node = NULL;		}		/* If we have memory resources copy them and fill in the		 * bridge's memory range registers.  Otherwise, fill in the		 * range registers with values that disable them. */		if (mem_node) {			memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));			mem_node->next = NULL;			/* set Mem base and Limit registers */			temp_word = mem_node->base >> 16;			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);			temp_word = (mem_node->base + mem_node->length - 1) >> 16;			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);		} else {			temp_word = 0xFFFF;			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_w

⌨️ 快捷键说明

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