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

📄 pata_hpt37x.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 *	@qc: ATA command * *	Clean up after the HPT372 and later DMA engine */static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc){	struct ata_port *ap = qc->ap;	struct pci_dev *pdev = to_pci_dev(ap->host->dev);	int mscreg = 0x50 + 4 * ap->port_no;	u8 bwsr_stat, msc_stat;	pci_read_config_byte(pdev, 0x6A, &bwsr_stat);	pci_read_config_byte(pdev, mscreg, &msc_stat);	if (bwsr_stat & (1 << ap->port_no))		pci_write_config_byte(pdev, mscreg, msc_stat | 0x30);	ata_bmdma_stop(qc);}static struct scsi_host_template hpt37x_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 HPT370 */static struct ata_port_operations hpt370_port_ops = {	.set_piomode	= hpt370_set_piomode,	.set_dmamode	= hpt370_set_dmamode,	.mode_filter	= hpt370_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	= hpt37x_error_handler,	.post_internal_cmd = ata_bmdma_post_internal_cmd,	.bmdma_setup 	= ata_bmdma_setup,	.bmdma_start 	= hpt370_bmdma_start,	.bmdma_stop	= hpt370_bmdma_stop,	.bmdma_status 	= ata_bmdma_status,	.qc_prep 	= ata_qc_prep,	.qc_issue	= ata_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,};/* *	Configuration for HPT370A. Close to 370 but less filters */static struct ata_port_operations hpt370a_port_ops = {	.set_piomode	= hpt370_set_piomode,	.set_dmamode	= hpt370_set_dmamode,	.mode_filter	= hpt370a_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	= hpt37x_error_handler,	.post_internal_cmd = ata_bmdma_post_internal_cmd,	.bmdma_setup 	= ata_bmdma_setup,	.bmdma_start 	= hpt370_bmdma_start,	.bmdma_stop	= hpt370_bmdma_stop,	.bmdma_status 	= ata_bmdma_status,	.qc_prep 	= ata_qc_prep,	.qc_issue	= ata_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,};/* *	Configuration for HPT372, HPT371, HPT302. Slightly different PIO *	and DMA mode setting functionality. */static struct ata_port_operations hpt372_port_ops = {	.set_piomode	= hpt372_set_piomode,	.set_dmamode	= hpt372_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	= hpt37x_error_handler,	.post_internal_cmd = ata_bmdma_post_internal_cmd,	.bmdma_setup 	= ata_bmdma_setup,	.bmdma_start 	= ata_bmdma_start,	.bmdma_stop	= hpt37x_bmdma_stop,	.bmdma_status 	= ata_bmdma_status,	.qc_prep 	= ata_qc_prep,	.qc_issue	= ata_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,};/* *	Configuration for HPT374. Mode setting works like 372 and friends *	but we have a different cable detection procedure. */static struct ata_port_operations hpt374_port_ops = {	.set_piomode	= hpt372_set_piomode,	.set_dmamode	= hpt372_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	= hpt374_error_handler,	.post_internal_cmd = ata_bmdma_post_internal_cmd,	.bmdma_setup 	= ata_bmdma_setup,	.bmdma_start 	= ata_bmdma_start,	.bmdma_stop	= hpt37x_bmdma_stop,	.bmdma_status 	= ata_bmdma_status,	.qc_prep 	= ata_qc_prep,	.qc_issue	= ata_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,};/** *	htp37x_clock_slot	-	Turn timing to PC clock entry *	@freq: Reported frequency timing *	@base: Base timing * *	Turn the timing data intoa clock slot (0 for 33, 1 for 40, 2 for 50 *	and 3 for 66Mhz) */static int hpt37x_clock_slot(unsigned int freq, unsigned int base){	unsigned int f = (base * freq) / 192;	/* Mhz */	if (f < 40)		return 0;	/* 33Mhz slot */	if (f < 45)		return 1;	/* 40Mhz slot */	if (f < 55)		return 2;	/* 50Mhz slot */	return 3;		/* 60Mhz slot */}/** *	hpt37x_calibrate_dpll		-	Calibrate the DPLL loop *	@dev: PCI device * *	Perform a calibration cycle on the HPT37x DPLL. Returns 1 if this *	succeeds */static int hpt37x_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 u32 hpt374_read_freq(struct pci_dev *pdev){	u32 freq;	unsigned long io_base = pci_resource_start(pdev, 4);	if (PCI_FUNC(pdev->devfn) & 1) {		struct pci_dev *pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);		/* Someone hot plugged the controller on us ? */		if (pdev_0 == NULL)			return 0;		io_base = pci_resource_start(pdev_0, 4);		freq = inl(io_base + 0x90);		pci_dev_put(pdev_0);	}	else		freq = inl(io_base + 0x90);	return freq;}/** *	hpt37x_init_one		-	Initialise an HPT37X/302 *	@dev: PCI device *	@id: Entry in match table * *	Initialise an HPT37x 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 *	HPT366			4 (HPT366)	0	Other driver *	HPT366			4 (HPT366)	1	Other driver *	HPT368			4 (HPT366)	2	Other driver *	HPT370			4 (HPT366)	3	UDMA100 *	HPT370A			4 (HPT366)	4	UDMA100 *	HPT372			4 (HPT366)	5	UDMA133 (1) *	HPT372N			4 (HPT366)	6	Other driver *	HPT372A			5 (HPT372)	1	UDMA133 (1) *	HPT372N			5 (HPT372)	2	Other driver *	HPT302			6 (HPT302)	1	UDMA133 *	HPT302N			6 (HPT302)	2	Other driver *	HPT371			7 (HPT371)	*	UDMA133 *	HPT374			8 (HPT374)	*	UDMA133 4 channel *	HPT372N			9 (HPT372N)	*	Other driver * *	(1) UDMA133 support depends on the bus clock */static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id){	/* HPT370 - UDMA100 */	static const struct ata_port_info info_hpt370 = {		.sht = &hpt37x_sht,		.flags = ATA_FLAG_SLAVE_POSS,		.pio_mask = 0x1f,		.mwdma_mask = 0x07,		.udma_mask = ATA_UDMA5,		.port_ops = &hpt370_port_ops	};	/* HPT370A - UDMA100 */	static const struct ata_port_info info_hpt370a = {		.sht = &hpt37x_sht,		.flags = ATA_FLAG_SLAVE_POSS,		.pio_mask = 0x1f,		.mwdma_mask = 0x07,		.udma_mask = ATA_UDMA5,		.port_ops = &hpt370a_port_ops	};	/* HPT370 - UDMA100 */	static const struct ata_port_info info_hpt370_33 = {		.sht = &hpt37x_sht,		.flags = ATA_FLAG_SLAVE_POSS,		.pio_mask = 0x1f,		.mwdma_mask = 0x07,		.udma_mask = ATA_UDMA5,		.port_ops = &hpt370_port_ops	};	/* HPT370A - UDMA100 */	static const struct ata_port_info info_hpt370a_33 = {		.sht = &hpt37x_sht,		.flags = ATA_FLAG_SLAVE_POSS,		.pio_mask = 0x1f,		.mwdma_mask = 0x07,		.udma_mask = ATA_UDMA5,		.port_ops = &hpt370a_port_ops	};	/* HPT371, 372 and friends - UDMA133 */	static const struct ata_port_info info_hpt372 = {		.sht = &hpt37x_sht,		.flags = ATA_FLAG_SLAVE_POSS,		.pio_mask = 0x1f,		.mwdma_mask = 0x07,		.udma_mask = ATA_UDMA6,		.port_ops = &hpt372_port_ops	};	/* HPT374 - UDMA100 */	static const struct ata_port_info info_hpt374 = {		.sht = &hpt37x_sht,		.flags = ATA_FLAG_SLAVE_POSS,		.pio_mask = 0x1f,		.mwdma_mask = 0x07,		.udma_mask = ATA_UDMA5,		.port_ops = &hpt374_port_ops	};	static const int MHz[4] = { 33, 40, 50, 66 };	const struct ata_port_info *port;	void *private_data = NULL;	struct ata_port_info port_info;	const struct ata_port_info *ppi[] = { &port_info, NULL };	u8 irqmask;	u32 class_rev;	u8 mcr1;	u32 freq;	int prefer_dpll = 1;	unsigned long iobase = pci_resource_start(dev, 4);	const struct hpt_chip *chip_table;	int clock_slot;	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);	class_rev &= 0xFF;	if (dev->device == PCI_DEVICE_ID_TTI_HPT366) {		/* May be a later chip in disguise. Check */		/* Older chips are in the HPT366 driver. Ignore them */		if (class_rev < 3)			return -ENODEV;		/* N series chips have their own driver. Ignore */		if (class_rev == 6)			return -ENODEV;		switch(class_rev) {			case 3:				port = &info_hpt370;				chip_table = &hpt370;				prefer_dpll = 0;				break;			case 4:				port = &info_hpt370a;				chip_table = &hpt370a;				prefer_dpll = 0;				break;			case 5:				port = &info_hpt372;				chip_table = &hpt372;				break;			default:				printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype please report (%d).\n", class_rev);				return -ENODEV;		}	} else {		switch(dev->device) {			case PCI_DEVICE_ID_TTI_HPT372:				/* 372N if rev >= 2*/				if (class_rev >= 2)					return -ENODEV;				port = &info_hpt372;				chip_table = &hpt372a;				break;			case PCI_DEVICE_ID_TTI_HPT302:				/* 302N if rev > 1 */				if (class_rev > 1)					return -ENODEV;				port = &info_hpt372;				/* Check this */				chip_table = &hpt302;				break;			case PCI_DEVICE_ID_TTI_HPT371:				if (class_rev > 1)					return -ENODEV;				port = &info_hpt372;				chip_table = &hpt371;				/* Single channel device, master is not present				   but the BIOS (or us for non x86) must mark it				   absent */				pci_read_config_byte(dev, 0x50, &mcr1);				mcr1 &= ~0x04;				pci_write_config_byte(dev, 0x50, mcr1);				break;			case PCI_DEVICE_ID_TTI_HPT374:				chip_table = &hpt374;				port = &info_hpt374;				break;			default:				printk(KERN_ERR "pata_hpt37x: 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);	/*	 * default to pci clock. make sure MA15/16 are set to output	 * to prevent drives having problems with 40-pin cables. Needed	 * for some drives such as IBM-DTLA which will not enter ready	 * state on reset when PDIAG is a input.	 */	pci_write_config_byte(dev, 0x5b, 0x23);	/*	 * HighPoint does this for HPT372A.	 * NOTE: This register is only writeable via I/O space.	 */	if (chip_table == &hpt372a)		outb(0x0e, iobase + 0x9c);	/* Some devices do not let this value be accessed via PCI space	   according to the old driver. In addition we must use the value	   from FN 0 on the HPT374 */	if (chip_table == &hpt374) {		freq = hpt374_read_freq(dev);		if (freq == 0)			return -ENODEV;	} else		freq = inl(iobase + 0x90);	if ((freq >> 12) != 0xABCDE) {		int i;		u8 sr;		u32 total = 0;		printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n");		/* This is the process the HPT371 BIOS is reported to use */		for(i = 0; i < 128; i++) {			pci_read_config_byte(dev, 0x78, &sr);			total += sr & 0x1FF;			udelay(15);		}		freq = total / 128;	}	freq &= 0x1FF;	/*	 *	Turn the frequency check into a band and then find a timing	 *	table to match it.	 */	clock_slot = hpt37x_clock_slot(freq, chip_table->base);	if (chip_table->clocks[clock_slot] == NULL || prefer_dpll) {		/*		 *	We need to try PLL mode instead		 *		 *	For non UDMA133 capable devices we should		 *	use a 50MHz DPLL by choice		 */		unsigned int f_low, f_high;		int dpll, adjust;		/* Compute DPLL */		dpll = (port->udma_mask & 0xC0) ? 3 : 2;		f_low = (MHz[clock_slot] * 48) / MHz[dpll];		f_high = f_low + 2;		if (clock_slot > 1)			f_high += 2;		/* Select the DPLL clock. */		pci_write_config_byte(dev, 0x5b, 0x21);		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100);		for(adjust = 0; adjust < 8; adjust++) {			if (hpt37x_calibrate_dpll(dev))				break;			/* See if it'll settle at a fractionally different clock */			if (adjust & 1)				f_low -= adjust >> 1;			else				f_high += adjust >> 1;			pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100);		}		if (adjust == 8) {			printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n");			return -ENODEV;		}		if (dpll == 3)			private_data = (void *)hpt37x_timings_66;		else			private_data = (void *)hpt37x_timings_50;		printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n",		       MHz[clock_slot], MHz[dpll]);	} else {		private_data = (void *)chip_table->clocks[clock_slot];		/*		 *	Perform a final fixup. Note that we will have used the		 *	DPLL on the HPT372 which means we don't have to worry		 *	about lack of UDMA133 support on lower clocks 		 */		if (clock_slot < 2 && port == &info_hpt370)			port = &info_hpt370_33;		if (clock_slot < 2 && port == &info_hpt370a)			port = &info_hpt370a_33;		printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n",		       chip_table->name, MHz[clock_slot]);	}	/* Now kick off ATA set up */	port_info = *port;	port_info.private_data = private_data;	return ata_pci_init_one(dev, ppi);}static const struct pci_device_id hpt37x[] = {	{ 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_HPT374), },	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), },	{ },};static struct pci_driver hpt37x_pci_driver = {	.name 		= DRV_NAME,	.id_table	= hpt37x,	.probe 		= hpt37x_init_one,	.remove		= ata_pci_remove_one};static int __init hpt37x_init(void){	return pci_register_driver(&hpt37x_pci_driver);}static void __exit hpt37x_exit(void){	pci_unregister_driver(&hpt37x_pci_driver);}MODULE_AUTHOR("Alan Cox");MODULE_DESCRIPTION("low-level driver for the Highpoint HPT37x/30x");MODULE_LICENSE("GPL");MODULE_DEVICE_TABLE(pci, hpt37x);MODULE_VERSION(DRV_VERSION);module_init(hpt37x_init);module_exit(hpt37x_exit);

⌨️ 快捷键说明

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