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

📄 sata_nv.c

📁 LINUX 系统内如 清大家快去下载 这2个把 破 东西 要下载 还的上传 估计来的会很少清管理 考虑从
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  sata_nv.c - NVIDIA nForce SATA * *  Copyright 2004 NVIDIA Corp.  All rights reserved. *  Copyright 2004 Andrew Chew * * *  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.* * *  No hardware documentation available outside of NVIDIA. *  This driver programs the NVIDIA SATA controller in a similar *  fashion as with other PCI IDE BMDMA controllers, with a few *  NV-specific details such as register offsets, SATA phy location, *  hotplug info, etc. * *  CK804/MCP04 controllers support an alternate programming interface *  similar to the ADMA specification (with some modifications). *  This allows the use of NCQ. Non-DMA-mapped ATA commands are still *  sent through the legacy interface. * */#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/interrupt.h>#include <linux/device.h>#include <scsi/scsi_host.h>#include <scsi/scsi_device.h>#include <linux/libata.h>#define DRV_NAME			"sata_nv"#define DRV_VERSION			"3.2-Driver Package V1.24"#define NV_ADMA_DMA_BOUNDARY		0xffffffffULenum {	NV_PORTS			= 2,	NV_PIO_MASK			= 0x1f,	NV_MWDMA_MASK			= 0x07,	NV_UDMA_MASK			= 0x7f,	NV_PORT0_SCR_REG_OFFSET		= 0x00,	NV_PORT1_SCR_REG_OFFSET		= 0x40,	/* INT_STATUS/ENABLE */	NV_INT_STATUS			= 0x10,	NV_INT_ENABLE			= 0x11,	NV_INT_STATUS_CK804		= 0x440,	NV_INT_ENABLE_CK804		= 0x441,	/* INT_STATUS/ENABLE bits */	NV_INT_DEV			= 0x01,	NV_INT_PM			= 0x02,	NV_INT_ADDED			= 0x04,	NV_INT_REMOVED			= 0x08,	NV_INT_PORT_SHIFT		= 4,	/* each port occupies 4 bits */	NV_INT_ALL			= 0x0f,	NV_INT_MASK			= NV_INT_DEV |					  NV_INT_ADDED | NV_INT_REMOVED,	/* INT_CONFIG */	NV_INT_CONFIG			= 0x12,	NV_INT_CONFIG_METHD		= 0x01, // 0 = INT, 1 = SMI	// For PCI config register 20	NV_MCP_SATA_CFG_20		= 0x50,	NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04,	NV_MCP_SATA_CFG_20_PORT0_EN	= (1 << 17),	NV_MCP_SATA_CFG_20_PORT1_EN	= (1 << 16),	NV_MCP_SATA_CFG_20_PORT0_PWB_EN	= (1 << 14),	NV_MCP_SATA_CFG_20_PORT1_PWB_EN	= (1 << 12),	NV_ADMA_MAX_CPBS		= 32,	NV_ADMA_CPB_SZ			= 128,	NV_ADMA_APRD_SZ			= 16,	NV_ADMA_SGTBL_LEN		= (1024 - NV_ADMA_CPB_SZ) /					   NV_ADMA_APRD_SZ,	NV_ADMA_SGTBL_TOTAL_LEN		= NV_ADMA_SGTBL_LEN + 5,	NV_ADMA_SGTBL_SZ                = NV_ADMA_SGTBL_LEN * NV_ADMA_APRD_SZ,	NV_ADMA_PORT_PRIV_DMA_SZ        = NV_ADMA_MAX_CPBS *					   (NV_ADMA_CPB_SZ + NV_ADMA_SGTBL_SZ),	/* BAR5 offset to ADMA general registers */	NV_ADMA_GEN			= 0x400,	NV_ADMA_GEN_CTL			= 0x00,	NV_ADMA_NOTIFIER_CLEAR		= 0x30,	/* BAR5 offset to ADMA ports */	NV_ADMA_PORT			= 0x480,	/* size of ADMA port register space  */	NV_ADMA_PORT_SIZE		= 0x100,	/* ADMA port registers */	NV_ADMA_CTL			= 0x40,	NV_ADMA_CPB_COUNT		= 0x42,	NV_ADMA_NEXT_CPB_IDX		= 0x43,	NV_ADMA_STAT			= 0x44,	NV_ADMA_CPB_BASE_LOW		= 0x48,	NV_ADMA_CPB_BASE_HIGH		= 0x4C,	NV_ADMA_APPEND			= 0x50,	NV_ADMA_NOTIFIER		= 0x68,	NV_ADMA_NOTIFIER_ERROR		= 0x6C,	/* NV_ADMA_CTL register bits */	NV_ADMA_CTL_HOTPLUG_IEN		= (1 << 0),	NV_ADMA_CTL_CHANNEL_RESET	= (1 << 5),	NV_ADMA_CTL_GO			= (1 << 7),	NV_ADMA_CTL_AIEN		= (1 << 8),	NV_ADMA_CTL_READ_NON_COHERENT	= (1 << 11),	NV_ADMA_CTL_WRITE_NON_COHERENT	= (1 << 12),	/* CPB response flag bits */	NV_CPB_RESP_DONE		= (1 << 0),	NV_CPB_RESP_ATA_ERR		= (1 << 3),	NV_CPB_RESP_CMD_ERR		= (1 << 4),	NV_CPB_RESP_CPB_ERR		= (1 << 7),	/* CPB control flag bits */	NV_CPB_CTL_CPB_VALID		= (1 << 0),	NV_CPB_CTL_QUEUE		= (1 << 1),	NV_CPB_CTL_APRD_VALID		= (1 << 2),	NV_CPB_CTL_IEN			= (1 << 3),	NV_CPB_CTL_FPDMA		= (1 << 4),	/* APRD flags */	NV_APRD_WRITE			= (1 << 1),	NV_APRD_END			= (1 << 2),	NV_APRD_CONT			= (1 << 3),	/* NV_ADMA_STAT flags */	NV_ADMA_STAT_TIMEOUT		= (1 << 0),	NV_ADMA_STAT_HOTUNPLUG		= (1 << 1),	NV_ADMA_STAT_HOTPLUG		= (1 << 2),	NV_ADMA_STAT_CPBERR		= (1 << 4),	NV_ADMA_STAT_SERROR		= (1 << 5),	NV_ADMA_STAT_CMD_COMPLETE	= (1 << 6),	NV_ADMA_STAT_IDLE		= (1 << 8),	NV_ADMA_STAT_LEGACY		= (1 << 9),	NV_ADMA_STAT_STOPPED		= (1 << 10),	NV_ADMA_STAT_DONE		= (1 << 12),	NV_ADMA_STAT_ERR		= NV_ADMA_STAT_CPBERR |	 				  NV_ADMA_STAT_TIMEOUT,	/* port flags */	NV_ADMA_PORT_REGISTER_MODE	= (1 << 0),	NV_ADMA_ATAPI_SETUP_COMPLETE	= (1 << 1),	//sgpio	// Sgpio defines	// SGPIO state defines        NV_SGPIO_STATE_RESET		= 0,	NV_SGPIO_STATE_OPERATIONAL	= 1,	NV_SGPIO_STATE_ERROR		= 2,	// SGPIO command opcodes	NV_SGPIO_CMD_RESET		= 0,	NV_SGPIO_CMD_READ_PARAMS	= 1,	NV_SGPIO_CMD_READ_DATA		= 2,	NV_SGPIO_CMD_WRITE_DATA		= 3,	// SGPIO command status defines	NV_SGPIO_CMD_OK			= 0,	NV_SGPIO_CMD_ACTIVE		= 1,	NV_SGPIO_CMD_ERR		= 2,	NV_SGPIO_UPDATE_TICK		= 90,	NV_SGPIO_MIN_UPDATE_DELTA	= 33,	NV_CNTRLR_SHARE_INIT		= 2,	NV_SGPIO_MAX_ACTIVITY_ON	= 20,	NV_SGPIO_MIN_FORCE_OFF		= 5,	NV_SGPIO_PCI_CSR_OFFSET		= 0x58,	NV_SGPIO_PCI_CB_OFFSET		= 0x5C,	NV_SGPIO_DFLT_CB_SIZE		= 256,	NV_ON                           = 1,	NV_OFF                          = 0,};/* ADMA Physical Region Descriptor - one SG segment */struct nv_adma_prd {	__le64			addr;	__le32			len;	u8			flags;	u8			packet_len;	__le16			reserved;};enum nv_adma_regbits {	CMDEND	= (1 << 15),		/* end of command list */	WNB	= (1 << 14),		/* wait-not-BSY */	IGN	= (1 << 13),		/* ignore this entry */	CS1n	= (1 << (4 + 8)),	/* std. PATA signals follow... */	DA2	= (1 << (2 + 8)),	DA1	= (1 << (1 + 8)),	DA0	= (1 << (0 + 8)),};/* ADMA Command Parameter Block   The first 5 SG segments are stored inside the Command Parameter Block itself.   If there are more than 5 segments the remainder are stored in a separate   memory area indicated by next_aprd. */struct nv_adma_cpb {	u8			resp_flags;    /* 0 */	u8			reserved1;     /* 1 */	u8			ctl_flags;     /* 2 */	/* len is length of taskfile in 64 bit words */ 	u8			len;           /* 3  */	u8			tag;           /* 4 */	u8			next_cpb_idx;  /* 5 */	__le16			reserved2;     /* 6-7 */	__le16			tf[12];        /* 8-31 */	struct nv_adma_prd	aprd[5];       /* 32-111 */	__le64			next_aprd;     /* 112-119 */	__le64			reserved3;     /* 120-127 */};struct nv_adma_port_priv {	struct nv_adma_cpb	*cpb;	dma_addr_t		cpb_dma;	struct nv_adma_prd	*aprd;	dma_addr_t		aprd_dma;	u8			flags;};#ifndef bool#define bool u8#endif#define BF_EXTRACT(v, off, bc)	\	((((u8)(v)) >> (off)) & ((1 << (bc)) - 1))#define BF_INS(v, ins, off, bc)				\	(((v) & ~((((1 << (bc)) - 1)) << (off))) |	\	(((u8)(ins)) << (off)))#define BF_EXTRACT_U32(v, off, bc)	\	((((u32)(v)) >> (off)) & ((1 << (bc)) - 1))#define BF_INS_U32(v, ins, off, bc)			\	(((v) & ~((((1 << (bc)) - 1)) << (off))) |	\	(((u32)(ins)) << (off)))#define GET_SGPIO_STATUS(v)	BF_EXTRACT(v, 0, 2)#define GET_CMD_STATUS(v)	BF_EXTRACT(v, 3, 2)#define GET_CMD(v)		BF_EXTRACT(v, 5, 3)#define SET_CMD(v, cmd)		BF_INS(v, cmd, 5, 3) #define GET_ENABLE(v)		BF_EXTRACT_U32(v, 23, 1)#define SET_ENABLE(v)		BF_INS_U32(v, 1, 23, 1)// Needs to have a u8 bit-field insert.#define GET_ACTIVITY(v)		BF_EXTRACT(v, 5, 3)#define SET_ACTIVITY(v, on_off)	BF_INS(v, on_off, 5, 3)union nv_sgpio_nvcr {	struct {		u8	init_cnt;		u8	cb_size;		u8	cbver;		u8	rsvd;	} bit;	u32	all;};union nv_sgpio_tx {	u8	tx_port[4];	u32 	all;};struct nv_sgpio_cb {	u64			scratch_space;	union nv_sgpio_nvcr	nvcr;	u32			cr0;	u32                     rsvd[4];	union nv_sgpio_tx       tx[2];};struct nv_sgpio_host_share{	spinlock_t	*plock;	unsigned long   *ptstamp;};struct nv_sgpio_host_flags{	u8	sgpio_enabled:1;	u8	need_update:1;	u8	rsvd:6;};	struct nv_host_sgpio{	struct nv_sgpio_host_flags	flags;	u8				*pcsr;	struct nv_sgpio_cb		*pcb;		struct nv_sgpio_host_share	share;	struct timer_list		sgpio_timer;};struct nv_sgpio_port_flags{	u8	last_state:1;	u8	recent_activity:1;	u8	rsvd:6;};struct nv_sgpio_led {	struct nv_sgpio_port_flags	flags;	u8				force_off;	u8      			last_cons_active;};struct nv_port_sgpio{	struct nv_sgpio_led	activity;};#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))static spinlock_t	nv_sgpio_lock;static unsigned long	nv_sgpio_tstamp;static inline void nv_sgpio_set_csr(u8 csr, unsigned long pcsr){	outb(csr, pcsr);}static inline u8 nv_sgpio_get_csr(unsigned long pcsr){	return inb(pcsr);}static inline u8 nv_sgpio_get_func(struct ata_host *host){	u8 devfn = (to_pci_dev(host->dev))->devfn;	return (PCI_FUNC(devfn));}static inline u8 nv_sgpio_tx_host_offset(struct ata_host *host){	return (nv_sgpio_get_func(host)/NV_CNTRLR_SHARE_INIT);}static inline u8 nv_sgpio_calc_tx_offset(u8 cntrlr, u8 channel){	return (sizeof(union nv_sgpio_tx) - (NV_CNTRLR_SHARE_INIT *		(cntrlr % NV_CNTRLR_SHARE_INIT)) - channel - 1);}static inline u8 nv_sgpio_tx_port_offset(struct ata_port *ap){	u8 cntrlr = nv_sgpio_get_func(ap->host);	return (nv_sgpio_calc_tx_offset(cntrlr, ap->port_no));}static inline bool nv_sgpio_capable(const struct pci_device_id *ent){	if (ent->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2)		return 1;	else		return 0;}static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);static void nv_ck804_host_stop(struct ata_host *host);static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance, struct pt_regs *pt_regs);static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance, struct pt_regs *pt_regs);static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, struct pt_regs *pt_regs);static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);static void nv_host_stop (struct ata_host *host);static int nv_port_start(struct ata_port *ap);static void nv_port_stop(struct ata_port *ap);static unsigned int nv_qc_issue(struct ata_queued_cmd *qc);static void nv_nf2_freeze(struct ata_port *ap);static void nv_nf2_thaw(struct ata_port *ap);static void nv_ck804_freeze(struct ata_port *ap);static void nv_ck804_thaw(struct ata_port *ap);static void nv_error_handler(struct ata_port *ap);static int nv_adma_slave_config(struct scsi_device *sdev);static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);static void nv_adma_qc_prep(struct ata_queued_cmd *qc);static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc);static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance, struct pt_regs *pt_regs);static void nv_adma_irq_clear(struct ata_port *ap);static int nv_adma_port_start(struct ata_port *ap);static void nv_adma_port_stop(struct ata_port *ap);static void nv_adma_error_handler(struct ata_port *ap);static void nv_adma_host_stop(struct ata_host *host);static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc);static void nv_adma_bmdma_start(struct ata_queued_cmd *qc);static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc);static u8 nv_adma_bmdma_status(struct ata_port *ap);enum nv_host_type{	GENERIC,	NFORCE2,	NFORCE3 = NFORCE2,	/* NF2 == NF3 as far as sata_nv is concerned */	CK804,	ADMA};static const struct pci_device_id nv_pci_tbl[] = {	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), NFORCE2 },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), NFORCE3 },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), NFORCE3 },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA), CK804 },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), GENERIC },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), GENERIC },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), GENERIC },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), GENERIC },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },	{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },	{ PCI_VDEVICE(NVIDIA, 0x045c), GENERIC },	{ PCI_VDEVICE(NVIDIA, 0x045d), GENERIC },	{ PCI_VDEVICE(NVIDIA, 0x045e), GENERIC },	{ PCI_VDEVICE(NVIDIA, 0x045f), GENERIC },	{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,		PCI_ANY_ID, PCI_ANY_ID,		PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,		PCI_ANY_ID, PCI_ANY_ID,		PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },	{ } /* terminate list */};struct nv_host{	unsigned long		host_flags;	struct nv_host_sgpio	host_sgpio;};struct nv_port{	struct nv_port_sgpio	port_sgpio;};// SGPIO function prototypesstatic void nv_sgpio_init(struct pci_dev *pdev, struct nv_host *phost);static void nv_sgpio_reset(u8 *pcsr);static void nv_sgpio_set_timer(struct timer_list *ptimer, 				unsigned int timeout_msec);static void nv_sgpio_timer_handler(unsigned long ptr);static void nv_sgpio_host_cleanup(struct nv_host *host);static bool nv_sgpio_update_led(struct nv_sgpio_led *led, bool *on_off);static void nv_sgpio_clear_all_leds(struct ata_port *ap);static bool nv_sgpio_send_cmd(struct nv_host *host, u8 cmd);static struct pci_driver nv_pci_driver = {	.name			= DRV_NAME,	.id_table		= nv_pci_tbl,	.probe			= nv_init_one,	.remove			= ata_pci_remove_one,};static struct scsi_host_template nv_sht = {	.eh_strategy_handler	= ata_scsi_error,	.eh_timed_out		= ata_scsi_timed_out,	.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,	.dump_sanity_check	= ata_scsi_dump_sanity_check,	.dump_quiesce		= ata_scsi_dump_quiesce,	.dump_poll		= ata_scsi_dump_poll,};static struct scsi_host_template nv_adma_sht = {	.eh_strategy_handler	= ata_scsi_error,	.eh_timed_out		= ata_scsi_timed_out,	.module			= THIS_MODULE,	.name			= DRV_NAME,	.ioctl			= ata_scsi_ioctl,	.queuecommand		= ata_scsi_queuecmd,	.can_queue		= NV_ADMA_MAX_CPBS,	.this_id		= ATA_SHT_THIS_ID,

⌨️ 快捷键说明

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