diff options
Diffstat (limited to 'drivers/ide/ide-acpi.c')
-rw-r--r-- | drivers/ide/ide-acpi.c | 214 |
1 files changed, 52 insertions, 162 deletions
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index ec7d07fa570a..5b704f1ea90c 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c | |||
@@ -20,9 +20,6 @@ | |||
20 | #include <acpi/acpi_bus.h> | 20 | #include <acpi/acpi_bus.h> |
21 | 21 | ||
22 | #define REGS_PER_GTF 7 | 22 | #define REGS_PER_GTF 7 |
23 | struct taskfile_array { | ||
24 | u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ | ||
25 | }; | ||
26 | 23 | ||
27 | struct GTM_buffer { | 24 | struct GTM_buffer { |
28 | u32 PIO_speed0; | 25 | u32 PIO_speed0; |
@@ -89,12 +86,8 @@ static const struct dmi_system_id ide_acpi_dmi_table[] = { | |||
89 | { } /* terminate list */ | 86 | { } /* terminate list */ |
90 | }; | 87 | }; |
91 | 88 | ||
92 | static int ide_acpi_blacklist(void) | 89 | int ide_acpi_init(void) |
93 | { | 90 | { |
94 | static int done; | ||
95 | if (done) | ||
96 | return 0; | ||
97 | done = 1; | ||
98 | dmi_check_system(ide_acpi_dmi_table); | 91 | dmi_check_system(ide_acpi_dmi_table); |
99 | return 0; | 92 | return 0; |
100 | } | 93 | } |
@@ -202,40 +195,6 @@ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) | |||
202 | } | 195 | } |
203 | 196 | ||
204 | /** | 197 | /** |
205 | * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive | ||
206 | * @drive: device to locate | ||
207 | * | ||
208 | * Retrieves the object handle of a given drive. According to the ACPI | ||
209 | * spec the drive is a child of the hwif. | ||
210 | * | ||
211 | * Returns handle on success, 0 on error. | ||
212 | */ | ||
213 | static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive) | ||
214 | { | ||
215 | ide_hwif_t *hwif = drive->hwif; | ||
216 | int port; | ||
217 | acpi_handle drive_handle; | ||
218 | |||
219 | if (!hwif->acpidata) | ||
220 | return NULL; | ||
221 | |||
222 | if (!hwif->acpidata->obj_handle) | ||
223 | return NULL; | ||
224 | |||
225 | port = hwif->channel ? drive->dn - 2: drive->dn; | ||
226 | |||
227 | DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", | ||
228 | drive->name, hwif->channel, port); | ||
229 | |||
230 | |||
231 | /* TBD: could also check ACPI object VALID bits */ | ||
232 | drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port); | ||
233 | DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle); | ||
234 | |||
235 | return drive_handle; | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * do_drive_get_GTF - get the drive bootup default taskfile settings | 198 | * do_drive_get_GTF - get the drive bootup default taskfile settings |
240 | * @drive: the drive for which the taskfile settings should be retrieved | 199 | * @drive: the drive for which the taskfile settings should be retrieved |
241 | * @gtf_length: number of bytes of _GTF data returned at @gtf_address | 200 | * @gtf_length: number of bytes of _GTF data returned at @gtf_address |
@@ -257,47 +216,15 @@ static int do_drive_get_GTF(ide_drive_t *drive, | |||
257 | acpi_status status; | 216 | acpi_status status; |
258 | struct acpi_buffer output; | 217 | struct acpi_buffer output; |
259 | union acpi_object *out_obj; | 218 | union acpi_object *out_obj; |
260 | ide_hwif_t *hwif = drive->hwif; | ||
261 | struct device *dev = hwif->gendev.parent; | ||
262 | int err = -ENODEV; | 219 | int err = -ENODEV; |
263 | int port; | ||
264 | 220 | ||
265 | *gtf_length = 0; | 221 | *gtf_length = 0; |
266 | *gtf_address = 0UL; | 222 | *gtf_address = 0UL; |
267 | *obj_loc = 0UL; | 223 | *obj_loc = 0UL; |
268 | 224 | ||
269 | if (ide_noacpi) | ||
270 | return 0; | ||
271 | |||
272 | if (!dev) { | ||
273 | DEBPRINT("no PCI device for %s\n", hwif->name); | ||
274 | goto out; | ||
275 | } | ||
276 | |||
277 | if (!hwif->acpidata) { | ||
278 | DEBPRINT("no ACPI data for %s\n", hwif->name); | ||
279 | goto out; | ||
280 | } | ||
281 | |||
282 | port = hwif->channel ? drive->dn - 2: drive->dn; | ||
283 | |||
284 | DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", | ||
285 | hwif->name, dev_name(dev), port, hwif->channel); | ||
286 | |||
287 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) { | ||
288 | DEBPRINT("%s drive %d:%d not present\n", | ||
289 | hwif->name, hwif->channel, port); | ||
290 | goto out; | ||
291 | } | ||
292 | |||
293 | /* Get this drive's _ADR info. if not already known. */ | ||
294 | if (!drive->acpidata->obj_handle) { | 225 | if (!drive->acpidata->obj_handle) { |
295 | drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); | 226 | DEBPRINT("No ACPI object found for %s\n", drive->name); |
296 | if (!drive->acpidata->obj_handle) { | 227 | goto out; |
297 | DEBPRINT("No ACPI object found for %s\n", | ||
298 | drive->name); | ||
299 | goto out; | ||
300 | } | ||
301 | } | 228 | } |
302 | 229 | ||
303 | /* Setting up output buffer */ | 230 | /* Setting up output buffer */ |
@@ -355,43 +282,6 @@ out: | |||
355 | } | 282 | } |
356 | 283 | ||
357 | /** | 284 | /** |
358 | * taskfile_load_raw - send taskfile registers to drive | ||
359 | * @drive: drive to which output is sent | ||
360 | * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) | ||
361 | * | ||
362 | * Outputs IDE taskfile to the drive. | ||
363 | */ | ||
364 | static int taskfile_load_raw(ide_drive_t *drive, | ||
365 | const struct taskfile_array *gtf) | ||
366 | { | ||
367 | ide_task_t args; | ||
368 | int err = 0; | ||
369 | |||
370 | DEBPRINT("(0x1f1-1f7): hex: " | ||
371 | "%02x %02x %02x %02x %02x %02x %02x\n", | ||
372 | gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], | ||
373 | gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); | ||
374 | |||
375 | memset(&args, 0, sizeof(ide_task_t)); | ||
376 | |||
377 | /* convert gtf to IDE Taskfile */ | ||
378 | memcpy(&args.tf_array[7], >f->tfa, 7); | ||
379 | args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | ||
380 | |||
381 | if (!ide_acpigtf) { | ||
382 | DEBPRINT("_GTF execution disabled\n"); | ||
383 | return err; | ||
384 | } | ||
385 | |||
386 | err = ide_no_data_taskfile(drive, &args); | ||
387 | if (err) | ||
388 | printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n", | ||
389 | __func__, err); | ||
390 | |||
391 | return err; | ||
392 | } | ||
393 | |||
394 | /** | ||
395 | * do_drive_set_taskfiles - write the drive taskfile settings from _GTF | 285 | * do_drive_set_taskfiles - write the drive taskfile settings from _GTF |
396 | * @drive: the drive to which the taskfile command should be sent | 286 | * @drive: the drive to which the taskfile command should be sent |
397 | * @gtf_length: total number of bytes of _GTF taskfiles | 287 | * @gtf_length: total number of bytes of _GTF taskfiles |
@@ -404,43 +294,41 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, | |||
404 | unsigned int gtf_length, | 294 | unsigned int gtf_length, |
405 | unsigned long gtf_address) | 295 | unsigned long gtf_address) |
406 | { | 296 | { |
407 | int rc = -ENODEV, err; | 297 | int rc = 0, err; |
408 | int gtf_count = gtf_length / REGS_PER_GTF; | 298 | int gtf_count = gtf_length / REGS_PER_GTF; |
409 | int ix; | 299 | int ix; |
410 | struct taskfile_array *gtf; | ||
411 | |||
412 | if (ide_noacpi) | ||
413 | return 0; | ||
414 | |||
415 | DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn); | ||
416 | |||
417 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) | ||
418 | goto out; | ||
419 | |||
420 | if (!gtf_count) /* shouldn't be here */ | ||
421 | goto out; | ||
422 | 300 | ||
423 | DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", | 301 | DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", |
424 | gtf_length, gtf_length, gtf_count, gtf_address); | 302 | gtf_length, gtf_length, gtf_count, gtf_address); |
425 | 303 | ||
426 | if (gtf_length % REGS_PER_GTF) { | 304 | /* send all taskfile registers (0x1f1-0x1f7) *in*that*order* */ |
427 | printk(KERN_ERR "%s: unexpected GTF length (%d)\n", | ||
428 | __func__, gtf_length); | ||
429 | goto out; | ||
430 | } | ||
431 | |||
432 | rc = 0; | ||
433 | for (ix = 0; ix < gtf_count; ix++) { | 305 | for (ix = 0; ix < gtf_count; ix++) { |
434 | gtf = (struct taskfile_array *) | 306 | u8 *gtf = (u8 *)(gtf_address + ix * REGS_PER_GTF); |
435 | (gtf_address + ix * REGS_PER_GTF); | 307 | ide_task_t task; |
436 | 308 | ||
437 | /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ | 309 | DEBPRINT("(0x1f1-1f7): " |
438 | err = taskfile_load_raw(drive, gtf); | 310 | "hex: %02x %02x %02x %02x %02x %02x %02x\n", |
439 | if (err) | 311 | gtf[0], gtf[1], gtf[2], |
312 | gtf[3], gtf[4], gtf[5], gtf[6]); | ||
313 | |||
314 | if (!ide_acpigtf) { | ||
315 | DEBPRINT("_GTF execution disabled\n"); | ||
316 | continue; | ||
317 | } | ||
318 | |||
319 | /* convert GTF to taskfile */ | ||
320 | memset(&task, 0, sizeof(ide_task_t)); | ||
321 | memcpy(&task.tf_array[7], gtf, REGS_PER_GTF); | ||
322 | task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | ||
323 | |||
324 | err = ide_no_data_taskfile(drive, &task); | ||
325 | if (err) { | ||
326 | printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n", | ||
327 | __func__, err); | ||
440 | rc = err; | 328 | rc = err; |
329 | } | ||
441 | } | 330 | } |
442 | 331 | ||
443 | out: | ||
444 | return rc; | 332 | return rc; |
445 | } | 333 | } |
446 | 334 | ||
@@ -647,26 +535,23 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) | |||
647 | DEBPRINT("no ACPI data for %s\n", hwif->name); | 535 | DEBPRINT("no ACPI data for %s\n", hwif->name); |
648 | return; | 536 | return; |
649 | } | 537 | } |
538 | |||
650 | /* channel first and then drives for power on and verse versa for power off */ | 539 | /* channel first and then drives for power on and verse versa for power off */ |
651 | if (on) | 540 | if (on) |
652 | acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); | 541 | acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); |
653 | 542 | ||
654 | ide_port_for_each_dev(i, drive, hwif) { | 543 | ide_port_for_each_present_dev(i, drive, hwif) { |
655 | if (!drive->acpidata->obj_handle) | 544 | if (drive->acpidata->obj_handle) |
656 | drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); | ||
657 | |||
658 | if (drive->acpidata->obj_handle && | ||
659 | (drive->dev_flags & IDE_DFLAG_PRESENT)) { | ||
660 | acpi_bus_set_power(drive->acpidata->obj_handle, | 545 | acpi_bus_set_power(drive->acpidata->obj_handle, |
661 | on? ACPI_STATE_D0: ACPI_STATE_D3); | 546 | on ? ACPI_STATE_D0 : ACPI_STATE_D3); |
662 | } | ||
663 | } | 547 | } |
548 | |||
664 | if (!on) | 549 | if (!on) |
665 | acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3); | 550 | acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3); |
666 | } | 551 | } |
667 | 552 | ||
668 | /** | 553 | /** |
669 | * ide_acpi_init - initialize the ACPI link for an IDE interface | 554 | * ide_acpi_init_port - initialize the ACPI link for an IDE interface |
670 | * @hwif: target IDE interface (channel) | 555 | * @hwif: target IDE interface (channel) |
671 | * | 556 | * |
672 | * The ACPI spec is not quite clear when the drive identify buffer | 557 | * The ACPI spec is not quite clear when the drive identify buffer |
@@ -676,10 +561,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) | |||
676 | * So we get the information during startup; but this means that | 561 | * So we get the information during startup; but this means that |
677 | * any changes during run-time will be lost after resume. | 562 | * any changes during run-time will be lost after resume. |
678 | */ | 563 | */ |
679 | void ide_acpi_init(ide_hwif_t *hwif) | 564 | void ide_acpi_init_port(ide_hwif_t *hwif) |
680 | { | 565 | { |
681 | ide_acpi_blacklist(); | ||
682 | |||
683 | hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); | 566 | hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); |
684 | if (!hwif->acpidata) | 567 | if (!hwif->acpidata) |
685 | return; | 568 | return; |
@@ -708,15 +591,24 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) | |||
708 | hwif->devices[0]->acpidata = &hwif->acpidata->master; | 591 | hwif->devices[0]->acpidata = &hwif->acpidata->master; |
709 | hwif->devices[1]->acpidata = &hwif->acpidata->slave; | 592 | hwif->devices[1]->acpidata = &hwif->acpidata->slave; |
710 | 593 | ||
711 | /* | 594 | /* get _ADR info for each device */ |
712 | * Send IDENTIFY for each drive | 595 | ide_port_for_each_present_dev(i, drive, hwif) { |
713 | */ | 596 | acpi_handle dev_handle; |
714 | ide_port_for_each_dev(i, drive, hwif) { | ||
715 | memset(drive->acpidata, 0, sizeof(*drive->acpidata)); | ||
716 | 597 | ||
717 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) | 598 | DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", |
718 | continue; | 599 | drive->name, hwif->channel, drive->dn & 1); |
600 | |||
601 | /* TBD: could also check ACPI object VALID bits */ | ||
602 | dev_handle = acpi_get_child(hwif->acpidata->obj_handle, | ||
603 | drive->dn & 1); | ||
604 | |||
605 | DEBPRINT("drive %s handle 0x%p\n", drive->name, dev_handle); | ||
606 | |||
607 | drive->acpidata->obj_handle = dev_handle; | ||
608 | } | ||
719 | 609 | ||
610 | /* send IDENTIFY for each device */ | ||
611 | ide_port_for_each_present_dev(i, drive, hwif) { | ||
720 | err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff); | 612 | err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff); |
721 | if (err) | 613 | if (err) |
722 | DEBPRINT("identify device %s failed (%d)\n", | 614 | DEBPRINT("identify device %s failed (%d)\n", |
@@ -736,9 +628,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) | |||
736 | ide_acpi_get_timing(hwif); | 628 | ide_acpi_get_timing(hwif); |
737 | ide_acpi_push_timing(hwif); | 629 | ide_acpi_push_timing(hwif); |
738 | 630 | ||
739 | ide_port_for_each_dev(i, drive, hwif) { | 631 | ide_port_for_each_present_dev(i, drive, hwif) { |
740 | if (drive->dev_flags & IDE_DFLAG_PRESENT) | 632 | ide_acpi_exec_tfs(drive); |
741 | /* Execute ACPI startup code */ | ||
742 | ide_acpi_exec_tfs(drive); | ||
743 | } | 633 | } |
744 | } | 634 | } |