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

📄 sata_nv.c

📁 LINUX 系统内如 清大家快去下载 这2个把 破 东西 要下载 还的上传 估计来的会很少清管理 考虑从
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  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. * */#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 <linux/libata.h>#define DRV_NAME			"sata_nv"#define DRV_VERSION			"2.1-Driver Package V1.24"enum {	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,};//sgpio// Sgpio defines// SGPIO state defines#define NV_SGPIO_STATE_RESET		0#define NV_SGPIO_STATE_OPERATIONAL	1#define NV_SGPIO_STATE_ERROR		2// SGPIO command opcodes#define NV_SGPIO_CMD_RESET		0#define NV_SGPIO_CMD_READ_PARAMS	1#define NV_SGPIO_CMD_READ_DATA		2#define NV_SGPIO_CMD_WRITE_DATA		3// SGPIO command status defines#define NV_SGPIO_CMD_OK			0#define NV_SGPIO_CMD_ACTIVE		1#define NV_SGPIO_CMD_ERR		2#define NV_SGPIO_UPDATE_TICK		90#define NV_SGPIO_MIN_UPDATE_DELTA	33#define NV_CNTRLR_SHARE_INIT		2#define NV_SGPIO_MAX_ACTIVITY_ON	20#define NV_SGPIO_MIN_FORCE_OFF		5#define NV_SGPIO_PCI_CSR_OFFSET		0x58#define NV_SGPIO_PCI_CB_OFFSET		0x5C#define NV_SGPIO_DFLT_CB_SIZE		256#define NV_ON 1#define NV_OFF 0#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;};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 *regs);static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,				    struct pt_regs *regs);static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,				      struct pt_regs *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);enum nv_host_type{	GENERIC,	NFORCE2,	NFORCE3 = NFORCE2,	/* NF2 == NF3 as far as sata_nv is concerned */	CK804};static const struct pci_device_id nv_pci_tbl[] = {	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE2 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, 0x045c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, 0x045d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, 0x045e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },	{ PCI_VENDOR_ID_NVIDIA, 0x045f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 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 },	{ 0, } /* 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 = {	.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 nv_generic_ops = {	.port_disable		= ata_port_disable,	.tf_load		= ata_tf_load,	.tf_read		= ata_tf_read,	.exec_command		= ata_exec_command,	.check_status		= ata_check_status,	.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		= nv_qc_issue,	.freeze			= ata_bmdma_freeze,	.thaw			= ata_bmdma_thaw,	.error_handler		= nv_error_handler,	.post_internal_cmd	= ata_bmdma_post_internal_cmd,	.data_xfer		= ata_pio_data_xfer,	.irq_handler		= nv_generic_interrupt,	.irq_clear		= ata_bmdma_irq_clear,	.scr_read		= nv_scr_read,	.scr_write		= nv_scr_write,	.port_start		= nv_port_start,	.port_stop		= nv_port_stop,	.host_stop		= nv_host_stop,};static const struct ata_port_operations nv_nf2_ops = {	.port_disable		= ata_port_disable,	.tf_load		= ata_tf_load,	.tf_read		= ata_tf_read,	.exec_command		= ata_exec_command,	.check_status		= ata_check_status,	.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		= nv_qc_issue,	.freeze			= nv_nf2_freeze,	.thaw			= nv_nf2_thaw,	.error_handler		= nv_error_handler,	.post_internal_cmd	= ata_bmdma_post_internal_cmd,	.data_xfer		= ata_pio_data_xfer,	.irq_handler		= nv_nf2_interrupt,	.irq_clear		= ata_bmdma_irq_clear,	.scr_read		= nv_scr_read,	.scr_write		= nv_scr_write,	.port_start		= nv_port_start,	.port_stop		= nv_port_stop,	.host_stop		= nv_host_stop,};static const struct ata_port_operations nv_ck804_ops = {	.port_disable		= ata_port_disable,	.tf_load		= ata_tf_load,	.tf_read		= ata_tf_read,	.exec_command		= ata_exec_command,	.check_status		= ata_check_status,	.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		= nv_qc_issue,	.freeze			= nv_ck804_freeze,	.thaw			= nv_ck804_thaw,	.error_handler		= nv_error_handler,	.post_internal_cmd	= ata_bmdma_post_internal_cmd,	.data_xfer		= ata_pio_data_xfer,	.irq_handler		= nv_ck804_interrupt,	.irq_clear		= ata_bmdma_irq_clear,	.scr_read		= nv_scr_read,	.scr_write		= nv_scr_write,	.port_start		= nv_port_start,	.port_stop		= nv_port_stop,	.host_stop		= nv_ck804_host_stop,};static struct ata_port_info nv_port_info[] = {	/* generic */	{		.sht		= &nv_sht,		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,		.pio_mask	= NV_PIO_MASK,		.mwdma_mask	= NV_MWDMA_MASK,		.udma_mask	= NV_UDMA_MASK,		.port_ops	= &nv_generic_ops,	},	/* nforce2/3 */	{		.sht		= &nv_sht,		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,		.pio_mask	= NV_PIO_MASK,		.mwdma_mask	= NV_MWDMA_MASK,		.udma_mask	= NV_UDMA_MASK,		.port_ops	= &nv_nf2_ops,	},	/* ck804 */	{		.sht		= &nv_sht,		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,		.pio_mask	= NV_PIO_MASK,		.mwdma_mask	= NV_MWDMA_MASK,		.udma_mask	= NV_UDMA_MASK,		.port_ops	= &nv_ck804_ops,	},};MODULE_AUTHOR("NVIDIA");MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");MODULE_LICENSE("GPL");MODULE_DEVICE_TABLE(pci, nv_pci_tbl);MODULE_VERSION(DRV_VERSION);static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,					struct pt_regs *regs){	struct ata_host *host = dev_instance;	unsigned int i;	unsigned int handled = 0;	unsigned long flags;	spin_lock_irqsave(&host->lock, flags);	for (i = 0; i < host->n_ports; i++) {		struct ata_port *ap;		ap = host->ports[i];		if (ap &&		    !(ap->flags & ATA_FLAG_DISABLED)) {			struct ata_queued_cmd *qc;			qc = ata_qc_from_tag(ap, ap->active_tag);			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))				handled += ata_host_intr(ap, qc);			else				// No request pending?  Clear interrupt status				// anyway, in case there's one pending.				ap->ops->check_status(ap);		}	}	spin_unlock_irqrestore(&host->lock, flags);	return IRQ_RETVAL(handled);}static int nv_host_intr(struct ata_port *ap, u8 irq_stat){	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);	int handled;	/* freeze if hotplugged */	if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {		ata_port_freeze(ap);		return 1;	}	/* bail out if not our interrupt */	if (!(irq_stat & NV_INT_DEV))		return 0;	/* DEV interrupt w/ no active qc? */	if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {		ata_check_status(ap);		return 1;	}	/* handle interrupt */	handled = ata_host_intr(ap, qc);	if (unlikely(!handled)) {		/* spurious, clear it */		ata_check_status(ap);	}	return 1;}static irqreturn_t nv_do_interrupt(struct ata_host *host, u8 irq_stat){	int i, handled = 0;	for (i = 0; i < host->n_ports; i++) {		struct ata_port *ap = host->ports[i];

⌨️ 快捷键说明

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