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

📄 sata_nv.c

📁 LINUX 系统内如 清大家快去下载 这2个把 破 东西 要下载 还的上传 估计来的会很少清管理 考虑从
💻 C
📖 第 1 页 / 共 4 页
字号:
				struct nv_adma_cpb *cpb = &pp->cpb[i];				if( (ata_tag_valid(ap->active_tag) && i == ap->active_tag) ||				    ap->sactive & (1 << i) )					ata_port_printk(ap, KERN_ERR,						"CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",						i, cpb->ctl_flags, cpb->resp_flags);			}		}		/* Push us back into port register mode for error handling. */		nv_adma_register_mode(ap);		/* Mark all of the CPBs as invalid to prevent them from being executed */		for( i=0;i<NV_ADMA_MAX_CPBS;i++)			pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID;		/* clear CPB fetch count */		writew(0, mmio + NV_ADMA_CPB_COUNT);		/* Reset channel */		tmp = readw(mmio + NV_ADMA_CTL);		writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);		readw( mmio + NV_ADMA_CTL );	/* flush posted write */		udelay(1);		writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);		readw( mmio + NV_ADMA_CTL );	/* flush posted write */	}	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,			   nv_hardreset, ata_std_postreset);}static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent){	static int printed_version = 0;	struct nv_host *host;	struct ata_port_info *ppi[2];	struct ata_probe_ent *probe_ent;	int rc;	u32 bar;	void __iomem *base;	unsigned long type = ent->driver_data;	int mask_set = 0;        // Make sure this is a SATA controller by counting the number of bars        // (NVIDIA SATA controllers will always have six bars).  Otherwise,        // it's an IDE controller and we ignore it.	for (bar=0; bar<6; bar++)		if (pci_resource_start(pdev, bar) == 0)			return -ENODEV;	if (!printed_version++)		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");	rc = pcim_enable_device(pdev);	if (rc)		return rc;	rc = pci_request_regions(pdev, DRV_NAME);	if (rc) {		pcim_pin_device(pdev);		return rc;	}	if(type >= CK804 && adma_enabled) {		dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");		type = ADMA;		if(!pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&		   !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))			mask_set = 1;	}	if(!mask_set) {		rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);		if (rc)			return rc;		rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);		if (rc)			return rc;	}	rc = -ENOMEM;	ppi[0] = ppi[1] = &nv_port_info[type];	probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);	if (!probe_ent)		return -ENOMEM;	if (!pcim_iomap(pdev, NV_MMIO_BAR, 0))		return -EIO;	probe_ent->iomap = pcim_iomap_table(pdev);	//host = kmalloc(sizeof(struct nv_host), GFP_KERNEL);	host = devm_kzalloc(&pdev->dev,sizeof(struct nv_host), GFP_KERNEL);	if (!host)		return -ENOMEM;	memset(host, 0, sizeof(struct nv_host));	probe_ent->private_data = host;	host->type = type;	base = probe_ent->iomap[NV_MMIO_BAR];	probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;	probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;	/* enable SATA space for CK804 */	if (type >= CK804) {		u8 regval;		pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);		regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;		pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);	}	pci_set_master(pdev);	if (type == ADMA) {		rc = nv_adma_host_init(probe_ent);		if (rc)			return rc;	}	rc = ata_device_add(probe_ent);	if (rc != NV_PORTS)		return -ENODEV;	if (nv_sgpio_capable(ent))		nv_sgpio_init(pdev, host);	devm_kfree(&pdev->dev, probe_ent);	return 0;}static void nv_remove_one (struct pci_dev *pdev){	struct ata_host *host = dev_get_drvdata(&pdev->dev);	struct nv_host *hpriv = host->private_data;	//devm_kfree(&pdev->dev,hpriv);	ata_pci_remove_one(pdev);	//kfree(hpriv);}#ifdef CONFIG_PMstatic int nv_pci_device_resume(struct pci_dev *pdev){	struct ata_host *host = dev_get_drvdata(&pdev->dev);	struct nv_host *hpriv = host->private_data;	int rc;	rc = ata_pci_device_do_resume(pdev);	if(rc)		return rc;	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {		if(hpriv->type >= CK804) {			u8 regval;			pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);			regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;			pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);		}		if(hpriv->type == ADMA) {			u32 tmp32;			struct nv_adma_port_priv *pp;			/* enable/disable ADMA on the ports appropriately */			pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);			pp = host->ports[0]->private_data;			if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)				tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |				 	   NV_MCP_SATA_CFG_20_PORT0_PWB_EN);			else				tmp32 |=  (NV_MCP_SATA_CFG_20_PORT0_EN |				 	   NV_MCP_SATA_CFG_20_PORT0_PWB_EN);			pp = host->ports[1]->private_data;			if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)				tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN |				 	   NV_MCP_SATA_CFG_20_PORT1_PWB_EN);			else				tmp32 |=  (NV_MCP_SATA_CFG_20_PORT1_EN |				 	   NV_MCP_SATA_CFG_20_PORT1_PWB_EN);			pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);		}	}	ata_host_resume(host);	return 0;}#endifstatic int nv_port_start(struct ata_port *ap){	int stat;	struct nv_port *port;	stat = ata_port_start(ap);	if (stat) {		return stat;	}	port = kmalloc(sizeof(struct nv_port), GFP_KERNEL);	if (!port) 		goto err_out_no_free;	memset(port, 0, sizeof(struct nv_port));	ap->private_data = port;	return 0;err_out_no_free:	return 1;}static void nv_port_stop(struct ata_port *ap){	nv_sgpio_clear_all_leds(ap);	if (ap->private_data) {		kfree(ap->private_data);		ap->private_data = NULL;	}}static unsigned int nv_qc_issue(struct ata_queued_cmd *qc){	struct nv_port *port = qc->ap->private_data;	if (port) 		port->port_sgpio.activity.flags.recent_activity = 1;	return (ata_qc_issue_prot(qc));}static void nv_ck804_host_stop(struct ata_host *host){	struct nv_host *nv_host = host->private_data;	struct pci_dev *pdev = to_pci_dev(host->dev);	u8 regval;	/* disable SATA space for CK804 */	nv_sgpio_host_cleanup(nv_host);	pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);	regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;	pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);}static void nv_adma_host_stop(struct ata_host *host){	struct pci_dev *pdev = to_pci_dev(host->dev);	u32 tmp32;	/* disable ADMA on the ports */	pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);	tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |		   NV_MCP_SATA_CFG_20_PORT0_PWB_EN |		   NV_MCP_SATA_CFG_20_PORT1_EN |		   NV_MCP_SATA_CFG_20_PORT1_PWB_EN);	pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);	nv_ck804_host_stop(host);}static void nv_host_stop (struct ata_host *host){	struct nv_host *nv_host = host->private_data;	nv_sgpio_host_cleanup(nv_host);	//kfree(nv_host);}static void nv_sgpio_init(struct pci_dev *pdev, struct nv_host *phost){	u16 csr_add; 	u32 cb_add, temp32;	struct device *dev = pci_dev_to_dev(pdev);	struct ata_host *host = dev_get_drvdata(dev);	u8 pro=0;		pci_read_config_word(pdev, NV_SGPIO_PCI_CSR_OFFSET, &csr_add);	pci_read_config_dword(pdev, NV_SGPIO_PCI_CB_OFFSET, &cb_add);	pci_read_config_byte(pdev, 0xA4, &pro);		if (csr_add == 0 || cb_add == 0)		return;		if (!(pro&0x40))		return;				temp32 = csr_add;	phost->host_sgpio.pcsr = (void *)temp32;	phost->host_sgpio.pcb = phys_to_virt(cb_add);	if (phost->host_sgpio.pcb->nvcr.bit.init_cnt!=0x2 || phost->host_sgpio.pcb->nvcr.bit.cbver!=0x0)		return;			if (temp32 <=0x200 || temp32 >=0xFFFE )		return;			if (cb_add<=0x80000 || cb_add>=0x9FC00)		return;		if (phost->host_sgpio.pcb->scratch_space == 0) {		spin_lock_init(&nv_sgpio_lock);		phost->host_sgpio.share.plock = &nv_sgpio_lock;		phost->host_sgpio.share.ptstamp = &nv_sgpio_tstamp;		phost->host_sgpio.pcb->scratch_space = 			(unsigned long)&phost->host_sgpio.share;		spin_lock(phost->host_sgpio.share.plock);		nv_sgpio_reset(phost->host_sgpio.pcsr);		phost->host_sgpio.pcb->cr0 = 			SET_ENABLE(phost->host_sgpio.pcb->cr0);		spin_unlock(phost->host_sgpio.share.plock);	}	phost->host_sgpio.share = 		*(struct nv_sgpio_host_share *)(unsigned long)		phost->host_sgpio.pcb->scratch_space;	phost->host_sgpio.flags.sgpio_enabled = 1;	init_timer(&phost->host_sgpio.sgpio_timer);	phost->host_sgpio.sgpio_timer.data = (unsigned long)host;	nv_sgpio_set_timer(&phost->host_sgpio.sgpio_timer, 				NV_SGPIO_UPDATE_TICK);}static void nv_sgpio_set_timer(struct timer_list *ptimer, unsigned int timeout_msec){	if (!ptimer)		return;	ptimer->function = nv_sgpio_timer_handler;	ptimer->expires = msecs_to_jiffies(timeout_msec) + jiffies;	add_timer(ptimer);}static void nv_sgpio_timer_handler(unsigned long context){	struct ata_host *host_set = (struct ata_host *)context;	struct nv_host *host;	u8 count, host_offset, port_offset;	union nv_sgpio_tx tx;	bool on_off;	unsigned long mask = 0xFFFF;	struct nv_port *port;	if (!host_set)		goto err_out;	else 		host = (struct nv_host *)host_set->private_data;	if (!host->host_sgpio.flags.sgpio_enabled)		goto err_out;	host_offset = nv_sgpio_tx_host_offset(host_set);	spin_lock(host->host_sgpio.share.plock);	tx = host->host_sgpio.pcb->tx[host_offset];	spin_unlock(host->host_sgpio.share.plock);	for (count = 0; count < host_set->n_ports; count++) {		struct ata_port *ap; 		ap = host_set->ports[count];			if (!(ap && !(ap->flags & ATA_FLAG_DISABLED)))			continue;		port = (struct nv_port *)ap->private_data;		if (!port)			continue;            				port_offset = nv_sgpio_tx_port_offset(ap);		on_off = GET_ACTIVITY(tx.tx_port[port_offset]);		if (nv_sgpio_update_led(&port->port_sgpio.activity, &on_off)) {			tx.tx_port[port_offset] = 				SET_ACTIVITY(tx.tx_port[port_offset], on_off);			host->host_sgpio.flags.need_update = 1;	       }	}	if (host->host_sgpio.flags.need_update) {		spin_lock(host->host_sgpio.share.plock);    		if (nv_sgpio_get_func(host_set) 			% NV_CNTRLR_SHARE_INIT == 0) {			host->host_sgpio.pcb->tx[host_offset].all &= mask;			mask = mask << 16;			tx.all &= mask;		} else {			tx.all &= mask;			mask = mask << 16;			host->host_sgpio.pcb->tx[host_offset].all &= mask;		}		host->host_sgpio.pcb->tx[host_offset].all |= tx.all;		spin_unlock(host->host_sgpio.share.plock);      		if (nv_sgpio_send_cmd(host, NV_SGPIO_CMD_WRITE_DATA)) { 			host->host_sgpio.flags.need_update = 0;			return;		}	} else {		nv_sgpio_set_timer(&host->host_sgpio.sgpio_timer, 				NV_SGPIO_UPDATE_TICK);	}err_out:	return;}static bool nv_sgpio_send_cmd(struct nv_host *host, u8 cmd){	u8 csr;	unsigned long *ptstamp;	spin_lock(host->host_sgpio.share.plock);    	ptstamp = host->host_sgpio.share.ptstamp;	if (jiffies_to_msecs(jiffies - *ptstamp) >= NV_SGPIO_MIN_UPDATE_DELTA) {		csr = nv_sgpio_get_csr((unsigned long)host->host_sgpio.pcsr);		if ((GET_SGPIO_STATUS(csr) != NV_SGPIO_STATE_OPERATIONAL) ||			(GET_CMD_STATUS(csr) == NV_SGPIO_CMD_ACTIVE)) {					} else {			host->host_sgpio.pcb->cr0 = 				SET_ENABLE(host->host_sgpio.pcb->cr0);			csr = 0;			csr = SET_CMD(csr, cmd);			nv_sgpio_set_csr(csr, 				(unsigned long)host->host_sgpio.pcsr);			*ptstamp = jiffies;		}		spin_unlock(host->host_sgpio.share.plock);		nv_sgpio_set_timer(&host->host_sgpio.sgpio_timer, 			NV_SGPIO_UPDATE_TICK);		return 1;	} else {		spin_unlock(host->host_sgpio.share.plock);		nv_sgpio_set_timer(&host->host_sgpio.sgpio_timer, 				(NV_SGPIO_MIN_UPDATE_DELTA - 				jiffies_to_msecs(jiffies - *ptstamp)));		return 0;	}}static bool nv_sgpio_update_led(struct nv_sgpio_led *led, bool *on_off){	bool need_update = 0;	if (led->force_off > 0) {		led->force_off--;	} else if (led->flags.recent_activity ^ led->flags.last_state) {		*on_off = led->flags.recent_activity;		led->flags.last_state = led->flags.recent_activity;		need_update = 1;	} else if ((led->flags.recent_activity & led->flags.last_state) &&		(led->last_cons_active >= NV_SGPIO_MAX_ACTIVITY_ON)) {		*on_off = NV_OFF;		led->flags.last_state = NV_OFF;		led->force_off = NV_SGPIO_MIN_FORCE_OFF;		need_update = 1;	}	if (*on_off) 		led->last_cons_active++;		else		led->last_cons_active = 0;	led->flags.recent_activity = 0;	return need_update;}static void nv_sgpio_reset(u8  *pcsr){	u8 csr;	csr = nv_sgpio_get_csr((unsigned long)pcsr);	if (GET_SGPIO_STATUS(csr) == NV_SGPIO_STATE_RESET) {		csr = 0;		csr = SET_CMD(csr, NV_SGPIO_CMD_RESET);		nv_sgpio_set_csr(csr, (unsigned long)pcsr);	}	csr = 0;	csr = SET_CMD(csr, NV_SGPIO_CMD_READ_PARAMS);	nv_sgpio_set_csr(csr, (unsigned long)pcsr);}static void nv_sgpio_host_cleanup(struct nv_host *host){	u8 csr;	if (!host)		return;	if (host->host_sgpio.flags.sgpio_enabled) {		spin_lock(host->host_sgpio.share.plock);		host->host_sgpio.pcb->cr0 = SET_ENABLE(host->host_sgpio.pcb->cr0);		csr = 0;		csr = SET_CMD(csr, NV_SGPIO_CMD_WRITE_DATA);		nv_sgpio_set_csr(csr,(unsigned long)host->host_sgpio.pcsr);		spin_unlock(host->host_sgpio.share.plock);		if (timer_pending(&host->host_sgpio.sgpio_timer))			del_timer(&host->host_sgpio.sgpio_timer);		host->host_sgpio.flags.sgpio_enabled = 0;		host->host_sgpio.pcb->scratch_space = 0;	}}static void nv_sgpio_clear_all_leds(struct ata_port *ap){	struct nv_port *port = ap->private_data;	struct nv_host *host;	u8 host_offset, port_offset;	if (!port || !ap->host)		return;	if (!ap->host->private_data)		return;	host = ap->host->private_data;	if (!host->host_sgpio.flags.sgpio_enabled)		return;	host_offset = nv_sgpio_tx_host_offset(ap->host);	port_offset = nv_sgpio_tx_port_offset(ap);	spin_lock(host->host_sgpio.share.plock);	host->host_sgpio.pcb->tx[host_offset].tx_port[port_offset] = 0;	host->host_sgpio.flags.need_update = 1;	spin_unlock(host->host_sgpio.share.plock);}static int __init nv_init(void){	return pci_register_driver(&nv_pci_driver);}static void __exit nv_exit(void){	pci_unregister_driver(&nv_pci_driver);}module_init(nv_init);module_exit(nv_exit);module_param_named(adma, adma_enabled, bool, 0444);MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");

⌨️ 快捷键说明

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