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

📄 pata_via.c

📁 their RouterBoard 1xx and 5xx series devices. The original Mikrotik code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * pata_via.c 	- VIA PATA for new ATA layer *			  (C) 2005-2006 Red Hat Inc *			  Alan Cox <alan@redhat.com> * *  Documentation *	Most chipset documentation available under NDA only * *  VIA version guide *	VIA VT82C561	-	early design, uses ata_generic currently *	VIA VT82C576	-	MWDMA, 33Mhz *	VIA VT82C586	-	MWDMA, 33Mhz *	VIA VT82C586a	-	Added UDMA to 33Mhz *	VIA VT82C586b	-	UDMA33 *	VIA VT82C596a	-	Nonfunctional UDMA66 *	VIA VT82C596b	-	Working UDMA66 *	VIA VT82C686	-	Nonfunctional UDMA66 *	VIA VT82C686a	-	Working UDMA66 *	VIA VT82C686b	-	Updated to UDMA100 *	VIA VT8231	-	UDMA100 *	VIA VT8233	-	UDMA100 *	VIA VT8233a	-	UDMA133 *	VIA VT8233c	-	UDMA100 *	VIA VT8235	-	UDMA133 *	VIA VT8237	-	UDMA133 *	VIA VT8237S	-	UDMA133 *	VIA VT8251	-	UDMA133 * *	Most registers remain compatible across chips. Others start reserved *	and acquire sensible semantics if set to 1 (eg cable detect). A few *	exceptions exist, notably around the FIFO settings. * *	One additional quirk of the VIA design is that like ALi they use few *	PCI IDs for a lot of chips. * *	Based heavily on: * * Version 3.38 * * VIA IDE driver for Linux. Supported southbridges: * *   vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, *   vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, *   vt8235, vt8237 * * Copyright (c) 2000-2002 Vojtech Pavlik * * Based on the work of: *	Michel Aubry *	Jeff Garzik *	Andre Hedrick */#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 <scsi/scsi_host.h>#include <linux/libata.h>#include <linux/dmi.h>#define DRV_NAME "pata_via"#define DRV_VERSION "0.3.3"/* *	The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx *	driver. */enum {	VIA_UDMA	= 0x007,	VIA_UDMA_NONE	= 0x000,	VIA_UDMA_33	= 0x001,	VIA_UDMA_66	= 0x002,	VIA_UDMA_100	= 0x003,	VIA_UDMA_133	= 0x004,	VIA_BAD_PREQ	= 0x010, /* Crashes if PREQ# till DDACK# set */	VIA_BAD_CLK66	= 0x020, /* 66 MHz clock doesn't work correctly */	VIA_SET_FIFO	= 0x040, /* Needs to have FIFO split set */	VIA_NO_UNMASK	= 0x080, /* Doesn't work with IRQ unmasking on */	VIA_BAD_ID	= 0x100, /* Has wrong vendor ID (0x1107) */	VIA_BAD_AST	= 0x200, /* Don't touch Address Setup Timing */	VIA_NO_ENABLES	= 0x400, /* Has no enablebits */	VIA_SATA_PATA	= 0x800, /* SATA/PATA combined configuration */};/* * VIA SouthBridge chips. */static const struct via_isa_bridge {	const char *name;	u16 id;	u8 rev_min;	u8 rev_max;	u16 flags;} via_isa_bridges[] = {	{ "vx800",	PCI_DEVICE_ID_VIA_VX800,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },	{ "vt8237s",	PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES},	{ "vt8237a",	PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },	{ "vt8233c",	PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, VIA_UDMA_100 },	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, VIA_UDMA_100 },	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, VIA_UDMA_100 },	{ "vt82c686b",	PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, VIA_UDMA_100 },	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, VIA_UDMA_66 },	{ "vt82c686",	PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, VIA_UDMA_66 },	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO },	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ },	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO },	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },	{ NULL }};/* *	Cable special cases */static const struct dmi_system_id cable_dmi_table[] = {	{		.ident = "Acer Ferrari 3400",		.matches = {			DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),			DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),		},	},	{ }};static int via_cable_override(struct pci_dev *pdev){	/* Systems by DMI */	if (dmi_check_system(cable_dmi_table))		return 1;	/* Arima W730-K8/Targa Visionary 811/... */	if (pdev->subsystem_vendor == 0x161F && pdev->subsystem_device == 0x2032)		return 1;	return 0;}/** *	via_cable_detect	-	cable detection *	@ap: ATA port * *	Perform cable detection. Actually for the VIA case the BIOS *	already did this for us. We read the values provided by the *	BIOS. If you are using an 8235 in a non-PC configuration you *	may need to update this code. * *	Hotplug also impacts on this. */static int via_cable_detect(struct ata_port *ap) {	const struct via_isa_bridge *config = ap->host->private_data;	struct pci_dev *pdev = to_pci_dev(ap->host->dev);	u32 ata66;	if (via_cable_override(pdev))		return ATA_CBL_PATA40_SHORT;	if ((config->flags & VIA_SATA_PATA) && ap->port_no == 0)		return ATA_CBL_SATA;	/* Early chips are 40 wire */	if ((config->flags & VIA_UDMA) < VIA_UDMA_66)		return ATA_CBL_PATA40;	/* UDMA 66 chips have only drive side logic */	else if ((config->flags & VIA_UDMA) < VIA_UDMA_100)		return ATA_CBL_PATA_UNK;	/* UDMA 100 or later */	pci_read_config_dword(pdev, 0x50, &ata66);	/* Check both the drive cable reporting bits, we might not have	   two drives */	if (ata66 & (0x10100000 >> (16 * ap->port_no)))		return ATA_CBL_PATA80;	/* Check with ACPI so we can spot BIOS reported SATA bridges */	if (ata_acpi_init_gtm(ap) &&	    ata_acpi_cbl_80wire(ap, ata_acpi_init_gtm(ap)))		return ATA_CBL_PATA80;	return ATA_CBL_PATA40;}static int via_pre_reset(struct ata_link *link, unsigned long deadline){	struct ata_port *ap = link->ap;	const struct via_isa_bridge *config = ap->host->private_data;	if (!(config->flags & VIA_NO_ENABLES)) {		static const struct pci_bits via_enable_bits[] = {			{ 0x40, 1, 0x02, 0x02 },			{ 0x40, 1, 0x01, 0x01 }		};		struct pci_dev *pdev = to_pci_dev(ap->host->dev);		if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no]))			return -ENOENT;	}	return ata_sff_prereset(link, deadline);}/** *	via_do_set_mode	-	set initial PIO mode data *	@ap: ATA interface *	@adev: ATA device *	@mode: ATA mode being programmed *	@tdiv: Clocks per PCI clock *	@set_ast: Set to program address setup *	@udma_type: UDMA mode/format of registers * *	Program the VIA registers for DMA and PIO modes. Uses the ata timing *	support in order to compute modes. * *	FIXME: Hotplug will require we serialize multiple mode changes *	on the two channels. */static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mode, int tdiv, int set_ast, int udma_type){	struct pci_dev *pdev = to_pci_dev(ap->host->dev);	struct ata_device *peer = ata_dev_pair(adev);	struct ata_timing t, p;	static int via_clock = 33333;	/* Bus clock in kHZ - ought to be tunable one day */	unsigned long T =  1000000000 / via_clock;	unsigned long UT = T/tdiv;	int ut;	int offset = 3 - (2*ap->port_no) - adev->devno;	/* Calculate the timing values we require */	ata_timing_compute(adev, mode, &t, T, UT);	/* We share 8bit timing so we must merge the constraints */	if (peer) {		if (peer->pio_mode) {			ata_timing_compute(peer, peer->pio_mode, &p, T, UT);			ata_timing_merge(&p, &t, &t, ATA_TIMING_8BIT);		}	}	/* Address setup is programmable but breaks on UDMA133 setups */	if (set_ast) {		u8 setup;	/* 2 bits per drive */		int shift = 2 * offset;		pci_read_config_byte(pdev, 0x4C, &setup);		setup &= ~(3 << shift);		setup |= clamp_val(t.setup, 1, 4) << shift;	/* 1,4 or 1,4 - 1  FIXME */		pci_write_config_byte(pdev, 0x4C, setup);	}	/* Load the PIO mode bits */	pci_write_config_byte(pdev, 0x4F - ap->port_no,		((clamp_val(t.act8b, 1, 16) - 1) << 4) | (clamp_val(t.rec8b, 1, 16) - 1));	pci_write_config_byte(pdev, 0x48 + offset,		((clamp_val(t.active, 1, 16) - 1) << 4) | (clamp_val(t.recover, 1, 16) - 1));	/* Load the UDMA bits according to type */	switch(udma_type) {		default:			/* BUG() ? */			/* fall through */		case 33:			ut = t.udma ? (0xe0 | (clamp_val(t.udma, 2, 5) - 2)) : 0x03;			break;		case 66:			ut = t.udma ? (0xe8 | (clamp_val(t.udma, 2, 9) - 2)) : 0x0f;			break;		case 100:			ut = t.udma ? (0xe0 | (clamp_val(t.udma, 2, 9) - 2)) : 0x07;			break;		case 133:			ut = t.udma ? (0xe0 | (clamp_val(t.udma, 2, 9) - 2)) : 0x07;			break;	}	/* Set UDMA unless device is not UDMA capable */	if (udma_type && t.udma) {		u8 cable80_status;		/* Get 80-wire cable detection bit */		pci_read_config_byte(pdev, 0x50 + offset, &cable80_status);		cable80_status &= 0x10;		pci_write_config_byte(pdev, 0x50 + offset, ut | cable80_status);	}

⌨️ 快捷键说明

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