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

📄 pciehp_hpc.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
			return IRQ_NONE;		}		dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); 				/* Clear command complete interrupt caused by this write */		temp_word = 0x1F;		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);		if (rc) {			err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);			return IRQ_NONE;		}		dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); 	}		return IRQ_HANDLED;}static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value){	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;	enum pcie_link_speed lnk_speed;	u32	lnk_cap;	int retval = 0;	DBG_ENTER_ROUTINE 	if (!php_ctlr) {		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);		return -1;	}	if (slot->hp_slot >= php_ctlr->num_slots) {		err("%s: Invalid HPC slot number!\n", __FUNCTION__);		return -1;	}	retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap);	if (retval) {		err("%s : hp_register_read_dword  LNK_CAP failed\n", __FUNCTION__);		return retval;	}	switch (lnk_cap & 0x000F) {	case 1:		lnk_speed = PCIE_2PT5GB;		break;	default:		lnk_speed = PCIE_LNK_SPEED_UNKNOWN;		break;	}	*value = lnk_speed;	dbg("Max link speed = %d\n", lnk_speed);	DBG_LEAVE_ROUTINE 	return retval;}static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value){	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;	enum pcie_link_width lnk_wdth;	u32	lnk_cap;	int retval = 0;	DBG_ENTER_ROUTINE 	if (!php_ctlr) {		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);		return -1;	}	if (slot->hp_slot >= php_ctlr->num_slots) {		err("%s: Invalid HPC slot number!\n", __FUNCTION__);		return -1;	}	retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap);	if (retval) {		err("%s : hp_register_read_dword  LNK_CAP failed\n", __FUNCTION__);		return retval;	}	switch ((lnk_cap & 0x03F0) >> 4){	case 0:		lnk_wdth = PCIE_LNK_WIDTH_RESRV;		break;	case 1:		lnk_wdth = PCIE_LNK_X1;		break;	case 2:		lnk_wdth = PCIE_LNK_X2;		break;	case 4:		lnk_wdth = PCIE_LNK_X4;		break;	case 8:		lnk_wdth = PCIE_LNK_X8;		break;	case 12:		lnk_wdth = PCIE_LNK_X12;		break;	case 16:		lnk_wdth = PCIE_LNK_X16;		break;	case 32:		lnk_wdth = PCIE_LNK_X32;		break;	default:		lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;		break;	}	*value = lnk_wdth;	dbg("Max link width = %d\n", lnk_wdth);	DBG_LEAVE_ROUTINE 	return retval;}static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value){	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;	enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;	int retval = 0;	u16 lnk_status;	DBG_ENTER_ROUTINE 	if (!php_ctlr) {		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);		return -1;	}	if (slot->hp_slot >= php_ctlr->num_slots) {		err("%s: Invalid HPC slot number!\n", __FUNCTION__);		return -1;	}	retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status);	if (retval) {		err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);		return retval;	}	switch (lnk_status & 0x0F) {	case 1:		lnk_speed = PCIE_2PT5GB;		break;	default:		lnk_speed = PCIE_LNK_SPEED_UNKNOWN;		break;	}	*value = lnk_speed;	dbg("Current link speed = %d\n", lnk_speed);	DBG_LEAVE_ROUTINE 	return retval;}static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value){	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;	enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;	int retval = 0;	u16 lnk_status;	DBG_ENTER_ROUTINE 	if (!php_ctlr) {		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);		return -1;	}	if (slot->hp_slot >= php_ctlr->num_slots) {		err("%s: Invalid HPC slot number!\n", __FUNCTION__);		return -1;	}	retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status);	if (retval) {		err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);		return retval;	}		switch ((lnk_status & 0x03F0) >> 4){	case 0:		lnk_wdth = PCIE_LNK_WIDTH_RESRV;		break;	case 1:		lnk_wdth = PCIE_LNK_X1;		break;	case 2:		lnk_wdth = PCIE_LNK_X2;		break;	case 4:		lnk_wdth = PCIE_LNK_X4;		break;	case 8:		lnk_wdth = PCIE_LNK_X8;		break;	case 12:		lnk_wdth = PCIE_LNK_X12;		break;	case 16:		lnk_wdth = PCIE_LNK_X16;		break;	case 32:		lnk_wdth = PCIE_LNK_X32;		break;	default:		lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;		break;	}	*value = lnk_wdth;	dbg("Current link width = %d\n", lnk_wdth);	DBG_LEAVE_ROUTINE 	return retval;}static struct hpc_ops pciehp_hpc_ops = {	.power_on_slot			= hpc_power_on_slot,	.power_off_slot			= hpc_power_off_slot,	.set_attention_status		= hpc_set_attention_status,	.get_power_status		= hpc_get_power_status,	.get_attention_status		= hpc_get_attention_status,	.get_latch_status		= hpc_get_latch_status,	.get_adapter_status		= hpc_get_adapter_status,	.get_max_bus_speed		= hpc_get_max_lnk_speed,	.get_cur_bus_speed		= hpc_get_cur_lnk_speed,	.get_max_lnk_width		= hpc_get_max_lnk_width,	.get_cur_lnk_width		= hpc_get_cur_lnk_width,		.query_power_fault		= hpc_query_power_fault,	.green_led_on			= hpc_set_green_led_on,	.green_led_off			= hpc_set_green_led_off,	.green_led_blink		= hpc_set_green_led_blink,		.release_ctlr			= hpc_release_ctlr,	.check_lnk_status		= hpc_check_lnk_status,};int pcie_init(struct controller * ctrl,	struct pcie_device *dev,	php_intr_callback_t attention_button_callback,	php_intr_callback_t switch_change_callback,	php_intr_callback_t presence_change_callback,	php_intr_callback_t power_fault_callback){	struct php_ctlr_state_s *php_ctlr, *p;	void *instance_id = ctrl;	int rc;	static int first = 1;	u16 temp_word;	u16 cap_reg;	u16 intr_enable = 0;	u32 slot_cap;	int cap_base, saved_cap_base;	u16 slot_status, slot_ctrl;	struct pci_dev *pdev;	DBG_ENTER_ROUTINE		spin_lock_init(&list_lock);		php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);	if (!php_ctlr) {	/* allocate controller state data */		err("%s: HPC controller memory allocation error!\n", __FUNCTION__);		goto abort;	}	memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));		pdev = dev->port;	php_ctlr->pci_dev = pdev;	/* save pci_dev in context */	dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__,		pdev->vendor, pdev->device);	saved_cap_base = pcie_cap_base;	if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);		goto abort_free_ctlr;	}	ctrl->cap_base = cap_base;	dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base);	rc = hp_register_read_word(pdev, CAP_REG(ctrl->cap_base), cap_reg);	if (rc) {		err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG(ctrl->cap_base), cap_reg);	if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040)		&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {		dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__);		goto abort_free_ctlr;	}	rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap);	if (rc) {		err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP(ctrl->cap_base), slot_cap);	if (!(slot_cap & HP_CAP)) {		dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);		goto abort_free_ctlr;	}	/* For debugging purpose */	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);	if (rc) {		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), slot_status);	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), slot_ctrl);	if (rc) {		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), slot_ctrl);	if (first) {		spin_lock_init(&hpc_event_lock);		first = 0;	}	dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, 		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);	for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)		if (pci_resource_len(pdev, rc) > 0)			dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,				pci_resource_start(pdev, rc), pci_resource_len(pdev, rc));	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, 		pdev->subsystem_vendor, pdev->subsystem_device);	if (pci_enable_device(pdev))		goto abort_free_ctlr;		init_MUTEX(&ctrl->crit_sect);	/* setup wait queue */	init_waitqueue_head(&ctrl->queue);	/* find the IRQ */	php_ctlr->irq = dev->irq;	dbg("HPC interrupt = %d\n", php_ctlr->irq);	/* Save interrupt callback info */	php_ctlr->attention_button_callback = attention_button_callback;	php_ctlr->switch_change_callback = switch_change_callback;	php_ctlr->presence_change_callback = presence_change_callback;	php_ctlr->power_fault_callback = power_fault_callback;	php_ctlr->callback_instance_id = instance_id;	/* return PCI Controller Info */	php_ctlr->slot_device_offset = 0;	php_ctlr->num_slots = 1;	/* Mask Hot-plug Interrupt Enable */	rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);	if (rc) {		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;	rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);	if (rc) {		err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);	if (rc) {		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base)		, slot_status);	temp_word = 0x1F; /* Clear all events */	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);	if (rc) {		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);	if (pciehp_poll_mode)  {/* Install interrupt polling code */		/* Install and start the interrupt polling timer */		init_timer(&php_ctlr->int_poll_timer);		start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */	} else {		/* Installs the interrupt handler */		rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);		dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);		if (rc) {			err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);			goto abort_free_ctlr;		}	}	rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);	if (rc) {		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);	dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);	intr_enable = intr_enable | PRSN_DETECT_ENABLE;	if (ATTN_BUTTN(slot_cap))		intr_enable = intr_enable | ATTN_BUTTN_ENABLE;		if (POWER_CTRL(slot_cap))		intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;		if (MRL_SENS(slot_cap))		intr_enable = intr_enable | MRL_DETECT_ENABLE;	temp_word = (temp_word & ~intr_enable) | intr_enable; 	if (pciehp_poll_mode) {		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;	} else {		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;	}	dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);	/* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */	rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);	if (rc) {		err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);	if (rc) {		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, 		SLOT_STATUS(ctrl->cap_base), slot_status);		temp_word =  0x1F; /* Clear all events */	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);	if (rc) {		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);		/*  Add this HPC instance into the HPC list */	spin_lock(&list_lock);	if (php_ctlr_list_head == 0) {		php_ctlr_list_head = php_ctlr;		p = php_ctlr_list_head;		p->pnext = NULL;	} else {		p = php_ctlr_list_head;		while (p->pnext)			p = p->pnext;		p->pnext = php_ctlr;	}	spin_unlock(&list_lock);	ctlr_seq_num++;	ctrl->hpc_ctlr_handle = php_ctlr;	ctrl->hpc_ops = &pciehp_hpc_ops;	DBG_LEAVE_ROUTINE	return 0;	/* We end up here for the many possible ways to fail this API.  */abort_free_ctlr:	pcie_cap_base = saved_cap_base;	kfree(php_ctlr);abort:	DBG_LEAVE_ROUTINE	return -1;}

⌨️ 快捷键说明

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