aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-acpi.c
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2007-02-07 12:19:37 -0500
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-02-07 12:19:37 -0500
commite3a59b4d9378522479609042836ae930305a67fe (patch)
tree1dd41aefac4d7f370dd3798818c2ca36c654fe7c /drivers/ide/ide-acpi.c
parent78281c5350029e3fa21758d6db9b45ffc7bf72a1 (diff)
ACPI support for IDE devices
This patch implements ACPI integration for generic IDE devices. The ACPI spec mandates that some methods are called during suspend and resume. And consequently there most modern Laptops cannot resume properly without it. According to the spec, we should call '_GTM' (Get Timing) upon suspend to store the current IDE adapter settings. Upon resume we should call '_STM' (Set Timing) to initialize the adapter with the stored settings; afterwards '_GTF' (Get Taskfile) should be called which returns a buffer with some IDE initialisation commands. Those commands should be passed to the drive. There are two module params which control the behaviour of this patch: 'ide=noacpi' Do not call any ACPI methods (Disables any ACPI method calls) 'ide=acpigtf' Enable execution of _GTF methods upon resume. Has no effect if 'ide=noacpi' is set. 'ide=acpionboot' Enable execution of ACPI methods during boot. This might be required on some machines if 'ide=acpigtf' is selected as some machines modify the _GTF information depending on the drive identification passed down with _STM. Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-acpi.c')
-rw-r--r--drivers/ide/ide-acpi.c696
1 files changed, 696 insertions, 0 deletions
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
new file mode 100644
index 00000000000..1eb734951dc
--- /dev/null
+++ b/drivers/ide/ide-acpi.c
@@ -0,0 +1,696 @@
1/*
2 * ide-acpi.c
3 * Provides ACPI support for IDE drives.
4 *
5 * Copyright (C) 2005 Intel Corp.
6 * Copyright (C) 2005 Randy Dunlap
7 * Copyright (C) 2006 SUSE Linux Products GmbH
8 * Copyright (C) 2006 Hannes Reinecke
9 */
10
11#include <linux/ata.h>
12#include <linux/delay.h>
13#include <linux/device.h>
14#include <linux/errno.h>
15#include <linux/kernel.h>
16#include <acpi/acpi.h>
17#include <linux/ide.h>
18#include <linux/pci.h>
19
20#include <acpi/acpi_bus.h>
21#include <acpi/acnames.h>
22#include <acpi/acnamesp.h>
23#include <acpi/acparser.h>
24#include <acpi/acexcep.h>
25#include <acpi/acmacros.h>
26#include <acpi/actypes.h>
27
28#define REGS_PER_GTF 7
29struct taskfile_array {
30 u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
31};
32
33struct GTM_buffer {
34 u32 PIO_speed0;
35 u32 DMA_speed0;
36 u32 PIO_speed1;
37 u32 DMA_speed1;
38 u32 GTM_flags;
39};
40
41struct ide_acpi_drive_link {
42 ide_drive_t *drive;
43 acpi_handle obj_handle;
44 u8 idbuff[512];
45};
46
47struct ide_acpi_hwif_link {
48 ide_hwif_t *hwif;
49 acpi_handle obj_handle;
50 struct GTM_buffer gtm;
51 struct ide_acpi_drive_link master;
52 struct ide_acpi_drive_link slave;
53};
54
55#undef DEBUGGING
56/* note: adds function name and KERN_DEBUG */
57#ifdef DEBUGGING
58#define DEBPRINT(fmt, args...) \
59 printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args)
60#else
61#define DEBPRINT(fmt, args...) do {} while (0)
62#endif /* DEBUGGING */
63
64extern int ide_noacpi;
65extern int ide_noacpitfs;
66extern int ide_noacpionboot;
67
68/**
69 * ide_get_dev_handle - finds acpi_handle and PCI device.function
70 * @dev: device to locate
71 * @handle: returned acpi_handle for @dev
72 * @pcidevfn: return PCI device.func for @dev
73 *
74 * Returns the ACPI object handle to the corresponding PCI device.
75 *
76 * Returns 0 on success, <0 on error.
77 */
78static int ide_get_dev_handle(struct device *dev, acpi_handle *handle,
79 acpi_integer *pcidevfn)
80{
81 struct pci_dev *pdev = to_pci_dev(dev);
82 unsigned int bus, devnum, func;
83 acpi_integer addr;
84 acpi_handle dev_handle;
85 struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
86 .pointer = NULL};
87 acpi_status status;
88 struct acpi_device_info *dinfo = NULL;
89 int ret = -ENODEV;
90
91 bus = pdev->bus->number;
92 devnum = PCI_SLOT(pdev->devfn);
93 func = PCI_FUNC(pdev->devfn);
94 /* ACPI _ADR encoding for PCI bus: */
95 addr = (acpi_integer)(devnum << 16 | func);
96
97 DEBPRINT("ENTER: pci %02x:%02x.%01x\n", bus, devnum, func);
98
99 dev_handle = DEVICE_ACPI_HANDLE(dev);
100 if (!dev_handle) {
101 DEBPRINT("no acpi handle for device\n");
102 goto err;
103 }
104
105 status = acpi_get_object_info(dev_handle, &buffer);
106 if (ACPI_FAILURE(status)) {
107 DEBPRINT("get_object_info for device failed\n");
108 goto err;
109 }
110 dinfo = buffer.pointer;
111 if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
112 dinfo->address == addr) {
113 *pcidevfn = addr;
114 *handle = dev_handle;
115 } else {
116 DEBPRINT("get_object_info for device has wrong "
117 " address: %llu, should be %u\n",
118 dinfo ? (unsigned long long)dinfo->address : -1ULL,
119 (unsigned int)addr);
120 goto err;
121 }
122
123 DEBPRINT("for dev=0x%x.%x, addr=0x%llx, *handle=0x%p\n",
124 devnum, func, (unsigned long long)addr, *handle);
125 ret = 0;
126err:
127 kfree(dinfo);
128 return ret;
129}
130
131/**
132 * ide_acpi_hwif_get_handle - Get ACPI object handle for a given hwif
133 * @hwif: device to locate
134 *
135 * Retrieves the object handle for a given hwif.
136 *
137 * Returns handle on success, 0 on error.
138 */
139static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif)
140{
141 struct device *dev = hwif->gendev.parent;
142 acpi_handle dev_handle;
143 acpi_integer pcidevfn;
144 acpi_handle chan_handle;
145 int err;
146
147 DEBPRINT("ENTER: device %s\n", hwif->name);
148
149 if (!dev) {
150 DEBPRINT("no PCI device for %s\n", hwif->name);
151 return NULL;
152 }
153
154 err = ide_get_dev_handle(dev, &dev_handle, &pcidevfn);
155 if (err < 0) {
156 DEBPRINT("ide_get_dev_handle failed (%d)\n", err);
157 return NULL;
158 }
159
160 /* get child objects of dev_handle == channel objects,
161 * + _their_ children == drive objects */
162 /* channel is hwif->channel */
163 chan_handle = acpi_get_child(dev_handle, hwif->channel);
164 DEBPRINT("chan adr=%d: handle=0x%p\n",
165 hwif->channel, chan_handle);
166
167 return chan_handle;
168}
169
170/**
171 * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive
172 * @drive: device to locate
173 *
174 * Retrieves the object handle of a given drive. According to the ACPI
175 * spec the drive is a child of the hwif.
176 *
177 * Returns handle on success, 0 on error.
178 */
179static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive)
180{
181 ide_hwif_t *hwif = HWIF(drive);
182 int port;
183 acpi_handle drive_handle;
184
185 if (!hwif->acpidata)
186 return NULL;
187
188 if (!hwif->acpidata->obj_handle)
189 return NULL;
190
191 port = hwif->channel ? drive->dn - 2: drive->dn;
192
193 DEBPRINT("ENTER: %s at channel#: %d port#: %d\n",
194 drive->name, hwif->channel, port);
195
196
197 /* TBD: could also check ACPI object VALID bits */
198 drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port);
199 DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle);
200
201 return drive_handle;
202}
203
204/**
205 * do_drive_get_GTF - get the drive bootup default taskfile settings
206 * @drive: the drive for which the taskfile settings should be retrieved
207 * @gtf_length: number of bytes of _GTF data returned at @gtf_address
208 * @gtf_address: buffer containing _GTF taskfile arrays
209 *
210 * The _GTF method has no input parameters.
211 * It returns a variable number of register set values (registers
212 * hex 1F1..1F7, taskfiles).
213 * The <variable number> is not known in advance, so have ACPI-CA
214 * allocate the buffer as needed and return it, then free it later.
215 *
216 * The returned @gtf_length and @gtf_address are only valid if the
217 * function return value is 0.
218 */
219static int do_drive_get_GTF(ide_drive_t *drive,
220 unsigned int *gtf_length, unsigned long *gtf_address,
221 unsigned long *obj_loc)
222{
223 acpi_status status;
224 struct acpi_buffer output;
225 union acpi_object *out_obj;
226 ide_hwif_t *hwif = HWIF(drive);
227 struct device *dev = hwif->gendev.parent;
228 int err = -ENODEV;
229 int port;
230
231 *gtf_length = 0;
232 *gtf_address = 0UL;
233 *obj_loc = 0UL;
234
235 if (ide_noacpi)
236 return 0;
237
238 if (!dev) {
239 DEBPRINT("no PCI device for %s\n", hwif->name);
240 goto out;
241 }
242
243 if (!hwif->acpidata) {
244 DEBPRINT("no ACPI data for %s\n", hwif->name);
245 goto out;
246 }
247
248 port = hwif->channel ? drive->dn - 2: drive->dn;
249
250 if (!drive->acpidata) {
251 if (port == 0) {
252 drive->acpidata = &hwif->acpidata->master;
253 hwif->acpidata->master.drive = drive;
254 } else {
255 drive->acpidata = &hwif->acpidata->slave;
256 hwif->acpidata->slave.drive = drive;
257 }
258 }
259
260 DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
261 hwif->name, dev->bus_id, port, hwif->channel);
262
263 if (!drive->present) {
264 DEBPRINT("%s drive %d:%d not present\n",
265 hwif->name, hwif->channel, port);
266 goto out;
267 }
268
269 /* Get this drive's _ADR info. if not already known. */
270 if (!drive->acpidata->obj_handle) {
271 drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
272 if (!drive->acpidata->obj_handle) {
273 DEBPRINT("No ACPI object found for %s\n",
274 drive->name);
275 goto out;
276 }
277 }
278
279 /* Setting up output buffer */
280 output.length = ACPI_ALLOCATE_BUFFER;
281 output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
282
283 /* _GTF has no input parameters */
284 err = -EIO;
285 status = acpi_evaluate_object(drive->acpidata->obj_handle, "_GTF",
286 NULL, &output);
287 if (ACPI_FAILURE(status)) {
288 printk(KERN_DEBUG
289 "%s: Run _GTF error: status = 0x%x\n",
290 __FUNCTION__, status);
291 goto out;
292 }
293
294 if (!output.length || !output.pointer) {
295 DEBPRINT("Run _GTF: "
296 "length or ptr is NULL (0x%llx, 0x%p)\n",
297 (unsigned long long)output.length,
298 output.pointer);
299 goto out;
300 }
301
302 out_obj = output.pointer;
303 if (out_obj->type != ACPI_TYPE_BUFFER) {
304 DEBPRINT("Run _GTF: error: "
305 "expected object type of ACPI_TYPE_BUFFER, "
306 "got 0x%x\n", out_obj->type);
307 err = -ENOENT;
308 kfree(output.pointer);
309 goto out;
310 }
311
312 if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
313 out_obj->buffer.length % REGS_PER_GTF) {
314 printk(KERN_ERR
315 "%s: unexpected GTF length (%d) or addr (0x%p)\n",
316 __FUNCTION__, out_obj->buffer.length,
317 out_obj->buffer.pointer);
318 err = -ENOENT;
319 kfree(output.pointer);
320 goto out;
321 }
322
323 *gtf_length = out_obj->buffer.length;
324 *gtf_address = (unsigned long)out_obj->buffer.pointer;
325 *obj_loc = (unsigned long)out_obj;
326 DEBPRINT("returning gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
327 *gtf_length, *gtf_address, *obj_loc);
328 err = 0;
329out:
330 return err;
331}
332
333/**
334 * taskfile_load_raw - send taskfile registers to drive
335 * @drive: drive to which output is sent
336 * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
337 *
338 * Outputs IDE taskfile to the drive.
339 */
340static int taskfile_load_raw(ide_drive_t *drive,
341 const struct taskfile_array *gtf)
342{
343 ide_task_t args;
344 int err = 0;
345
346 DEBPRINT("(0x1f1-1f7): hex: "
347 "%02x %02x %02x %02x %02x %02x %02x\n",
348 gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
349 gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
350
351 memset(&args, 0, sizeof(ide_task_t));
352 args.command_type = IDE_DRIVE_TASK_NO_DATA;
353 args.data_phase = TASKFILE_IN;
354 args.handler = &task_no_data_intr;
355
356 /* convert gtf to IDE Taskfile */
357 args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */
358 args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */
359 args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */
360 args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */
361 args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */
362 args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */
363 args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */
364
365 if (ide_noacpitfs) {
366 DEBPRINT("_GTF execution disabled\n");
367 return err;
368 }
369
370 err = ide_raw_taskfile(drive, &args, NULL);
371 if (err)
372 printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n",
373 __FUNCTION__, err);
374
375 return err;
376}
377
378/**
379 * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
380 * @drive: the drive to which the taskfile command should be sent
381 * @gtf_length: total number of bytes of _GTF taskfiles
382 * @gtf_address: location of _GTF taskfile arrays
383 *
384 * Write {gtf_address, length gtf_length} in groups of
385 * REGS_PER_GTF bytes.
386 */
387static int do_drive_set_taskfiles(ide_drive_t *drive,
388 unsigned int gtf_length,
389 unsigned long gtf_address)
390{
391 int rc = -ENODEV, err;
392 int gtf_count = gtf_length / REGS_PER_GTF;
393 int ix;
394 struct taskfile_array *gtf;
395
396 if (ide_noacpi)
397 return 0;
398
399 DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn);
400
401 if (!drive->present)
402 goto out;
403 if (!gtf_count) /* shouldn't be here */
404 goto out;
405
406 DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n",
407 gtf_length, gtf_length, gtf_count, gtf_address);
408
409 if (gtf_length % REGS_PER_GTF) {
410 printk(KERN_ERR "%s: unexpected GTF length (%d)\n",
411 __FUNCTION__, gtf_length);
412 goto out;
413 }
414
415 rc = 0;
416 for (ix = 0; ix < gtf_count; ix++) {
417 gtf = (struct taskfile_array *)
418 (gtf_address + ix * REGS_PER_GTF);
419
420 /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
421 err = taskfile_load_raw(drive, gtf);
422 if (err)
423 rc = err;
424 }
425
426out:
427 return rc;
428}
429
430/**
431 * ide_acpi_exec_tfs - get then write drive taskfile settings
432 * @drive: the drive for which the taskfile settings should be
433 * written.
434 *
435 * According to the ACPI spec this should be called after _STM
436 * has been evaluated for the interface. Some ACPI vendors interpret
437 * that as a hard requirement and modify the taskfile according
438 * to the Identify Drive information passed down with _STM.
439 * So one should really make sure to call this only after _STM has
440 * been executed.
441 */
442int ide_acpi_exec_tfs(ide_drive_t *drive)
443{
444 int ret;
445 unsigned int gtf_length;
446 unsigned long gtf_address;
447 unsigned long obj_loc;
448
449 if (ide_noacpi)
450 return 0;
451
452 DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn);
453
454 ret = do_drive_get_GTF(drive, &gtf_length, &gtf_address, &obj_loc);
455 if (ret < 0) {
456 DEBPRINT("get_GTF error (%d)\n", ret);
457 return ret;
458 }
459
460 DEBPRINT("call set_taskfiles, drive=%s\n", drive->name);
461
462 ret = do_drive_set_taskfiles(drive, gtf_length, gtf_address);
463 kfree((void *)obj_loc);
464 if (ret < 0) {
465 DEBPRINT("set_taskfiles error (%d)\n", ret);
466 }
467
468 DEBPRINT("ret=%d\n", ret);
469
470 return ret;
471}
472EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs);
473
474/**
475 * ide_acpi_get_timing - get the channel (controller) timings
476 * @hwif: target IDE interface (channel)
477 *
478 * This function executes the _GTM ACPI method for the target channel.
479 *
480 */
481void ide_acpi_get_timing(ide_hwif_t *hwif)
482{
483 acpi_status status;
484 struct acpi_buffer output;
485 union acpi_object *out_obj;
486
487 if (ide_noacpi)
488 return;
489
490 DEBPRINT("ENTER:\n");
491
492 if (!hwif->acpidata) {
493 DEBPRINT("no ACPI data for %s\n", hwif->name);
494 return;
495 }
496
497 /* Setting up output buffer for _GTM */
498 output.length = ACPI_ALLOCATE_BUFFER;
499 output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
500
501 /* _GTM has no input parameters */
502 status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_GTM",
503 NULL, &output);
504
505 DEBPRINT("_GTM status: %d, outptr: 0x%p, outlen: 0x%llx\n",
506 status, output.pointer,
507 (unsigned long long)output.length);
508
509 if (ACPI_FAILURE(status)) {
510 DEBPRINT("Run _GTM error: status = 0x%x\n", status);
511 return;
512 }
513
514 if (!output.length || !output.pointer) {
515 DEBPRINT("Run _GTM: length or ptr is NULL (0x%llx, 0x%p)\n",
516 (unsigned long long)output.length,
517 output.pointer);
518 kfree(output.pointer);
519 return;
520 }
521
522 out_obj = output.pointer;
523 if (out_obj->type != ACPI_TYPE_BUFFER) {
524 kfree(output.pointer);
525 DEBPRINT("Run _GTM: error: "
526 "expected object type of ACPI_TYPE_BUFFER, "
527 "got 0x%x\n", out_obj->type);
528 return;
529 }
530
531 if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
532 out_obj->buffer.length != sizeof(struct GTM_buffer)) {
533 kfree(output.pointer);
534 printk(KERN_ERR
535 "%s: unexpected _GTM length (0x%x)[should be 0x%x] or addr (0x%p)\n",
536 __FUNCTION__, out_obj->buffer.length,
537 sizeof(struct GTM_buffer), out_obj->buffer.pointer);
538 return;
539 }
540
541 memcpy(&hwif->acpidata->gtm, out_obj->buffer.pointer,
542 sizeof(struct GTM_buffer));
543
544 DEBPRINT("_GTM info: ptr: 0x%p, len: 0x%x, exp.len: 0x%Zx\n",
545 out_obj->buffer.pointer, out_obj->buffer.length,
546 sizeof(struct GTM_buffer));
547
548 DEBPRINT("_GTM fields: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
549 hwif->acpidata->gtm.PIO_speed0,
550 hwif->acpidata->gtm.DMA_speed0,
551 hwif->acpidata->gtm.PIO_speed1,
552 hwif->acpidata->gtm.DMA_speed1,
553 hwif->acpidata->gtm.GTM_flags);
554
555 kfree(output.pointer);
556}
557EXPORT_SYMBOL_GPL(ide_acpi_get_timing);
558
559/**
560 * ide_acpi_push_timing - set the channel (controller) timings
561 * @hwif: target IDE interface (channel)
562 *
563 * This function executes the _STM ACPI method for the target channel.
564 *
565 * _STM requires Identify Drive data, which has to passed as an argument.
566 * Unfortunately hd_driveid is a mangled version which we can't readily
567 * use; hence we'll get the information afresh.
568 */
569void ide_acpi_push_timing(ide_hwif_t *hwif)
570{
571 acpi_status status;
572 struct acpi_object_list input;
573 union acpi_object in_params[3];
574 struct ide_acpi_drive_link *master = &hwif->acpidata->master;
575 struct ide_acpi_drive_link *slave = &hwif->acpidata->slave;
576
577 if (ide_noacpi)
578 return;
579
580 DEBPRINT("ENTER:\n");
581
582 if (!hwif->acpidata) {
583 DEBPRINT("no ACPI data for %s\n", hwif->name);
584 return;
585 }
586
587 /* Give the GTM buffer + drive Identify data to the channel via the
588 * _STM method: */
589 /* setup input parameters buffer for _STM */
590 input.count = 3;
591 input.pointer = in_params;
592 in_params[0].type = ACPI_TYPE_BUFFER;
593 in_params[0].buffer.length = sizeof(struct GTM_buffer);
594 in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm;
595 in_params[1].type = ACPI_TYPE_BUFFER;
596 in_params[1].buffer.length = sizeof(struct hd_driveid);
597 in_params[1].buffer.pointer = (u8 *)&master->idbuff;
598 in_params[2].type = ACPI_TYPE_BUFFER;
599 in_params[2].buffer.length = sizeof(struct hd_driveid);
600 in_params[2].buffer.pointer = (u8 *)&slave->idbuff;
601 /* Output buffer: _STM has no output */
602
603 status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_STM",
604 &input, NULL);
605
606 if (ACPI_FAILURE(status)) {
607 DEBPRINT("Run _STM error: status = 0x%x\n", status);
608 }
609 DEBPRINT("_STM status: %d\n", status);
610}
611EXPORT_SYMBOL_GPL(ide_acpi_push_timing);
612
613/**
614 * ide_acpi_init - initialize the ACPI link for an IDE interface
615 * @hwif: target IDE interface (channel)
616 *
617 * The ACPI spec is not quite clear when the drive identify buffer
618 * should be obtained. Calling IDENTIFY DEVICE during shutdown
619 * is not the best of ideas as the drive might already being put to
620 * sleep. And obviously we can't call it during resume.
621 * So we get the information during startup; but this means that
622 * any changes during run-time will be lost after resume.
623 */
624void ide_acpi_init(ide_hwif_t *hwif)
625{
626 int unit;
627 int err;
628 struct ide_acpi_drive_link *master;
629 struct ide_acpi_drive_link *slave;
630
631 hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL);
632 if (!hwif->acpidata)
633 return;
634
635 hwif->acpidata->obj_handle = ide_acpi_hwif_get_handle(hwif);
636 if (!hwif->acpidata->obj_handle) {
637 DEBPRINT("no ACPI object for %s found\n", hwif->name);
638 kfree(hwif->acpidata);
639 hwif->acpidata = NULL;
640 return;
641 }
642
643 /*
644 * The ACPI spec mandates that we send information
645 * for both drives, regardless whether they are connected
646 * or not.
647 */
648 hwif->acpidata->master.drive = &hwif->drives[0];
649 hwif->drives[0].acpidata = &hwif->acpidata->master;
650 master = &hwif->acpidata->master;
651
652 hwif->acpidata->slave.drive = &hwif->drives[1];
653 hwif->drives[1].acpidata = &hwif->acpidata->slave;
654 slave = &hwif->acpidata->slave;
655
656
657 /*
658 * Send IDENTIFY for each drive
659 */
660 if (master->drive->present) {
661 err = taskfile_lib_get_identify(master->drive, master->idbuff);
662 if (err) {
663 DEBPRINT("identify device %s failed (%d)\n",
664 master->drive->name, err);
665 }
666 }
667
668 if (slave->drive->present) {
669 err = taskfile_lib_get_identify(slave->drive, slave->idbuff);
670 if (err) {
671 DEBPRINT("identify device %s failed (%d)\n",
672 slave->drive->name, err);
673 }
674 }
675
676 if (ide_noacpionboot) {
677 DEBPRINT("ACPI methods disabled on boot\n");
678 return;
679 }
680
681 /*
682 * ACPI requires us to call _STM on startup
683 */
684 ide_acpi_get_timing(hwif);
685 ide_acpi_push_timing(hwif);
686
687 for (unit = 0; unit < MAX_DRIVES; ++unit) {
688 ide_drive_t *drive = &hwif->drives[unit];
689
690 if (drive->present) {
691 /* Execute ACPI startup code */
692 ide_acpi_exec_tfs(drive);
693 }
694 }
695}
696EXPORT_SYMBOL_GPL(ide_acpi_init);