triflex.c 3.46 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * IDE Chipset driver for the Compaq TriFlex IDE controller.
 * 
 * Known to work with the Compaq Workstation 5x00 series.
 *
 * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
 * Author: Torben Mathiasen <torben.mathiasen@hp.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * 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; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Loosely based on the piix & svwks drivers.
 *
 * Documentation:
 *	Not publically available.
 */

#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>

36
static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
Linus Torvalds's avatar
Linus Torvalds committed
37
38
{
	ide_hwif_t *hwif = HWIF(drive);
39
	struct pci_dev *dev = to_pci_dev(hwif->dev);
Linus Torvalds's avatar
Linus Torvalds committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
	u8 channel_offset = hwif->channel ? 0x74 : 0x70;
	u16 timing = 0;
	u32 triflex_timings = 0;
	u8 unit = (drive->select.b.unit & 0x01);
	
	pci_read_config_dword(dev, channel_offset, &triflex_timings);
	
	switch(speed) {
		case XFER_MW_DMA_2:
			timing = 0x0103; 
			break;
		case XFER_MW_DMA_1:
			timing = 0x0203;
			break;
		case XFER_MW_DMA_0:
			timing = 0x0808;
			break;
		case XFER_SW_DMA_2:
		case XFER_SW_DMA_1:
		case XFER_SW_DMA_0:
			timing = 0x0f0f;
			break;
		case XFER_PIO_4:
			timing = 0x0202;
			break;
		case XFER_PIO_3:
			timing = 0x0204;
			break;
		case XFER_PIO_2:
			timing = 0x0404;
			break;
		case XFER_PIO_1:
			timing = 0x0508;
			break;
		case XFER_PIO_0:
			timing = 0x0808;
			break;
	}

	triflex_timings &= ~(0xFFFF << (16 * unit));
	triflex_timings |= (timing << (16 * unit));
	
	pci_write_config_dword(dev, channel_offset, triflex_timings);
}

85
static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio)
Linus Torvalds's avatar
Linus Torvalds committed
86
{
87
	triflex_set_mode(drive, XFER_PIO_0 + pio);
Linus Torvalds's avatar
Linus Torvalds committed
88
89
}

90
91
92
93
static const struct ide_port_ops triflex_port_ops = {
	.set_pio_mode		= triflex_set_pio_mode,
	.set_dma_mode		= triflex_set_mode,
};
Linus Torvalds's avatar
Linus Torvalds committed
94

95
static const struct ide_port_info triflex_device __devinitdata = {
Linus Torvalds's avatar
Linus Torvalds committed
96
97
	.name		= "TRIFLEX",
	.enablebits	= {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
98
	.port_ops	= &triflex_port_ops,
Bartlomiej Zolnierkiewicz's avatar
Bartlomiej Zolnierkiewicz committed
99
	.pio_mask	= ATA_PIO4,
100
101
	.swdma_mask	= ATA_SWDMA2,
	.mwdma_mask	= ATA_MWDMA2,
Linus Torvalds's avatar
Linus Torvalds committed
102
103
104
105
106
};

static int __devinit triflex_init_one(struct pci_dev *dev, 
		const struct pci_device_id *id)
{
107
	return ide_pci_init_one(dev, &triflex_device, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
108
109
}

110
111
static const struct pci_device_id triflex_pci_tbl[] = {
	{ PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 },
Linus Torvalds's avatar
Linus Torvalds committed
112
113
114
115
116
117
118
119
	{ 0, },
};
MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);

static struct pci_driver driver = {
	.name		= "TRIFLEX_IDE",
	.id_table	= triflex_pci_tbl,
	.probe		= triflex_init_one,
120
	.remove		= ide_pci_remove,
Linus Torvalds's avatar
Linus Torvalds committed
121
122
};

123
static int __init triflex_ide_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
124
125
126
127
{
	return ide_pci_register_driver(&driver);
}

128
129
130
131
132
static void __exit triflex_ide_exit(void)
{
	pci_unregister_driver(&driver);
}

Linus Torvalds's avatar
Linus Torvalds committed
133
module_init(triflex_ide_init);
134
module_exit(triflex_ide_exit);
Linus Torvalds's avatar
Linus Torvalds committed
135
136
137
138
139
140

MODULE_AUTHOR("Torben Mathiasen");
MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
MODULE_LICENSE("GPL");