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

📄 ahci.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */	/* JMicron 360/1/3/5/6, match class to avoid IDE function */	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },	/* ATI */	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700/800 */	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb600 }, /* ATI SB700/800 */	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb600 }, /* ATI SB700/800 */	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb600 }, /* ATI SB700/800 */	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb600 }, /* ATI SB700/800 */	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb600 }, /* ATI SB700/800 */	/* VIA */	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */	/* NVIDIA */	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci },		/* MCP65 */	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci },		/* MCP65 */	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci },		/* MCP65 */	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci },		/* MCP65 */	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci },		/* MCP65 */	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci },		/* MCP65 */	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci },		/* MCP65 */	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci },		/* MCP65 */	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci },		/* MCP67 */	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci },		/* MCP73 */	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci },		/* MCP77 */	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci },		/* MCP79 */	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci },		/* MCP79 */	/* SiS */	{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */	{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */	{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */	/* Marvell */	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */	/* Generic, PCI class code for AHCI */	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },	{ }	/* terminate list */};static struct pci_driver ahci_pci_driver = {	.name			= DRV_NAME,	.id_table		= ahci_pci_tbl,	.probe			= ahci_init_one,	.remove			= ata_pci_remove_one,#ifdef CONFIG_PM	.suspend		= ahci_pci_device_suspend,	.resume			= ahci_pci_device_resume,#endif};static inline int ahci_nr_ports(u32 cap){	return (cap & 0x1f) + 1;}static inline void __iomem *__ahci_port_base(struct ata_host *host,					     unsigned int port_no){	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];	return mmio + 0x100 + (port_no * 0x80);}static inline void __iomem *ahci_port_base(struct ata_port *ap){	return __ahci_port_base(ap->host, ap->port_no);}/** *	ahci_save_initial_config - Save and fixup initial config values *	@pdev: target PCI device *	@hpriv: host private area to store config values * *	Some registers containing configuration info might be setup by *	BIOS and might be cleared on reset.  This function saves the *	initial values of those registers into @hpriv such that they *	can be restored after controller reset. * *	If inconsistent, config values are fixed up by this function. * *	LOCKING: *	None. */static void ahci_save_initial_config(struct pci_dev *pdev,				     struct ahci_host_priv *hpriv){	void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];	u32 cap, port_map;	int i;	/* Values prefixed with saved_ are written back to host after	 * reset.  Values without are used for driver operation.	 */	hpriv->saved_cap = cap = readl(mmio + HOST_CAP);	hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);	/* some chips have errata preventing 64bit use */	if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {		dev_printk(KERN_INFO, &pdev->dev,			   "controller can't do 64bit DMA, forcing 32bit\n");		cap &= ~HOST_CAP_64;	}	if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {		dev_printk(KERN_INFO, &pdev->dev,			   "controller can't do NCQ, turning off CAP_NCQ\n");		cap &= ~HOST_CAP_NCQ;	}	if ((cap && HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {		dev_printk(KERN_INFO, &pdev->dev,			   "controller can't do PMP, turning off CAP_PMP\n");		cap &= ~HOST_CAP_PMP;	}	/*	 * Temporary Marvell 6145 hack: PATA port presence	 * is asserted through the standard AHCI port	 * presence register, as bit 4 (counting from 0)	 */	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {		dev_printk(KERN_ERR, &pdev->dev,			   "MV_AHCI HACK: port_map %x -> %x\n",			   hpriv->port_map,			   hpriv->port_map & 0xf);		port_map &= 0xf;	}	/* cross check port_map and cap.n_ports */	if (port_map) {		u32 tmp_port_map = port_map;		int n_ports = ahci_nr_ports(cap);		for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {			if (tmp_port_map & (1 << i)) {				n_ports--;				tmp_port_map &= ~(1 << i);			}		}		/* If n_ports and port_map are inconsistent, whine and		 * clear port_map and let it be generated from n_ports.		 */		if (n_ports || tmp_port_map) {			dev_printk(KERN_WARNING, &pdev->dev,				   "nr_ports (%u) and implemented port map "				   "(0x%x) don't match, using nr_ports\n",				   ahci_nr_ports(cap), port_map);			port_map = 0;		}	}	/* fabricate port_map from cap.nr_ports */	if (!port_map) {		port_map = (1 << ahci_nr_ports(cap)) - 1;		dev_printk(KERN_WARNING, &pdev->dev,			   "forcing PORTS_IMPL to 0x%x\n", port_map);		/* write the fixed up value to the PI register */		hpriv->saved_port_map = port_map;	}	/* record values to use during operation */	hpriv->cap = cap;	hpriv->port_map = port_map;}/** *	ahci_restore_initial_config - Restore initial config *	@host: target ATA host * *	Restore initial config stored by ahci_save_initial_config(). * *	LOCKING: *	None. */static void ahci_restore_initial_config(struct ata_host *host){	struct ahci_host_priv *hpriv = host->private_data;	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];	writel(hpriv->saved_cap, mmio + HOST_CAP);	writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */}static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg){	static const int offset[] = {		[SCR_STATUS]		= PORT_SCR_STAT,		[SCR_CONTROL]		= PORT_SCR_CTL,		[SCR_ERROR]		= PORT_SCR_ERR,		[SCR_ACTIVE]		= PORT_SCR_ACT,		[SCR_NOTIFICATION]	= PORT_SCR_NTF,	};	struct ahci_host_priv *hpriv = ap->host->private_data;	if (sc_reg < ARRAY_SIZE(offset) &&	    (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))		return offset[sc_reg];	return 0;}static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val){	void __iomem *port_mmio = ahci_port_base(ap);	int offset = ahci_scr_offset(ap, sc_reg);	if (offset) {		*val = readl(port_mmio + offset);		return 0;	}	return -EINVAL;}static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val){	void __iomem *port_mmio = ahci_port_base(ap);	int offset = ahci_scr_offset(ap, sc_reg);	if (offset) {		writel(val, port_mmio + offset);		return 0;	}	return -EINVAL;}static void ahci_start_engine(struct ata_port *ap){	void __iomem *port_mmio = ahci_port_base(ap);	u32 tmp;	/* start DMA */	tmp = readl(port_mmio + PORT_CMD);	tmp |= PORT_CMD_START;	writel(tmp, port_mmio + PORT_CMD);	readl(port_mmio + PORT_CMD); /* flush */}static int ahci_stop_engine(struct ata_port *ap){	void __iomem *port_mmio = ahci_port_base(ap);	u32 tmp;	tmp = readl(port_mmio + PORT_CMD);	/* check if the HBA is idle */	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)		return 0;	/* setting HBA to idle */	tmp &= ~PORT_CMD_START;	writel(tmp, port_mmio + PORT_CMD);	/* wait for engine to stop. This could be as long as 500 msec */	tmp = ata_wait_register(port_mmio + PORT_CMD,				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);	if (tmp & PORT_CMD_LIST_ON)		return -EIO;	return 0;}static void ahci_start_fis_rx(struct ata_port *ap){	void __iomem *port_mmio = ahci_port_base(ap);	struct ahci_host_priv *hpriv = ap->host->private_data;	struct ahci_port_priv *pp = ap->private_data;	u32 tmp;	/* set FIS registers */	if (hpriv->cap & HOST_CAP_64)		writel((pp->cmd_slot_dma >> 16) >> 16,		       port_mmio + PORT_LST_ADDR_HI);	writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);	if (hpriv->cap & HOST_CAP_64)		writel((pp->rx_fis_dma >> 16) >> 16,		       port_mmio + PORT_FIS_ADDR_HI);	writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);	/* enable FIS reception */	tmp = readl(port_mmio + PORT_CMD);	tmp |= PORT_CMD_FIS_RX;	writel(tmp, port_mmio + PORT_CMD);	/* flush */	readl(port_mmio + PORT_CMD);}static int ahci_stop_fis_rx(struct ata_port *ap){	void __iomem *port_mmio = ahci_port_base(ap);	u32 tmp;	/* disable FIS reception */	tmp = readl(port_mmio + PORT_CMD);	tmp &= ~PORT_CMD_FIS_RX;	writel(tmp, port_mmio + PORT_CMD);	/* wait for completion, spec says 500ms, give it 1000 */	tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,				PORT_CMD_FIS_ON, 10, 1000);	if (tmp & PORT_CMD_FIS_ON)		return -EBUSY;	return 0;}static void ahci_power_up(struct ata_port *ap){	struct ahci_host_priv *hpriv = ap->host->private_data;	void __iomem *port_mmio = ahci_port_base(ap);	u32 cmd;	cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;	/* spin up device */	if (hpriv->cap & HOST_CAP_SSS) {		cmd |= PORT_CMD_SPIN_UP;		writel(cmd, port_mmio + PORT_CMD);	}	/* wake up link */	writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);}static void ahci_disable_alpm(struct ata_port *ap){	struct ahci_host_priv *hpriv = ap->host->private_data;	void __iomem *port_mmio = ahci_port_base(ap);	u32 cmd;	struct ahci_port_priv *pp = ap->private_data;	/* IPM bits should be disabled by libata-core */	/* get the existing command bits */	cmd = readl(port_mmio + PORT_CMD);	/* disable ALPM and ASP */	cmd &= ~PORT_CMD_ASP;	cmd &= ~PORT_CMD_ALPE;	/* force the interface back to active */	cmd |= PORT_CMD_ICC_ACTIVE;	/* write out new cmd value */	writel(cmd, port_mmio + PORT_CMD);	cmd = readl(port_mmio + PORT_CMD);	/* wait 10ms to be sure we've come out of any low power state */	msleep(10);	/* clear out any PhyRdy stuff from interrupt status */	writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);	/* go ahead and clean out PhyRdy Change from Serror too */	ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));	/* 	 * Clear flag to indicate that we should ignore all PhyRdy 	 * state changes 	 */	hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;	/* 	 * Enable interrupts on Phy Ready. 	 */	pp->intr_mask |= PORT_IRQ_PHYRDY;	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);	/* 	 * don't change the link pm policy - we can be called 	 * just to turn of link pm temporarily 	 */}static int ahci_enable_alpm(struct ata_port *ap,	enum link_pm policy){	struct ahci_host_priv *hpriv = ap->host->private_data;	void __iomem *port_mmio = ahci_port_base(ap);	u32 cmd;	struct ahci_port_priv *pp = ap->private_data;	u32 asp;	/* Make sure the host is capable of link power management */	if (!(hpriv->cap & HOST_CAP_ALPM))		return -EINVAL;	switch (policy) {	case MAX_PERFORMANCE:	case NOT_AVAILABLE:

⌨️ 快捷键说明

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