]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Tejun Heo <tj@kernel.org> |
2 | Subject: pata_hpt366: reimplement mode programming | |
3 | References: bnc#362159 | |
4 | ||
5 | Reimplement mode programming logic of pata_hpt366 such that it's | |
6 | identical to that of IDE hpt366 driver. The differences were... | |
7 | ||
8 | * pata_hpt366 used 0xCFFF8FFFF to mask pio modes and 0x3FFFFFFF dma | |
9 | modes. IDE hpt366 uses 0xC1F8FFFF for PIO, 0x303800FF for MWDMA and | |
10 | 0x30070000 for UDMA. | |
11 | ||
12 | * pata_hpt366 doesn't set 0x08000000 for PIO unless it's already set | |
13 | and always turns it on for MWDMA/UDMA. IDE hpt366 doesn't bother | |
14 | with the bit. It always uses what was there. | |
15 | ||
16 | * IDE hpt366 always clears 0xC0000000. pata_hpt366 doesn't. | |
17 | ||
18 | Signed-off-by: Tejun Heo <tj@kernel.org> | |
19 | Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> | |
20 | Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> | |
21 | Signed-off-by: Tejun Heo <teheo@suse.de> | |
22 | --- | |
23 | Unified pio/dma paths as per Sergei's suggestion. | |
24 | ||
25 | drivers/ata/pata_hpt366.c | 109 ++++++++++++++++++---------------------------- | |
26 | 1 file changed, 44 insertions(+), 65 deletions(-) | |
27 | ||
28 | Index: linux-2.6.27/drivers/ata/pata_hpt366.c | |
29 | =================================================================== | |
30 | --- linux-2.6.27.orig/drivers/ata/pata_hpt366.c | |
31 | +++ linux-2.6.27/drivers/ata/pata_hpt366.c | |
32 | @@ -30,7 +30,7 @@ | |
33 | #define DRV_VERSION "0.6.2" | |
34 | ||
35 | struct hpt_clock { | |
36 | - u8 xfer_speed; | |
37 | + u8 xfer_mode; | |
38 | u32 timing; | |
39 | }; | |
40 | ||
41 | @@ -189,28 +189,6 @@ static unsigned long hpt366_filter(struc | |
42 | return ata_bmdma_mode_filter(adev, mask); | |
43 | } | |
44 | ||
45 | -/** | |
46 | - * hpt36x_find_mode - reset the hpt36x bus | |
47 | - * @ap: ATA port | |
48 | - * @speed: transfer mode | |
49 | - * | |
50 | - * Return the 32bit register programming information for this channel | |
51 | - * that matches the speed provided. | |
52 | - */ | |
53 | - | |
54 | -static u32 hpt36x_find_mode(struct ata_port *ap, int speed) | |
55 | -{ | |
56 | - struct hpt_clock *clocks = ap->host->private_data; | |
57 | - | |
58 | - while(clocks->xfer_speed) { | |
59 | - if (clocks->xfer_speed == speed) | |
60 | - return clocks->timing; | |
61 | - clocks++; | |
62 | - } | |
63 | - BUG(); | |
64 | - return 0xffffffffU; /* silence compiler warning */ | |
65 | -} | |
66 | - | |
67 | static int hpt36x_cable_detect(struct ata_port *ap) | |
68 | { | |
69 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | |
70 | @@ -226,25 +204,16 @@ static int hpt36x_cable_detect(struct at | |
71 | return ATA_CBL_PATA80; | |
72 | } | |
73 | ||
74 | -/** | |
75 | - * hpt366_set_piomode - PIO setup | |
76 | - * @ap: ATA interface | |
77 | - * @adev: device on the interface | |
78 | - * | |
79 | - * Perform PIO mode setup. | |
80 | - */ | |
81 | - | |
82 | -static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev) | |
83 | +static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev, | |
84 | + u8 mode) | |
85 | { | |
86 | + struct hpt_clock *clocks = ap->host->private_data; | |
87 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | |
88 | - u32 addr1, addr2; | |
89 | - u32 reg; | |
90 | - u32 mode; | |
91 | + u32 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); | |
92 | + u32 addr2 = 0x51 + 4 * ap->port_no; | |
93 | + u32 mask, reg; | |
94 | u8 fast; | |
95 | ||
96 | - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); | |
97 | - addr2 = 0x51 + 4 * ap->port_no; | |
98 | - | |
99 | /* Fast interrupt prediction disable, hold off interrupt disable */ | |
100 | pci_read_config_byte(pdev, addr2, &fast); | |
101 | if (fast & 0x80) { | |
102 | @@ -252,12 +221,43 @@ static void hpt366_set_piomode(struct at | |
103 | pci_write_config_byte(pdev, addr2, fast); | |
104 | } | |
105 | ||
106 | + /* determine timing mask and find matching clock entry */ | |
107 | + if (mode < XFER_MW_DMA_0) | |
108 | + mask = 0xc1f8ffff; | |
109 | + else if (mode < XFER_UDMA_0) | |
110 | + mask = 0x303800ff; | |
111 | + else | |
112 | + mask = 0x30070000; | |
113 | + | |
114 | + while (clocks->xfer_mode) { | |
115 | + if (clocks->xfer_mode == mode) | |
116 | + break; | |
117 | + clocks++; | |
118 | + } | |
119 | + if (!clocks->xfer_mode) | |
120 | + BUG(); | |
121 | + | |
122 | + /* | |
123 | + * Combine new mode bits with old config bits and disable | |
124 | + * on-chip PIO FIFO/buffer (and PIO MST mode as well) to avoid | |
125 | + * problems handling I/O errors later. | |
126 | + */ | |
127 | pci_read_config_dword(pdev, addr1, ®); | |
128 | - mode = hpt36x_find_mode(ap, adev->pio_mode); | |
129 | - mode &= ~0x8000000; /* No FIFO in PIO */ | |
130 | - mode &= ~0x30070000; /* Leave config bits alone */ | |
131 | - reg &= 0x30070000; /* Strip timing bits */ | |
132 | - pci_write_config_dword(pdev, addr1, reg | mode); | |
133 | + reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000; | |
134 | + pci_write_config_dword(pdev, addr1, reg); | |
135 | +} | |
136 | + | |
137 | +/** | |
138 | + * hpt366_set_piomode - PIO setup | |
139 | + * @ap: ATA interface | |
140 | + * @adev: device on the interface | |
141 | + * | |
142 | + * Perform PIO mode setup. | |
143 | + */ | |
144 | + | |
145 | +static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev) | |
146 | +{ | |
147 | + hpt366_set_mode(ap, adev, adev->pio_mode); | |
148 | } | |
149 | ||
150 | /** | |
151 | @@ -271,28 +271,7 @@ static void hpt366_set_piomode(struct at | |
152 | ||
153 | static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |
154 | { | |
155 | - struct pci_dev *pdev = to_pci_dev(ap->host->dev); | |
156 | - u32 addr1, addr2; | |
157 | - u32 reg; | |
158 | - u32 mode; | |
159 | - u8 fast; | |
160 | - | |
161 | - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); | |
162 | - addr2 = 0x51 + 4 * ap->port_no; | |
163 | - | |
164 | - /* Fast interrupt prediction disable, hold off interrupt disable */ | |
165 | - pci_read_config_byte(pdev, addr2, &fast); | |
166 | - if (fast & 0x80) { | |
167 | - fast &= ~0x80; | |
168 | - pci_write_config_byte(pdev, addr2, fast); | |
169 | - } | |
170 | - | |
171 | - pci_read_config_dword(pdev, addr1, ®); | |
172 | - mode = hpt36x_find_mode(ap, adev->dma_mode); | |
173 | - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ | |
174 | - mode &= ~0xC0000000; /* Leave config bits alone */ | |
175 | - reg &= 0xC0000000; /* Strip timing bits */ | |
176 | - pci_write_config_dword(pdev, addr1, reg | mode); | |
177 | + hpt366_set_mode(ap, adev, adev->dma_mode); | |
178 | } | |
179 | ||
180 | static struct scsi_host_template hpt36x_sht = { |