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

📄 cpqphp_ctrl.c

📁 audio driver for hotplug pci on linux 2.6.27
💻 C
📖 第 1 页 / 共 5 页
字号:
			mutex_unlock(&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("%s: configure linux pci_dev structure\n", __func__);		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);		mutex_lock(&ctrl->crit_sect);		green_LED_on (ctrl, hp_slot);		set_SOGO(ctrl);		/* Wait for SOBS to be unset */		wait_for_ctrl_irq (ctrl);		mutex_unlock(&ctrl->crit_sect);	} else {		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;	}	return 0;}/** * remove_board - Turns off slot and LEDs * @func: PCI device/function info * @replace_flag: whether replacing or adding a new device * @ctrl: target controller */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 (cpqhp_unconfigure_device(func))		return 1;	device = func->device;	hp_slot = func->device - ctrl->slot_device_offset;	dbg("In %s, hp_slot = %d\n", __func__, 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;	mutex_lock(&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);	mutex_unlock(&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)			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;	wake_up_process(cpqhp_event_thread);}/* this is the main worker thread */static int event_thread(void* data){	struct controller *ctrl;	while (1) {		dbg("!!!!event_thread sleeping\n");		set_current_state(TASK_INTERRUPTIBLE);		schedule();		if (kthread_should_stop())			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");	return 0;}int cpqhp_event_start_thread(void){	cpqhp_event_thread = kthread_run(event_thread, NULL, "phpd_event");	if (IS_ERR(cpqhp_event_thread)) {		err ("Can't start up our event thread\n");		return PTR_ERR(cpqhp_event_thread);	}	return 0;}void cpqhp_event_stop_thread(void){	kthread_stop(cpqhp_event_thread);}static int update_slot_info(struct controller *ctrl, struct slot *slot){	struct hotplug_slot_info *info;	int result;	info = kmalloc(sizeof(*info), GFP_KERNEL);	if (!info)		return -ENOMEM;	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(slot->hotplug_slot, 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);				if (!func)					return;				p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);				if (!p_slot)					return;				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);					mutex_lock(&ctrl->crit_sect);					if (p_slot->state == BLINKINGOFF_STATE) {						/* slot is on */						dbg("turn on green LED\n");						green_LED_on (ctrl, hp_slot);					} else if (p_slot->state == BLINKINGON_STATE) {						/* slot is off */						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);					mutex_unlock(&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)) {						dbg("slot is on\n");						p_slot->state = BLINKINGOFF_STATE;						info(msg_button_off, p_slot->number);					} else {						dbg("slot is off\n");						p_slot->state = BLINKINGON_STATE;						info(msg_button_on, p_slot->number);					}					mutex_lock(&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);					mutex_unlock(&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 - handle pushbutton events * @slot: target slot (struct) * * 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 %s\n", __func__);			return ;		}		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 %s\n", __func__);			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;	tempdword = 0;	device = func->device;	hp_slot = device - ctrl->slot_device_offset;	p_slot = cpqhp_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)				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", __func__, rc);	}	if (p_slot)		update_slot_info(ctrl, p_slot);	return rc;}int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func){

⌨️ 快捷键说明

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