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

📄 ata_piix.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *    ata_piix.c - Intel PATA/SATA controllers * *    Maintained by:  Jeff Garzik <jgarzik@pobox.com> *    		    Please ALWAYS copy linux-ide@vger.kernel.org *		    on emails. * * *	Copyright 2003-2005 Red Hat Inc *	Copyright 2003-2005 Jeff Garzik * * *	Copyright header from piix.c: * *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com> * * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * *  libata documentation is available via 'make {ps|pdf}docs', *  as Documentation/DocBook/libata.* * *  Hardware documentation available at http://developer.intel.com/ * * Documentation *	Publically available from Intel web site. Errata documentation * is also publically available. As an aide to anyone hacking on this * driver the list of errata that are relevant is below, going back to * PIIX4. Older device documentation is now a bit tricky to find. * * The chipsets all follow very much the same design. The orginal Triton * series chipsets do _not_ support independant device timings, but this * is fixed in Triton II. With the odd mobile exception the chips then * change little except in gaining more modes until SATA arrives. This * driver supports only the chips with independant timing (that is those * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix * for the early chip drivers. * * Errata of note: * * Unfixable *	PIIX4    errata #9	- Only on ultra obscure hw *	ICH3	 errata #13     - Not observed to affect real hw *				  by Intel * * Things we must deal with *	PIIX4	errata #10	- BM IDE hang with non UDMA *				  (must stop/start dma to recover) *	440MX   errata #15	- As PIIX4 errata #10 *	PIIX4	errata #15	- Must not read control registers * 				  during a PIO transfer *	440MX   errata #13	- As PIIX4 errata #15 *	ICH2	errata #21	- DMA mode 0 doesn't work right *	ICH0/1  errata #55	- As ICH2 errata #21 *	ICH2	spec c #9	- Extra operations needed to handle *				  drive hotswap [NOT YET SUPPORTED] *	ICH2    spec c #20	- IDE PRD must not cross a 64K boundary *				  and must be dword aligned *	ICH2    spec c #24	- UDMA mode 4,5 t85/86 should be 6ns not 3.3 * * Should have been BIOS fixed: *	450NX:	errata #19	- DMA hangs on old 450NX *	450NX:  errata #20	- DMA hangs on old 450NX *	450NX:  errata #25	- Corruption with DMA on old 450NX *	ICH3    errata #15      - IDE deadlock under high load *				  (BIOS must set dev 31 fn 0 bit 23) *	ICH3	errata #18	- Don't use native mode */#include <linux/kernel.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/blkdev.h>#include <linux/delay.h>#include <linux/device.h>#include <scsi/scsi_host.h>#include <linux/libata.h>#include <linux/dmi.h>#define DRV_NAME	"ata_piix"#define DRV_VERSION	"2.12"enum {	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */	ICH5_PMR		= 0x90, /* port mapping register */	ICH5_PCS		= 0x92,	/* port control and status */	PIIX_SCC		= 0x0A, /* sub-class code register */	PIIX_FLAG_SCR		= (1 << 26), /* SCR available */	PIIX_FLAG_AHCI		= (1 << 27), /* AHCI possible */	PIIX_FLAG_CHECKINTR	= (1 << 28), /* make sure PCI INTx enabled */	PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS,	PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,	/* combined mode.  if set, PATA is channel 0.	 * if clear, PATA is channel 1.	 */	PIIX_PORT_ENABLED	= (1 << 0),	PIIX_PORT_PRESENT	= (1 << 4),	PIIX_80C_PRI		= (1 << 5) | (1 << 4),	PIIX_80C_SEC		= (1 << 7) | (1 << 6),	/* controller IDs */	piix_pata_mwdma		= 0,	/* PIIX3 MWDMA only */	piix_pata_33,			/* PIIX4 at 33Mhz */	ich_pata_33,			/* ICH up to UDMA 33 only */	ich_pata_66,			/* ICH up to 66 Mhz */	ich_pata_100,			/* ICH up to UDMA 100 */	ich5_sata,	ich6_sata,	ich6_sata_ahci,	ich6m_sata_ahci,	ich8_sata_ahci,	ich8_2port_sata,	ich8m_apple_sata_ahci,		/* locks up on second port enable */	tolapai_sata_ahci,	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */	/* constants for mapping table */	P0			= 0,  /* port 0 */	P1			= 1,  /* port 1 */	P2			= 2,  /* port 2 */	P3			= 3,  /* port 3 */	IDE			= -1, /* IDE */	NA			= -2, /* not avaliable */	RV			= -3, /* reserved */	PIIX_AHCI_DEVICE	= 6,	/* host->flags bits */	PIIX_HOST_BROKEN_SUSPEND = (1 << 24),};struct piix_map_db {	const u32 mask;	const u16 port_enable;	const int map[][4];};struct piix_host_priv {	const int *map;};static int piix_init_one(struct pci_dev *pdev,			 const struct pci_device_id *ent);static void piix_pata_error_handler(struct ata_port *ap);static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);static int ich_pata_cable_detect(struct ata_port *ap);static u8 piix_vmw_bmdma_status(struct ata_port *ap);#ifdef CONFIG_PMstatic int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);static int piix_pci_device_resume(struct pci_dev *pdev);#endifstatic unsigned int in_module_init = 1;static const struct pci_device_id piix_pci_tbl[] = {	/* Intel PIIX3 for the 430HX etc */	{ 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_mwdma },	/* VMware ICH4 */	{ 0x8086, 0x7111, 0x15ad, 0x1976, 0, 0, piix_pata_vmw },	/* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */	/* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */	{ 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },	/* Intel PIIX4 */	{ 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },	/* Intel PIIX4 */	{ 0x8086, 0x7601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },	/* Intel PIIX */	{ 0x8086, 0x84CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },	/* Intel ICH (i810, i815, i840) UDMA 66*/	{ 0x8086, 0x2411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_66 },	/* Intel ICH0 : UDMA 33*/	{ 0x8086, 0x2421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_33 },	/* Intel ICH2M */	{ 0x8086, 0x244A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* Intel ICH2 (i810E2, i845, 850, 860) UDMA 100 */	{ 0x8086, 0x244B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/*  Intel ICH3M */	{ 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* Intel ICH3 (E7500/1) UDMA 100 */	{ 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */	{ 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	{ 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* Intel ICH5 */	{ 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* C-ICH (i810E2) */	{ 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* ESB (855GME/875P + 6300ESB) UDMA 100  */	{ 0x8086, 0x25A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* ICH6 (and 6) (i915) UDMA 100 */	{ 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* ICH7/7-R (i945, i975) UDMA 100*/	{ 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	{ 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* ICH8 Mobile PATA Controller */	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },	/* NOTE: The following PCI ids must be kept in sync with the	 * list in drivers/pci/quirks.c.	 */	/* 82801EB (ICH5) */	{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },	/* 82801EB (ICH5) */	{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },	/* 6300ESB (ICH5 variant with broken PCS present bits) */	{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },	/* 6300ESB pretending RAID */	{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },	/* 82801FB/FW (ICH6/ICH6W) */	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },	/* 82801FR/FRW (ICH6R/ICH6RW) */	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },	/* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },	/* 82801GB/GR/GH (ICH7, identical to ICH6) */	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },	/* 2801GBM/GHM (ICH7M, identical to ICH6M) */	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },	/* Enterprise Southbridge 2 (631xESB/632xESB) */	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },	/* SATA Controller 1 IDE (ICH8) */	{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },	/* SATA Controller 2 IDE (ICH8) */	{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },	/* Mobile SATA Controller IDE (ICH8M) */	{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },	/* Mobile SATA Controller IDE (ICH8M), Apple */	{ 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata_ahci },	/* SATA Controller IDE (ICH9) */	{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },	/* SATA Controller IDE (ICH9) */	{ 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },	/* SATA Controller IDE (ICH9) */	{ 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },	/* SATA Controller IDE (ICH9M) */	{ 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },	/* SATA Controller IDE (ICH9M) */	{ 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },	/* SATA Controller IDE (ICH9M) */	{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },	/* SATA Controller IDE (Tolapai) */	{ 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata_ahci },	{ }	/* terminate list */};static struct pci_driver piix_pci_driver = {	.name			= DRV_NAME,	.id_table		= piix_pci_tbl,	.probe			= piix_init_one,	.remove			= ata_pci_remove_one,#ifdef CONFIG_PM	.suspend		= piix_pci_device_suspend,	.resume			= piix_pci_device_resume,#endif};static struct scsi_host_template piix_sht = {	.module			= THIS_MODULE,	.name			= DRV_NAME,	.ioctl			= ata_scsi_ioctl,	.queuecommand		= ata_scsi_queuecmd,	.can_queue		= ATA_DEF_QUEUE,	.this_id		= ATA_SHT_THIS_ID,	.sg_tablesize		= LIBATA_MAX_PRD,	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,	.emulated		= ATA_SHT_EMULATED,	.use_clustering		= ATA_SHT_USE_CLUSTERING,	.proc_name		= DRV_NAME,	.dma_boundary		= ATA_DMA_BOUNDARY,	.slave_configure	= ata_scsi_slave_config,	.slave_destroy		= ata_scsi_slave_destroy,	.bios_param		= ata_std_bios_param,};static const struct ata_port_operations piix_pata_ops = {	.set_piomode		= piix_set_piomode,	.set_dmamode		= piix_set_dmamode,	.mode_filter		= ata_pci_default_filter,	.tf_load		= ata_tf_load,	.tf_read		= ata_tf_read,	.check_status		= ata_check_status,	.exec_command		= ata_exec_command,	.dev_select		= ata_std_dev_select,	.bmdma_setup		= ata_bmdma_setup,	.bmdma_start		= ata_bmdma_start,	.bmdma_stop		= ata_bmdma_stop,	.bmdma_status		= ata_bmdma_status,	.qc_prep		= ata_qc_prep,	.qc_issue		= ata_qc_issue_prot,	.data_xfer		= ata_data_xfer,	.freeze			= ata_bmdma_freeze,	.thaw			= ata_bmdma_thaw,	.error_handler		= piix_pata_error_handler,	.post_internal_cmd	= ata_bmdma_post_internal_cmd,	.cable_detect		= ata_cable_40wire,	.irq_handler		= ata_interrupt,	.irq_clear		= ata_bmdma_irq_clear,	.irq_on			= ata_irq_on,	.port_start		= ata_port_start,};static const struct ata_port_operations ich_pata_ops = {	.set_piomode		= piix_set_piomode,	.set_dmamode		= ich_set_dmamode,	.mode_filter		= ata_pci_default_filter,	.tf_load		= ata_tf_load,	.tf_read		= ata_tf_read,	.check_status		= ata_check_status,	.exec_command		= ata_exec_command,	.dev_select		= ata_std_dev_select,	.bmdma_setup		= ata_bmdma_setup,	.bmdma_start		= ata_bmdma_start,	.bmdma_stop		= ata_bmdma_stop,	.bmdma_status		= ata_bmdma_status,	.qc_prep		= ata_qc_prep,	.qc_issue		= ata_qc_issue_prot,	.data_xfer		= ata_data_xfer,	.freeze			= ata_bmdma_freeze,	.thaw			= ata_bmdma_thaw,	.error_handler		= piix_pata_error_handler,	.post_internal_cmd	= ata_bmdma_post_internal_cmd,	.cable_detect		= ich_pata_cable_detect,	.irq_handler		= ata_interrupt,	.irq_clear		= ata_bmdma_irq_clear,	.irq_on			= ata_irq_on,	.port_start		= ata_port_start,};static const struct ata_port_operations piix_sata_ops = {	.tf_load		= ata_tf_load,	.tf_read		= ata_tf_read,	.check_status		= ata_check_status,	.exec_command		= ata_exec_command,	.dev_select		= ata_std_dev_select,	.bmdma_setup		= ata_bmdma_setup,	.bmdma_start		= ata_bmdma_start,	.bmdma_stop		= ata_bmdma_stop,	.bmdma_status		= ata_bmdma_status,	.qc_prep		= ata_qc_prep,	.qc_issue		= ata_qc_issue_prot,	.data_xfer		= ata_data_xfer,	.freeze			= ata_bmdma_freeze,	.thaw			= ata_bmdma_thaw,	.error_handler		= ata_bmdma_error_handler,	.post_internal_cmd	= ata_bmdma_post_internal_cmd,	.irq_handler		= ata_interrupt,	.irq_clear		= ata_bmdma_irq_clear,	.irq_on			= ata_irq_on,	.port_start		= ata_port_start,};static const struct ata_port_operations piix_vmw_ops = {	.set_piomode		= piix_set_piomode,	.set_dmamode		= piix_set_dmamode,	.mode_filter		= ata_pci_default_filter,	.tf_load		= ata_tf_load,	.tf_read		= ata_tf_read,	.check_status		= ata_check_status,	.exec_command		= ata_exec_command,	.dev_select		= ata_std_dev_select,	.bmdma_setup		= ata_bmdma_setup,	.bmdma_start		= ata_bmdma_start,	.bmdma_stop		= ata_bmdma_stop,	.bmdma_status		= piix_vmw_bmdma_status,	.qc_prep		= ata_qc_prep,	.qc_issue		= ata_qc_issue_prot,	.data_xfer		= ata_data_xfer,	.freeze			= ata_bmdma_freeze,	.thaw			= ata_bmdma_thaw,	.error_handler		= piix_pata_error_handler,	.post_internal_cmd	= ata_bmdma_post_internal_cmd,	.cable_detect		= ata_cable_40wire,	.irq_handler		= ata_interrupt,	.irq_clear		= ata_bmdma_irq_clear,	.irq_on			= ata_irq_on,	.port_start		= ata_port_start,};static const struct piix_map_db ich5_map_db = {	.mask = 0x7,	.port_enable = 0x3,	.map = {		/* PM   PS   SM   SS       MAP  */		{  P0,  NA,  P1,  NA }, /* 000b */		{  P1,  NA,  P0,  NA }, /* 001b */		{  RV,  RV,  RV,  RV },		{  RV,  RV,  RV,  RV },		{  P0,  P1, IDE, IDE }, /* 100b */		{  P1,  P0, IDE, IDE }, /* 101b */		{ IDE, IDE,  P0,  P1 }, /* 110b */		{ IDE, IDE,  P1,  P0 }, /* 111b */	},};static const struct piix_map_db ich6_map_db = {	.mask = 0x3,	.port_enable = 0xf,	.map = {		/* PM   PS   SM   SS       MAP */		{  P0,  P2,  P1,  P3 }, /* 00b */		{ IDE, IDE,  P1,  P3 }, /* 01b */		{  P0,  P2, IDE, IDE }, /* 10b */		{  RV,  RV,  RV,  RV },	},};static const struct piix_map_db ich6m_map_db = {	.mask = 0x3,	.port_enable = 0x5,	/* Map 01b isn't specified in the doc but some notebooks use	 * it anyway.  MAP 01b have been spotted on both ICH6M and	 * ICH7M.	 */	.map = {		/* PM   PS   SM   SS       MAP */		{  P0,  P2,  NA,  NA }, /* 00b */		{ IDE, IDE,  P1,  P3 }, /* 01b */		{  P0,  P2, IDE, IDE }, /* 10b */		{  RV,  RV,  RV,  RV },	},};static const struct piix_map_db ich8_map_db = {	.mask = 0x3,	.port_enable = 0xf,	.map = {		/* PM   PS   SM   SS       MAP */		{  P0,  P2,  P1,  P3 }, /* 00b (hardwired when in AHCI) */		{  RV,  RV,  RV,  RV },		{  P0,  P2, IDE, IDE }, /* 10b (IDE mode) */		{  RV,  RV,  RV,  RV },	},};static const struct piix_map_db ich8_2port_map_db = {	.mask = 0x3,	.port_enable = 0x3,	.map = {		/* PM   PS   SM   SS       MAP */		{  P0,  NA,  P1,  NA }, /* 00b */		{  RV,  RV,  RV,  RV }, /* 01b */		{  RV,  RV,  RV,  RV }, /* 10b */		{  RV,  RV,  RV,  RV },	},

⌨️ 快捷键说明

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