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

📄 pata_hpt3x2n.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
}static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc){	struct ata_taskfile *tf = &qc->tf;	struct ata_port *ap = qc->ap;	int flags = (long)ap->host->private_data;	if (hpt3x2n_pair_idle(ap)) {		int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE));		if ((flags & USE_DPLL) != dpll) {			if (dpll == 1)				hpt3x2n_set_clock(ap, 0x21);			else				hpt3x2n_set_clock(ap, 0x23);		}	}	return ata_qc_issue_prot(qc);}static struct scsi_host_template hpt3x2n_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,};/* *	Configuration for HPT3x2n. */static struct ata_port_operations hpt3x2n_port_ops = {	.set_piomode	= hpt3x2n_set_piomode,	.set_dmamode	= hpt3x2n_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,	.freeze		= ata_bmdma_freeze,	.thaw		= ata_bmdma_thaw,	.error_handler	= hpt3x2n_error_handler,	.post_internal_cmd = ata_bmdma_post_internal_cmd,	.cable_detect	= hpt3x2n_cable_detect,	.bmdma_setup 	= ata_bmdma_setup,	.bmdma_start 	= ata_bmdma_start,	.bmdma_stop	= hpt3x2n_bmdma_stop,	.bmdma_status 	= ata_bmdma_status,	.qc_prep 	= ata_qc_prep,	.qc_issue	= hpt3x2n_qc_issue_prot,	.data_xfer	= ata_data_xfer,	.irq_handler	= ata_interrupt,	.irq_clear	= ata_bmdma_irq_clear,	.irq_on		= ata_irq_on,	.port_start	= ata_sff_port_start,};/** *	hpt3xn_calibrate_dpll		-	Calibrate the DPLL loop *	@dev: PCI device * *	Perform a calibration cycle on the HPT3xN DPLL. Returns 1 if this *	succeeds */static int hpt3xn_calibrate_dpll(struct pci_dev *dev){	u8 reg5b;	u32 reg5c;	int tries;	for(tries = 0; tries < 0x5000; tries++) {		udelay(50);		pci_read_config_byte(dev, 0x5b, &reg5b);		if (reg5b & 0x80) {			/* See if it stays set */			for(tries = 0; tries < 0x1000; tries ++) {				pci_read_config_byte(dev, 0x5b, &reg5b);				/* Failed ? */				if ((reg5b & 0x80) == 0)					return 0;			}			/* Turn off tuning, we have the DPLL set */			pci_read_config_dword(dev, 0x5c, &reg5c);			pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100);			return 1;		}	}	/* Never went stable */	return 0;}static int hpt3x2n_pci_clock(struct pci_dev *pdev){	unsigned long freq;	u32 fcnt;	unsigned long iobase = pci_resource_start(pdev, 4);	fcnt = inl(iobase + 0x90);	/* Not PCI readable for some chips */	if ((fcnt >> 12) != 0xABCDE) {		printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n");		return 33;	/* Not BIOS set */	}	fcnt &= 0x1FF;	freq = (fcnt * 77) / 192;	/* Clamp to bands */	if (freq < 40)		return 33;	if (freq < 45)		return 40;	if (freq < 55)		return 50;	return 66;}/** *	hpt3x2n_init_one		-	Initialise an HPT37X/302 *	@dev: PCI device *	@id: Entry in match table * *	Initialise an HPT3x2n device. There are some interesting complications *	here. Firstly the chip may report 366 and be one of several variants. *	Secondly all the timings depend on the clock for the chip which we must *	detect and look up * *	This is the known chip mappings. It may be missing a couple of later *	releases. * *	Chip version		PCI		Rev	Notes *	HPT372			4 (HPT366)	5	Other driver *	HPT372N			4 (HPT366)	6	UDMA133 *	HPT372			5 (HPT372)	1	Other driver *	HPT372N			5 (HPT372)	2	UDMA133 *	HPT302			6 (HPT302)	*	Other driver *	HPT302N			6 (HPT302)	> 1	UDMA133 *	HPT371			7 (HPT371)	*	Other driver *	HPT371N			7 (HPT371)	> 1	UDMA133 *	HPT374			8 (HPT374)	*	Other driver *	HPT372N			9 (HPT372N)	*	UDMA133 * *	(1) UDMA133 support depends on the bus clock * *	To pin down		HPT371N */static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id){	/* HPT372N and friends - UDMA133 */	static const struct ata_port_info info = {		.sht = &hpt3x2n_sht,		.flags = ATA_FLAG_SLAVE_POSS,		.pio_mask = 0x1f,		.mwdma_mask = 0x07,		.udma_mask = ATA_UDMA6,		.port_ops = &hpt3x2n_port_ops	};	struct ata_port_info port = info;	const struct ata_port_info *ppi[] = { &port, NULL };	u8 irqmask;	u32 class_rev;	unsigned int pci_mhz;	unsigned int f_low, f_high;	int adjust;	unsigned long iobase = pci_resource_start(dev, 4);	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);	class_rev &= 0xFF;	switch(dev->device) {		case PCI_DEVICE_ID_TTI_HPT366:			if (class_rev < 6)				return -ENODEV;			break;		case PCI_DEVICE_ID_TTI_HPT371:			if (class_rev < 2)				return -ENODEV;			/* 371N if rev > 1 */			break;		case PCI_DEVICE_ID_TTI_HPT372:			/* 372N if rev >= 2*/			if (class_rev < 2)				return -ENODEV;			break;		case PCI_DEVICE_ID_TTI_HPT302:			if (class_rev < 2)				return -ENODEV;			break;		case PCI_DEVICE_ID_TTI_HPT372N:			break;		default:			printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device);			return -ENODEV;	}	/* Ok so this is a chip we support */	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);	pci_read_config_byte(dev, 0x5A, &irqmask);	irqmask &= ~0x10;	pci_write_config_byte(dev, 0x5a, irqmask);	/*	 * HPT371 chips physically have only one channel, the secondary one,	 * but the primary channel registers do exist!  Go figure...	 * So,  we manually disable the non-existing channel here	 * (if the BIOS hasn't done this already).	 */	if (dev->device == PCI_DEVICE_ID_TTI_HPT371) {		u8 mcr1;		pci_read_config_byte(dev, 0x50, &mcr1);		mcr1 &= ~0x04;		pci_write_config_byte(dev, 0x50, mcr1);	}	/* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or	   50 for UDMA100. Right now we always use 66 */	pci_mhz = hpt3x2n_pci_clock(dev);	f_low = (pci_mhz * 48) / 66;	/* PCI Mhz for 66Mhz DPLL */	f_high = f_low + 2;		/* Tolerance */	pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100);	/* PLL clock */	pci_write_config_byte(dev, 0x5B, 0x21);	/* Unlike the 37x we don't try jiggling the frequency */	for(adjust = 0; adjust < 8; adjust++) {		if (hpt3xn_calibrate_dpll(dev))			break;		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);	}	if (adjust == 8) {		printk(KERN_ERR "pata_hpt3x2n: DPLL did not stabilize!\n");		return -ENODEV;	}	printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using 66MHz DPLL.\n",	       pci_mhz);	/* Set our private data up. We only need a few flags so we use	   it directly */	port.private_data = NULL;	if (pci_mhz > 60) {		port.private_data = (void *)PCI66;		/*		 * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in		 * the MISC. register to stretch the UltraDMA Tss timing.		 * NOTE: This register is only writeable via I/O space.		 */		if (dev->device == PCI_DEVICE_ID_TTI_HPT371)			outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c);	}	/* Now kick off ATA set up */	return ata_pci_init_one(dev, ppi);}static const struct pci_device_id hpt3x2n[] = {	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), },	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), },	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), },	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), },	{ },};static struct pci_driver hpt3x2n_pci_driver = {	.name 		= DRV_NAME,	.id_table	= hpt3x2n,	.probe 		= hpt3x2n_init_one,	.remove		= ata_pci_remove_one};static int __init hpt3x2n_init(void){	return pci_register_driver(&hpt3x2n_pci_driver);}static void __exit hpt3x2n_exit(void){	pci_unregister_driver(&hpt3x2n_pci_driver);}MODULE_AUTHOR("Alan Cox");MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3x2n/30x");MODULE_LICENSE("GPL");MODULE_DEVICE_TABLE(pci, hpt3x2n);MODULE_VERSION(DRV_VERSION);module_init(hpt3x2n_init);module_exit(hpt3x2n_exit);

⌨️ 快捷键说明

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