diff options
author | Kristen Carlson Accardi <kristen.c.accardi@intel.com> | 2006-09-28 14:29:01 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-16 13:32:41 -0500 |
commit | 11ef697b37e3c85ce1ac21f7711babf1f5b12784 (patch) | |
tree | 7b118d54bc8fc24ca8cbc626d603013d07ed8c2a /drivers/ata/libata-acpi.c | |
parent | 8a03d9a498eaf02c8a118752050a5154852c13bf (diff) |
[PATCH] libata: ACPI and _GTF support
_GTF is an acpi method that is used to reinitialize the drive. It returns
a task file containing ata commands that are sent back to the drive to restore
it to boot up defaults.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
(cherry picked from 9c69cab24b51a89664f4c0dfaf8a436d32117624 commit)
Diffstat (limited to 'drivers/ata/libata-acpi.c')
-rw-r--r-- | drivers/ata/libata-acpi.c | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c new file mode 100644 index 000000000000..7b740fe1721b --- /dev/null +++ b/drivers/ata/libata-acpi.c | |||
@@ -0,0 +1,602 @@ | |||
1 | /* | ||
2 | * libata-acpi.c | ||
3 | * Provides ACPI support for PATA/SATA. | ||
4 | * | ||
5 | * Copyright (C) 2006 Intel Corp. | ||
6 | * Copyright (C) 2006 Randy Dunlap | ||
7 | */ | ||
8 | |||
9 | #include <linux/ata.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/acpi.h> | ||
15 | #include <linux/libata.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include "libata.h" | ||
18 | |||
19 | #include <acpi/acpi_bus.h> | ||
20 | #include <acpi/acnames.h> | ||
21 | #include <acpi/acnamesp.h> | ||
22 | #include <acpi/acparser.h> | ||
23 | #include <acpi/acexcep.h> | ||
24 | #include <acpi/acmacros.h> | ||
25 | #include <acpi/actypes.h> | ||
26 | |||
27 | #define SATA_ROOT_PORT(x) (((x) >> 16) & 0xffff) | ||
28 | #define SATA_PORT_NUMBER(x) ((x) & 0xffff) /* or NO_PORT_MULT */ | ||
29 | #define NO_PORT_MULT 0xffff | ||
30 | #define SATA_ADR_RSVD 0xffffffff | ||
31 | |||
32 | #define REGS_PER_GTF 7 | ||
33 | struct taskfile_array { | ||
34 | u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ | ||
35 | }; | ||
36 | |||
37 | |||
38 | /** | ||
39 | * sata_get_dev_handle - finds acpi_handle and PCI device.function | ||
40 | * @dev: device to locate | ||
41 | * @handle: returned acpi_handle for @dev | ||
42 | * @pcidevfn: return PCI device.func for @dev | ||
43 | * | ||
44 | * This function is somewhat SATA-specific. Or at least the | ||
45 | * PATA & SATA versions of this function are different, | ||
46 | * so it's not entirely generic code. | ||
47 | * | ||
48 | * Returns 0 on success, <0 on error. | ||
49 | */ | ||
50 | static int sata_get_dev_handle(struct device *dev, acpi_handle *handle, | ||
51 | acpi_integer *pcidevfn) | ||
52 | { | ||
53 | struct pci_dev *pci_dev; | ||
54 | acpi_integer addr; | ||
55 | |||
56 | pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */ | ||
57 | /* Please refer to the ACPI spec for the syntax of _ADR. */ | ||
58 | addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); | ||
59 | *pcidevfn = addr; | ||
60 | *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr); | ||
61 | if (!*handle) | ||
62 | return -ENODEV; | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * pata_get_dev_handle - finds acpi_handle and PCI device.function | ||
68 | * @dev: device to locate | ||
69 | * @handle: returned acpi_handle for @dev | ||
70 | * @pcidevfn: return PCI device.func for @dev | ||
71 | * | ||
72 | * The PATA and SATA versions of this function are different. | ||
73 | * | ||
74 | * Returns 0 on success, <0 on error. | ||
75 | */ | ||
76 | static int pata_get_dev_handle(struct device *dev, acpi_handle *handle, | ||
77 | acpi_integer *pcidevfn) | ||
78 | { | ||
79 | unsigned int bus, devnum, func; | ||
80 | acpi_integer addr; | ||
81 | acpi_handle dev_handle, parent_handle; | ||
82 | struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER, | ||
83 | .pointer = NULL}; | ||
84 | acpi_status status; | ||
85 | struct acpi_device_info *dinfo = NULL; | ||
86 | int ret = -ENODEV; | ||
87 | struct pci_dev *pdev = to_pci_dev(dev); | ||
88 | |||
89 | bus = pdev->bus->number; | ||
90 | devnum = PCI_SLOT(pdev->devfn); | ||
91 | func = PCI_FUNC(pdev->devfn); | ||
92 | |||
93 | dev_handle = DEVICE_ACPI_HANDLE(dev); | ||
94 | parent_handle = DEVICE_ACPI_HANDLE(dev->parent); | ||
95 | |||
96 | status = acpi_get_object_info(parent_handle, &buffer); | ||
97 | if (ACPI_FAILURE(status)) | ||
98 | goto err; | ||
99 | |||
100 | dinfo = buffer.pointer; | ||
101 | if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && | ||
102 | dinfo->address == bus) { | ||
103 | /* ACPI spec for _ADR for PCI bus: */ | ||
104 | addr = (acpi_integer)(devnum << 16 | func); | ||
105 | *pcidevfn = addr; | ||
106 | *handle = dev_handle; | ||
107 | } else { | ||
108 | goto err; | ||
109 | } | ||
110 | |||
111 | if (!*handle) | ||
112 | goto err; | ||
113 | ret = 0; | ||
114 | err: | ||
115 | kfree(dinfo); | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | struct walk_info { /* can be trimmed some */ | ||
120 | struct device *dev; | ||
121 | struct acpi_device *adev; | ||
122 | acpi_handle handle; | ||
123 | acpi_integer pcidevfn; | ||
124 | unsigned int drivenum; | ||
125 | acpi_handle obj_handle; | ||
126 | struct ata_port *ataport; | ||
127 | struct ata_device *atadev; | ||
128 | u32 sata_adr; | ||
129 | int status; | ||
130 | char basepath[ACPI_PATHNAME_MAX]; | ||
131 | int basepath_len; | ||
132 | }; | ||
133 | |||
134 | static acpi_status get_devices(acpi_handle handle, | ||
135 | u32 level, void *context, void **return_value) | ||
136 | { | ||
137 | acpi_status status; | ||
138 | struct walk_info *winfo = context; | ||
139 | struct acpi_buffer namebuf = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
140 | char *pathname; | ||
141 | struct acpi_buffer buffer; | ||
142 | struct acpi_device_info *dinfo; | ||
143 | |||
144 | status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf); | ||
145 | if (status) | ||
146 | goto ret; | ||
147 | pathname = namebuf.pointer; | ||
148 | |||
149 | buffer.length = ACPI_ALLOCATE_BUFFER; | ||
150 | buffer.pointer = NULL; | ||
151 | status = acpi_get_object_info(handle, &buffer); | ||
152 | if (ACPI_FAILURE(status)) | ||
153 | goto out2; | ||
154 | |||
155 | dinfo = buffer.pointer; | ||
156 | |||
157 | /* find full device path name for pcidevfn */ | ||
158 | if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && | ||
159 | dinfo->address == winfo->pcidevfn) { | ||
160 | if (ata_msg_probe(winfo->ataport)) | ||
161 | ata_dev_printk(winfo->atadev, KERN_DEBUG, | ||
162 | ":%s: matches pcidevfn (0x%llx)\n", | ||
163 | pathname, winfo->pcidevfn); | ||
164 | strlcpy(winfo->basepath, pathname, | ||
165 | sizeof(winfo->basepath)); | ||
166 | winfo->basepath_len = strlen(pathname); | ||
167 | goto out; | ||
168 | } | ||
169 | |||
170 | /* if basepath is not yet known, ignore this object */ | ||
171 | if (!winfo->basepath_len) | ||
172 | goto out; | ||
173 | |||
174 | /* if this object is in scope of basepath, maybe use it */ | ||
175 | if (strncmp(pathname, winfo->basepath, | ||
176 | winfo->basepath_len) == 0) { | ||
177 | if (!(dinfo->valid & ACPI_VALID_ADR)) | ||
178 | goto out; | ||
179 | if (ata_msg_probe(winfo->ataport)) | ||
180 | ata_dev_printk(winfo->atadev, KERN_DEBUG, | ||
181 | "GOT ONE: (%s) root_port = 0x%llx," | ||
182 | " port_num = 0x%llx\n", pathname, | ||
183 | SATA_ROOT_PORT(dinfo->address), | ||
184 | SATA_PORT_NUMBER(dinfo->address)); | ||
185 | /* heuristics: */ | ||
186 | if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT) | ||
187 | if (ata_msg_probe(winfo->ataport)) | ||
188 | ata_dev_printk(winfo->atadev, | ||
189 | KERN_DEBUG, "warning: don't" | ||
190 | " know how to handle SATA port" | ||
191 | " multiplier\n"); | ||
192 | if (SATA_ROOT_PORT(dinfo->address) == | ||
193 | winfo->ataport->port_no && | ||
194 | SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) { | ||
195 | if (ata_msg_probe(winfo->ataport)) | ||
196 | ata_dev_printk(winfo->atadev, | ||
197 | KERN_DEBUG, | ||
198 | "THIS ^^^^^ is the requested" | ||
199 | " SATA drive (handle = 0x%p)\n", | ||
200 | handle); | ||
201 | winfo->sata_adr = dinfo->address; | ||
202 | winfo->obj_handle = handle; | ||
203 | } | ||
204 | } | ||
205 | out: | ||
206 | kfree(dinfo); | ||
207 | out2: | ||
208 | kfree(pathname); | ||
209 | |||
210 | ret: | ||
211 | return status; | ||
212 | } | ||
213 | |||
214 | /* Get the SATA drive _ADR object. */ | ||
215 | static int get_sata_adr(struct device *dev, acpi_handle handle, | ||
216 | acpi_integer pcidevfn, unsigned int drive, | ||
217 | struct ata_port *ap, | ||
218 | struct ata_device *atadev, u32 *dev_adr) | ||
219 | { | ||
220 | acpi_status status; | ||
221 | struct walk_info *winfo; | ||
222 | int err = -ENOMEM; | ||
223 | |||
224 | winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL); | ||
225 | if (!winfo) | ||
226 | goto out; | ||
227 | |||
228 | winfo->dev = dev; | ||
229 | winfo->atadev = atadev; | ||
230 | winfo->ataport = ap; | ||
231 | if (acpi_bus_get_device(handle, &winfo->adev) < 0) | ||
232 | if (ata_msg_probe(ap)) | ||
233 | ata_dev_printk(winfo->atadev, KERN_DEBUG, | ||
234 | "acpi_bus_get_device failed\n"); | ||
235 | winfo->handle = handle; | ||
236 | winfo->pcidevfn = pcidevfn; | ||
237 | winfo->drivenum = drive; | ||
238 | |||
239 | status = acpi_get_devices(NULL, get_devices, winfo, NULL); | ||
240 | if (ACPI_FAILURE(status)) { | ||
241 | if (ata_msg_probe(ap)) | ||
242 | ata_dev_printk(winfo->atadev, KERN_DEBUG, | ||
243 | "%s: acpi_get_devices failed\n", | ||
244 | __FUNCTION__); | ||
245 | err = -ENODEV; | ||
246 | } else { | ||
247 | *dev_adr = winfo->sata_adr; | ||
248 | atadev->obj_handle = winfo->obj_handle; | ||
249 | err = 0; | ||
250 | } | ||
251 | kfree(winfo); | ||
252 | out: | ||
253 | return err; | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * do_drive_get_GTF - get the drive bootup default taskfile settings | ||
258 | * @ap: the ata_port for the drive | ||
259 | * @ix: target ata_device (drive) index | ||
260 | * @gtf_length: number of bytes of _GTF data returned at @gtf_address | ||
261 | * @gtf_address: buffer containing _GTF taskfile arrays | ||
262 | * | ||
263 | * This applies to both PATA and SATA drives. | ||
264 | * | ||
265 | * The _GTF method has no input parameters. | ||
266 | * It returns a variable number of register set values (registers | ||
267 | * hex 1F1..1F7, taskfiles). | ||
268 | * The <variable number> is not known in advance, so have ACPI-CA | ||
269 | * allocate the buffer as needed and return it, then free it later. | ||
270 | * | ||
271 | * The returned @gtf_length and @gtf_address are only valid if the | ||
272 | * function return value is 0. | ||
273 | */ | ||
274 | static int do_drive_get_GTF(struct ata_port *ap, int ix, | ||
275 | unsigned int *gtf_length, unsigned long *gtf_address, | ||
276 | unsigned long *obj_loc) | ||
277 | { | ||
278 | acpi_status status; | ||
279 | acpi_handle dev_handle = NULL; | ||
280 | acpi_handle chan_handle, drive_handle; | ||
281 | acpi_integer pcidevfn = 0; | ||
282 | u32 dev_adr; | ||
283 | struct acpi_buffer output; | ||
284 | union acpi_object *out_obj; | ||
285 | struct device *dev = ap->host->dev; | ||
286 | struct ata_device *atadev = &ap->device[ix]; | ||
287 | int err = -ENODEV; | ||
288 | |||
289 | *gtf_length = 0; | ||
290 | *gtf_address = 0UL; | ||
291 | *obj_loc = 0UL; | ||
292 | |||
293 | if (noacpi) | ||
294 | return 0; | ||
295 | |||
296 | if (ata_msg_probe(ap)) | ||
297 | ata_dev_printk(atadev, KERN_DEBUG, | ||
298 | "%s: ENTER: ap->id: %d, port#: %d\n", | ||
299 | __FUNCTION__, ap->id, ap->port_no); | ||
300 | |||
301 | if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) { | ||
302 | if (ata_msg_probe(ap)) | ||
303 | ata_dev_printk(atadev, KERN_DEBUG, "%s: ERR: " | ||
304 | "ata_dev_present: %d, PORT_DISABLED: %lu\n", | ||
305 | __FUNCTION__, ata_dev_enabled(atadev), | ||
306 | ap->flags & ATA_FLAG_DISABLED); | ||
307 | goto out; | ||
308 | } | ||
309 | |||
310 | /* Don't continue if device has no _ADR method. | ||
311 | * _GTF is intended for known motherboard devices. */ | ||
312 | if (!(ap->cbl == ATA_CBL_SATA)) { | ||
313 | err = pata_get_dev_handle(dev, &dev_handle, &pcidevfn); | ||
314 | if (err < 0) { | ||
315 | if (ata_msg_probe(ap)) | ||
316 | ata_dev_printk(atadev, KERN_DEBUG, | ||
317 | "%s: pata_get_dev_handle failed (%d)\n", | ||
318 | __FUNCTION__, err); | ||
319 | goto out; | ||
320 | } | ||
321 | } else { | ||
322 | err = sata_get_dev_handle(dev, &dev_handle, &pcidevfn); | ||
323 | if (err < 0) { | ||
324 | if (ata_msg_probe(ap)) | ||
325 | ata_dev_printk(atadev, KERN_DEBUG, | ||
326 | "%s: sata_get_dev_handle failed (%d\n", | ||
327 | __FUNCTION__, err); | ||
328 | goto out; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | /* Get this drive's _ADR info. if not already known. */ | ||
333 | if (!atadev->obj_handle) { | ||
334 | if (!(ap->cbl == ATA_CBL_SATA)) { | ||
335 | /* get child objects of dev_handle == channel objects, | ||
336 | * + _their_ children == drive objects */ | ||
337 | /* channel is ap->port_no */ | ||
338 | chan_handle = acpi_get_child(dev_handle, | ||
339 | ap->port_no); | ||
340 | if (ata_msg_probe(ap)) | ||
341 | ata_dev_printk(atadev, KERN_DEBUG, | ||
342 | "%s: chan adr=%d: chan_handle=0x%p\n", | ||
343 | __FUNCTION__, ap->port_no, | ||
344 | chan_handle); | ||
345 | if (!chan_handle) { | ||
346 | err = -ENODEV; | ||
347 | goto out; | ||
348 | } | ||
349 | /* TBD: could also check ACPI object VALID bits */ | ||
350 | drive_handle = acpi_get_child(chan_handle, ix); | ||
351 | if (!drive_handle) { | ||
352 | err = -ENODEV; | ||
353 | goto out; | ||
354 | } | ||
355 | dev_adr = ix; | ||
356 | atadev->obj_handle = drive_handle; | ||
357 | } else { /* for SATA mode */ | ||
358 | dev_adr = SATA_ADR_RSVD; | ||
359 | err = get_sata_adr(dev, dev_handle, pcidevfn, 0, | ||
360 | ap, atadev, &dev_adr); | ||
361 | } | ||
362 | if (err < 0 || dev_adr == SATA_ADR_RSVD || | ||
363 | !atadev->obj_handle) { | ||
364 | if (ata_msg_probe(ap)) | ||
365 | ata_dev_printk(atadev, KERN_DEBUG, | ||
366 | "%s: get_sata/pata_adr failed: " | ||
367 | "err=%d, dev_adr=%u, obj_handle=0x%p\n", | ||
368 | __FUNCTION__, err, dev_adr, | ||
369 | atadev->obj_handle); | ||
370 | goto out; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /* Setting up output buffer */ | ||
375 | output.length = ACPI_ALLOCATE_BUFFER; | ||
376 | output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ | ||
377 | |||
378 | /* _GTF has no input parameters */ | ||
379 | err = -EIO; | ||
380 | status = acpi_evaluate_object(atadev->obj_handle, "_GTF", | ||
381 | NULL, &output); | ||
382 | if (ACPI_FAILURE(status)) { | ||
383 | if (ata_msg_probe(ap)) | ||
384 | ata_dev_printk(atadev, KERN_DEBUG, | ||
385 | "%s: Run _GTF error: status = 0x%x\n", | ||
386 | __FUNCTION__, status); | ||
387 | goto out; | ||
388 | } | ||
389 | |||
390 | if (!output.length || !output.pointer) { | ||
391 | if (ata_msg_probe(ap)) | ||
392 | ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: " | ||
393 | "length or ptr is NULL (0x%llx, 0x%p)\n", | ||
394 | __FUNCTION__, | ||
395 | (unsigned long long)output.length, | ||
396 | output.pointer); | ||
397 | kfree(output.pointer); | ||
398 | goto out; | ||
399 | } | ||
400 | |||
401 | out_obj = output.pointer; | ||
402 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
403 | kfree(output.pointer); | ||
404 | if (ata_msg_probe(ap)) | ||
405 | ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: " | ||
406 | "error: expected object type of " | ||
407 | " ACPI_TYPE_BUFFER, got 0x%x\n", | ||
408 | __FUNCTION__, out_obj->type); | ||
409 | err = -ENOENT; | ||
410 | goto out; | ||
411 | } | ||
412 | |||
413 | if (!out_obj->buffer.length || !out_obj->buffer.pointer || | ||
414 | out_obj->buffer.length % REGS_PER_GTF) { | ||
415 | if (ata_msg_drv(ap)) | ||
416 | ata_dev_printk(atadev, KERN_ERR, | ||
417 | "%s: unexpected GTF length (%d) or addr (0x%p)\n", | ||
418 | __FUNCTION__, out_obj->buffer.length, | ||
419 | out_obj->buffer.pointer); | ||
420 | err = -ENOENT; | ||
421 | goto out; | ||
422 | } | ||
423 | |||
424 | *gtf_length = out_obj->buffer.length; | ||
425 | *gtf_address = (unsigned long)out_obj->buffer.pointer; | ||
426 | *obj_loc = (unsigned long)out_obj; | ||
427 | if (ata_msg_probe(ap)) | ||
428 | ata_dev_printk(atadev, KERN_DEBUG, "%s: returning " | ||
429 | "gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n", | ||
430 | __FUNCTION__, *gtf_length, *gtf_address, *obj_loc); | ||
431 | err = 0; | ||
432 | out: | ||
433 | return err; | ||
434 | } | ||
435 | |||
436 | /** | ||
437 | * taskfile_load_raw - send taskfile registers to host controller | ||
438 | * @ap: Port to which output is sent | ||
439 | * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) | ||
440 | * | ||
441 | * Outputs ATA taskfile to standard ATA host controller using MMIO | ||
442 | * or PIO as indicated by the ATA_FLAG_MMIO flag. | ||
443 | * Writes the control, feature, nsect, lbal, lbam, and lbah registers. | ||
444 | * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect, | ||
445 | * hob_lbal, hob_lbam, and hob_lbah. | ||
446 | * | ||
447 | * This function waits for idle (!BUSY and !DRQ) after writing | ||
448 | * registers. If the control register has a new value, this | ||
449 | * function also waits for idle after writing control and before | ||
450 | * writing the remaining registers. | ||
451 | * | ||
452 | * LOCKING: TBD: | ||
453 | * Inherited from caller. | ||
454 | */ | ||
455 | static void taskfile_load_raw(struct ata_port *ap, | ||
456 | struct ata_device *atadev, | ||
457 | const struct taskfile_array *gtf) | ||
458 | { | ||
459 | if (ata_msg_probe(ap)) | ||
460 | ata_dev_printk(atadev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: " | ||
461 | "%02x %02x %02x %02x %02x %02x %02x\n", | ||
462 | __FUNCTION__, | ||
463 | gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], | ||
464 | gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); | ||
465 | |||
466 | if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0) | ||
467 | && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0) | ||
468 | && (gtf->tfa[6] == 0)) | ||
469 | return; | ||
470 | |||
471 | if (ap->ops->qc_issue) { | ||
472 | struct ata_taskfile tf; | ||
473 | unsigned int err; | ||
474 | |||
475 | ata_tf_init(atadev, &tf); | ||
476 | |||
477 | /* convert gtf to tf */ | ||
478 | tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */ | ||
479 | tf.protocol = atadev->class == ATA_DEV_ATAPI ? | ||
480 | ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA; | ||
481 | tf.feature = gtf->tfa[0]; /* 0x1f1 */ | ||
482 | tf.nsect = gtf->tfa[1]; /* 0x1f2 */ | ||
483 | tf.lbal = gtf->tfa[2]; /* 0x1f3 */ | ||
484 | tf.lbam = gtf->tfa[3]; /* 0x1f4 */ | ||
485 | tf.lbah = gtf->tfa[4]; /* 0x1f5 */ | ||
486 | tf.device = gtf->tfa[5]; /* 0x1f6 */ | ||
487 | tf.command = gtf->tfa[6]; /* 0x1f7 */ | ||
488 | |||
489 | err = ata_exec_internal(atadev, &tf, NULL, DMA_NONE, NULL, 0); | ||
490 | if (err && ata_msg_probe(ap)) | ||
491 | ata_dev_printk(atadev, KERN_ERR, | ||
492 | "%s: ata_exec_internal failed: %u\n", | ||
493 | __FUNCTION__, err); | ||
494 | } else | ||
495 | if (ata_msg_warn(ap)) | ||
496 | ata_dev_printk(atadev, KERN_WARNING, | ||
497 | "%s: SATA driver is missing qc_issue function" | ||
498 | " entry points\n", | ||
499 | __FUNCTION__); | ||
500 | } | ||
501 | |||
502 | /** | ||
503 | * do_drive_set_taskfiles - write the drive taskfile settings from _GTF | ||
504 | * @ap: the ata_port for the drive | ||
505 | * @atadev: target ata_device | ||
506 | * @gtf_length: total number of bytes of _GTF taskfiles | ||
507 | * @gtf_address: location of _GTF taskfile arrays | ||
508 | * | ||
509 | * This applies to both PATA and SATA drives. | ||
510 | * | ||
511 | * Write {gtf_address, length gtf_length} in groups of | ||
512 | * REGS_PER_GTF bytes. | ||
513 | */ | ||
514 | static int do_drive_set_taskfiles(struct ata_port *ap, | ||
515 | struct ata_device *atadev, unsigned int gtf_length, | ||
516 | unsigned long gtf_address) | ||
517 | { | ||
518 | int err = -ENODEV; | ||
519 | int gtf_count = gtf_length / REGS_PER_GTF; | ||
520 | int ix; | ||
521 | struct taskfile_array *gtf; | ||
522 | |||
523 | if (ata_msg_probe(ap)) | ||
524 | ata_dev_printk(atadev, KERN_DEBUG, | ||
525 | "%s: ENTER: ap->id: %d, port#: %d\n", | ||
526 | __FUNCTION__, ap->id, ap->port_no); | ||
527 | |||
528 | if (noacpi || !(ap->cbl == ATA_CBL_SATA)) | ||
529 | return 0; | ||
530 | |||
531 | if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) | ||
532 | goto out; | ||
533 | if (!gtf_count) /* shouldn't be here */ | ||
534 | goto out; | ||
535 | |||
536 | if (gtf_length % REGS_PER_GTF) { | ||
537 | if (ata_msg_drv(ap)) | ||
538 | ata_dev_printk(atadev, KERN_ERR, | ||
539 | "%s: unexpected GTF length (%d)\n", | ||
540 | __FUNCTION__, gtf_length); | ||
541 | goto out; | ||
542 | } | ||
543 | |||
544 | for (ix = 0; ix < gtf_count; ix++) { | ||
545 | gtf = (struct taskfile_array *) | ||
546 | (gtf_address + ix * REGS_PER_GTF); | ||
547 | |||
548 | /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ | ||
549 | taskfile_load_raw(ap, atadev, gtf); | ||
550 | } | ||
551 | |||
552 | err = 0; | ||
553 | out: | ||
554 | return err; | ||
555 | } | ||
556 | |||
557 | /** | ||
558 | * ata_acpi_exec_tfs - get then write drive taskfile settings | ||
559 | * @ap: the ata_port for the drive | ||
560 | * | ||
561 | * This applies to both PATA and SATA drives. | ||
562 | */ | ||
563 | int ata_acpi_exec_tfs(struct ata_port *ap) | ||
564 | { | ||
565 | int ix; | ||
566 | int ret =0; | ||
567 | unsigned int gtf_length; | ||
568 | unsigned long gtf_address; | ||
569 | unsigned long obj_loc; | ||
570 | |||
571 | if (noacpi) | ||
572 | return 0; | ||
573 | |||
574 | for (ix = 0; ix < ATA_MAX_DEVICES; ix++) { | ||
575 | if (!ata_dev_enabled(&ap->device[ix])) | ||
576 | continue; | ||
577 | |||
578 | ret = do_drive_get_GTF(ap, ix, | ||
579 | >f_length, >f_address, &obj_loc); | ||
580 | if (ret < 0) { | ||
581 | if (ata_msg_probe(ap)) | ||
582 | ata_port_printk(ap, KERN_DEBUG, | ||
583 | "%s: get_GTF error (%d)\n", | ||
584 | __FUNCTION__, ret); | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | ret = do_drive_set_taskfiles(ap, &ap->device[ix], | ||
589 | gtf_length, gtf_address); | ||
590 | kfree((void *)obj_loc); | ||
591 | if (ret < 0) { | ||
592 | if (ata_msg_probe(ap)) | ||
593 | ata_port_printk(ap, KERN_DEBUG, | ||
594 | "%s: set_taskfiles error (%d)\n", | ||
595 | __FUNCTION__, ret); | ||
596 | break; | ||
597 | } | ||
598 | } | ||
599 | |||
600 | return ret; | ||
601 | } | ||
602 | |||