aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_acpi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-12 19:16:41 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-12 19:16:41 -0400
commitab9c232286c2b77be78441c2d8396500b045777e (patch)
tree17570e159e4fb1ba36f1c363a7abef9b55909275 /drivers/ata/pata_acpi.c
parent8bd0983e05757e5c1f7a3342cd09badae93c167d (diff)
parent2855568b1ee4f58ef2c0a13ddfceb4b0b216b7ed (diff)
Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (119 commits) [libata] struct pci_dev related cleanups libata: use ata_exec_internal() for PMP register access libata: implement ATA_PFLAG_RESETTING libata: add @timeout to ata_exec_internal[_sg]() ahci: fix notification handling ahci: clean up PORT_IRQ_BAD_PMP enabling ahci: kill leftover from enabling NCQ over PMP libata: wrap schedule_timeout_uninterruptible() in loop libata: skip suppress reporting if ATA_EHI_QUIET libata: clear ehi description after initial host report pata_jmicron: match vendor and class code only libata: add ST9160821AS / 3.ALD to NCQ blacklist pata_acpi: ACPI driver support libata-core: Expose gtm methods for driver use libata: add HDT722516DLA380 to NCQ blacklist libata: blacklist NCQ on Seagate Barracuda ST380817AS [libata] Turn on ACPI by default libata_scsi: Fix ATAPI transfer lengths libata: correct handling of SRST reset sequences libata: Integrate ACPI-based PATA/SATA hotplug - version 5 ...
Diffstat (limited to 'drivers/ata/pata_acpi.c')
-rw-r--r--drivers/ata/pata_acpi.c395
1 files changed, 395 insertions, 0 deletions
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
new file mode 100644
index 000000000000..5d3920f6fd69
--- /dev/null
+++ b/drivers/ata/pata_acpi.c
@@ -0,0 +1,395 @@
1/*
2 * ACPI PATA driver
3 *
4 * (c) 2007 Red Hat <alan@redhat.com>
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <linux/pci.h>
10#include <linux/init.h>
11#include <linux/blkdev.h>
12#include <linux/delay.h>
13#include <linux/device.h>
14#include <scsi/scsi_host.h>
15#include <acpi/acpi_bus.h>
16#include <acpi/acnames.h>
17#include <acpi/acnamesp.h>
18#include <acpi/acparser.h>
19#include <acpi/acexcep.h>
20#include <acpi/acmacros.h>
21#include <acpi/actypes.h>
22
23#include <linux/libata.h>
24#include <linux/ata.h>
25
26#define DRV_NAME "pata_acpi"
27#define DRV_VERSION "0.2.3"
28
29struct pata_acpi {
30 struct ata_acpi_gtm gtm;
31 void *last;
32 unsigned long mask[2];
33};
34
35/**
36 * pacpi_pre_reset - check for 40/80 pin
37 * @ap: Port
38 * @deadline: deadline jiffies for the operation
39 *
40 * Perform the PATA port setup we need.
41 */
42
43static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline)
44{
45 struct ata_port *ap = link->ap;
46 struct pata_acpi *acpi = ap->private_data;
47 if (ap->acpi_handle == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0)
48 return -ENODEV;
49
50 return ata_std_prereset(link, deadline);
51}
52
53/**
54 * pacpi_cable_detect - cable type detection
55 * @ap: port to detect
56 *
57 * Perform device specific cable detection
58 */
59
60static int pacpi_cable_detect(struct ata_port *ap)
61{
62 struct pata_acpi *acpi = ap->private_data;
63
64 if ((acpi->mask[0] | acpi->mask[1]) & (0xF8 << ATA_SHIFT_UDMA))
65 return ATA_CBL_PATA80;
66 else
67 return ATA_CBL_PATA40;
68}
69
70/**
71 * pacpi_error_handler - Setup and error handler
72 * @ap: Port to handle
73 *
74 * LOCKING:
75 * None (inherited from caller).
76 */
77
78static void pacpi_error_handler(struct ata_port *ap)
79{
80 return ata_bmdma_drive_eh(ap, pacpi_pre_reset, ata_std_softreset,
81 NULL, ata_std_postreset);
82}
83
84/* Welcome to ACPI, bring a bucket */
85static const unsigned int pio_cycle[7] = {
86 600, 383, 240, 180, 120, 100, 80
87};
88static const unsigned int mwdma_cycle[5] = {
89 480, 150, 120, 100, 80
90};
91static const unsigned int udma_cycle[7] = {
92 120, 80, 60, 45, 30, 20, 15
93};
94
95/**
96 * pacpi_discover_modes - filter non ACPI modes
97 * @adev: ATA device
98 * @mask: proposed modes
99 *
100 * Try the modes available and see which ones the ACPI method will
101 * set up sensibly. From this we get a mask of ACPI modes we can use
102 */
103
104static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev)
105{
106 int unit = adev->devno;
107 struct pata_acpi *acpi = ap->private_data;
108 int i;
109 u32 t;
110 unsigned long mask = (0x7f << ATA_SHIFT_UDMA) | (0x7 << ATA_SHIFT_MWDMA) | (0x1F << ATA_SHIFT_PIO);
111
112 struct ata_acpi_gtm probe;
113
114 probe = acpi->gtm;
115
116 /* We always use the 0 slot for crap hardware */
117 if (!(probe.flags & 0x10))
118 unit = 0;
119
120 ata_acpi_gtm(ap, &probe);
121
122 /* Start by scanning for PIO modes */
123 for (i = 0; i < 7; i++) {
124 t = probe.drive[unit].pio;
125 if (t <= pio_cycle[i]) {
126 mask |= (2 << (ATA_SHIFT_PIO + i)) - 1;
127 break;
128 }
129 }
130
131 /* See if we have MWDMA or UDMA data. We don't bother with MWDMA
132 if UDMA is availabe as this means the BIOS set UDMA and our
133 error changedown if it works is UDMA to PIO anyway */
134 if (probe.flags & (1 << (2 * unit))) {
135 /* MWDMA */
136 for (i = 0; i < 5; i++) {
137 t = probe.drive[unit].dma;
138 if (t <= mwdma_cycle[i]) {
139 mask |= (2 << (ATA_SHIFT_MWDMA + i)) - 1;
140 break;
141 }
142 }
143 } else {
144 /* UDMA */
145 for (i = 0; i < 7; i++) {
146 t = probe.drive[unit].dma;
147 if (t <= udma_cycle[i]) {
148 mask |= (2 << (ATA_SHIFT_UDMA + i)) - 1;
149 break;
150 }
151 }
152 }
153 if (mask & (0xF8 << ATA_SHIFT_UDMA))
154 ap->cbl = ATA_CBL_PATA80;
155 return mask;
156}
157
158/**
159 * pacpi_mode_filter - mode filter for ACPI
160 * @adev: device
161 * @mask: mask of valid modes
162 *
163 * Filter the valid mode list according to our own specific rules, in
164 * this case the list of discovered valid modes obtained by ACPI probing
165 */
166
167static unsigned long pacpi_mode_filter(struct ata_device *adev, unsigned long mask)
168{
169 struct pata_acpi *acpi = adev->link->ap->private_data;
170 return ata_pci_default_filter(adev, mask & acpi->mask[adev->devno]);
171}
172
173/**
174 * pacpi_set_piomode - set initial PIO mode data
175 * @ap: ATA interface
176 * @adev: ATA device
177 */
178
179static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
180{
181 int unit = adev->devno;
182 struct pata_acpi *acpi = ap->private_data;
183
184 if(!(acpi->gtm.flags & 0x10))
185 unit = 0;
186
187 /* Now stuff the nS values into the structure */
188 acpi->gtm.drive[unit].pio = pio_cycle[adev->pio_mode - XFER_PIO_0];
189 ata_acpi_stm(ap, &acpi->gtm);
190 /* See what mode we actually got */
191 ata_acpi_gtm(ap, &acpi->gtm);
192}
193
194/**
195 * pacpi_set_dmamode - set initial DMA mode data
196 * @ap: ATA interface
197 * @adev: ATA device
198 */
199
200static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
201{
202 int unit = adev->devno;
203 struct pata_acpi *acpi = ap->private_data;
204
205 if(!(acpi->gtm.flags & 0x10))
206 unit = 0;
207
208 /* Now stuff the nS values into the structure */
209 if (adev->dma_mode >= XFER_UDMA_0) {
210 acpi->gtm.drive[unit].dma = udma_cycle[adev->dma_mode - XFER_UDMA_0];
211 acpi->gtm.flags |= (1 << (2 * unit));
212 } else {
213 acpi->gtm.drive[unit].dma = mwdma_cycle[adev->dma_mode - XFER_MW_DMA_0];
214 acpi->gtm.flags &= ~(1 << (2 * unit));
215 }
216 ata_acpi_stm(ap, &acpi->gtm);
217 /* See what mode we actually got */
218 ata_acpi_gtm(ap, &acpi->gtm);
219}
220
221/**
222 * pacpi_qc_issue_prot - command issue
223 * @qc: command pending
224 *
225 * Called when the libata layer is about to issue a command. We wrap
226 * this interface so that we can load the correct ATA timings if
227 * neccessary.
228 */
229
230static unsigned int pacpi_qc_issue_prot(struct ata_queued_cmd *qc)
231{
232 struct ata_port *ap = qc->ap;
233 struct ata_device *adev = qc->dev;
234 struct pata_acpi *acpi = ap->private_data;
235
236 if (acpi->gtm.flags & 0x10)
237 return ata_qc_issue_prot(qc);
238
239 if (adev != acpi->last) {
240 pacpi_set_piomode(ap, adev);
241 if (adev->dma_mode)
242 pacpi_set_dmamode(ap, adev);
243 acpi->last = adev;
244 }
245 return ata_qc_issue_prot(qc);
246}
247
248/**
249 * pacpi_port_start - port setup
250 * @ap: ATA port being set up
251 *
252 * Use the port_start hook to maintain private control structures
253 */
254
255static int pacpi_port_start(struct ata_port *ap)
256{
257 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
258 struct pata_acpi *acpi;
259
260 int ret;
261
262 if (ap->acpi_handle == NULL)
263 return -ENODEV;
264
265 acpi = ap->private_data = devm_kzalloc(&pdev->dev, sizeof(struct pata_acpi), GFP_KERNEL);
266 if (ap->private_data == NULL)
267 return -ENOMEM;
268 acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]);
269 acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]);
270 ret = ata_sff_port_start(ap);
271 if (ret < 0)
272 return ret;
273
274 return ret;
275}
276
277static struct scsi_host_template pacpi_sht = {
278 .module = THIS_MODULE,
279 .name = DRV_NAME,
280 .ioctl = ata_scsi_ioctl,
281 .queuecommand = ata_scsi_queuecmd,
282 .can_queue = ATA_DEF_QUEUE,
283 .this_id = ATA_SHT_THIS_ID,
284 .sg_tablesize = LIBATA_MAX_PRD,
285 .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
286 .emulated = ATA_SHT_EMULATED,
287 .use_clustering = ATA_SHT_USE_CLUSTERING,
288 .proc_name = DRV_NAME,
289 .dma_boundary = ATA_DMA_BOUNDARY,
290 .slave_configure = ata_scsi_slave_config,
291 .slave_destroy = ata_scsi_slave_destroy,
292 /* Use standard CHS mapping rules */
293 .bios_param = ata_std_bios_param,
294};
295
296static const struct ata_port_operations pacpi_ops = {
297 .set_piomode = pacpi_set_piomode,
298 .set_dmamode = pacpi_set_dmamode,
299 .mode_filter = pacpi_mode_filter,
300
301 /* Task file is PCI ATA format, use helpers */
302 .tf_load = ata_tf_load,
303 .tf_read = ata_tf_read,
304 .check_status = ata_check_status,
305 .exec_command = ata_exec_command,
306 .dev_select = ata_std_dev_select,
307
308 .freeze = ata_bmdma_freeze,
309 .thaw = ata_bmdma_thaw,
310 .error_handler = pacpi_error_handler,
311 .post_internal_cmd = ata_bmdma_post_internal_cmd,
312 .cable_detect = pacpi_cable_detect,
313
314 /* BMDMA handling is PCI ATA format, use helpers */
315 .bmdma_setup = ata_bmdma_setup,
316 .bmdma_start = ata_bmdma_start,
317 .bmdma_stop = ata_bmdma_stop,
318 .bmdma_status = ata_bmdma_status,
319 .qc_prep = ata_qc_prep,
320 .qc_issue = pacpi_qc_issue_prot,
321 .data_xfer = ata_data_xfer,
322
323 /* Timeout handling */
324 .irq_handler = ata_interrupt,
325 .irq_clear = ata_bmdma_irq_clear,
326 .irq_on = ata_irq_on,
327
328 /* Generic PATA PCI ATA helpers */
329 .port_start = pacpi_port_start,
330};
331
332
333/**
334 * pacpi_init_one - Register ACPI ATA PCI device with kernel services
335 * @pdev: PCI device to register
336 * @ent: Entry in pacpi_pci_tbl matching with @pdev
337 *
338 * Called from kernel PCI layer.
339 *
340 * LOCKING:
341 * Inherited from PCI layer (may sleep).
342 *
343 * RETURNS:
344 * Zero on success, or -ERRNO value.
345 */
346
347static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
348{
349 static const struct ata_port_info info = {
350 .sht = &pacpi_sht,
351 .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
352
353 .pio_mask = 0x1f,
354 .mwdma_mask = 0x07,
355 .udma_mask = 0x7f,
356
357 .port_ops = &pacpi_ops,
358 };
359 const struct ata_port_info *ppi[] = { &info, NULL };
360 return ata_pci_init_one(pdev, ppi);
361}
362
363static const struct pci_device_id pacpi_pci_tbl[] = {
364 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
365 { } /* terminate list */
366};
367
368static struct pci_driver pacpi_pci_driver = {
369 .name = DRV_NAME,
370 .id_table = pacpi_pci_tbl,
371 .probe = pacpi_init_one,
372 .remove = ata_pci_remove_one,
373 .suspend = ata_pci_device_suspend,
374 .resume = ata_pci_device_resume,
375};
376
377static int __init pacpi_init(void)
378{
379 return pci_register_driver(&pacpi_pci_driver);
380}
381
382static void __exit pacpi_exit(void)
383{
384 pci_unregister_driver(&pacpi_pci_driver);
385}
386
387module_init(pacpi_init);
388module_exit(pacpi_exit);
389
390MODULE_AUTHOR("Alan Cox");
391MODULE_DESCRIPTION("SCSI low-level driver for ATA in ACPI mode");
392MODULE_LICENSE("GPL");
393MODULE_DEVICE_TABLE(pci, pacpi_pci_tbl);
394MODULE_VERSION(DRV_VERSION);
395