]>
Commit | Line | Data |
---|---|---|
2127e193 GI |
1 | /* |
2 | * dev_ata_cmd_set.cpp | |
3 | * | |
a86ec89e | 4 | * Home page of code is: http://www.smartmontools.org |
2127e193 | 5 | * |
ff28b140 | 6 | * Copyright (C) 2008-18 Christian Franke |
2127e193 | 7 | * |
ff28b140 | 8 | * SPDX-License-Identifier: GPL-2.0-or-later |
2127e193 GI |
9 | */ |
10 | ||
11 | #include "config.h" | |
ff28b140 | 12 | |
2127e193 GI |
13 | #include "atacmds.h" |
14 | #include "dev_ata_cmd_set.h" | |
15 | ||
16 | #include <errno.h> | |
17 | ||
ff28b140 | 18 | const char * dev_ata_cmd_set_cpp_cvsid = "$Id: dev_ata_cmd_set.cpp 4760 2018-08-19 18:45:53Z chrfranke $" |
2127e193 GI |
19 | DEV_ATA_CMD_SET_H_CVSID; |
20 | ||
21 | ||
22 | ///////////////////////////////////////////////////////////////////////////// | |
23 | // ata_device_with_command_set | |
24 | ||
25 | // Adapter routine to implement new ATA pass through with old interface | |
26 | ||
27 | bool ata_device_with_command_set::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) | |
28 | { | |
29 | if (!ata_cmd_is_ok(in, true)) // data_out_support | |
30 | return false; | |
31 | ||
32 | smart_command_set command = (smart_command_set)-1; | |
33 | int select = 0; | |
34 | char * data = (char *)in.buffer; | |
35 | char buffer[512]; | |
36 | switch (in.in_regs.command) { | |
37 | case ATA_IDENTIFY_DEVICE: | |
38 | command = IDENTIFY; | |
39 | break; | |
40 | case ATA_IDENTIFY_PACKET_DEVICE: | |
41 | command = PIDENTIFY; | |
42 | break; | |
43 | case ATA_CHECK_POWER_MODE: | |
44 | command = CHECK_POWER_MODE; | |
45 | data = buffer; data[0] = 0; | |
46 | break; | |
47 | case ATA_SMART_CMD: | |
48 | switch (in.in_regs.features) { | |
49 | case ATA_SMART_ENABLE: | |
50 | command = ENABLE; | |
51 | break; | |
52 | case ATA_SMART_READ_VALUES: | |
53 | command = READ_VALUES; | |
54 | break; | |
55 | case ATA_SMART_READ_THRESHOLDS: | |
56 | command = READ_THRESHOLDS; | |
57 | break; | |
58 | case ATA_SMART_READ_LOG_SECTOR: | |
59 | command = READ_LOG; | |
60 | select = in.in_regs.lba_low; | |
61 | break; | |
62 | case ATA_SMART_WRITE_LOG_SECTOR: | |
63 | command = WRITE_LOG; | |
64 | select = in.in_regs.lba_low; | |
65 | break; | |
66 | case ATA_SMART_DISABLE: | |
67 | command = DISABLE; | |
68 | break; | |
69 | case ATA_SMART_STATUS: | |
70 | command = (in.out_needed.lba_high ? STATUS_CHECK : STATUS); | |
71 | break; | |
72 | case ATA_SMART_AUTO_OFFLINE: | |
73 | command = AUTO_OFFLINE; | |
74 | select = in.in_regs.sector_count; | |
75 | break; | |
76 | case ATA_SMART_AUTOSAVE: | |
77 | command = AUTOSAVE; | |
78 | select = in.in_regs.sector_count; | |
79 | break; | |
80 | case ATA_SMART_IMMEDIATE_OFFLINE: | |
81 | command = IMMEDIATE_OFFLINE; | |
82 | select = in.in_regs.lba_low; | |
83 | break; | |
84 | default: | |
85 | return set_err(ENOSYS, "Unknown SMART command"); | |
86 | } | |
87 | break; | |
88 | default: | |
89 | return set_err(ENOSYS, "Non-SMART commands not implemented"); | |
90 | } | |
91 | ||
92 | clear_err(); errno = 0; | |
93 | int rc = ata_command_interface(command, select, data); | |
94 | if (rc < 0) { | |
95 | if (!get_errno()) | |
96 | set_err(errno); | |
97 | return false; | |
98 | } | |
99 | ||
100 | switch (command) { | |
101 | case CHECK_POWER_MODE: | |
102 | out.out_regs.sector_count = data[0]; | |
103 | break; | |
104 | case STATUS_CHECK: | |
105 | switch (rc) { | |
106 | case 0: // Good SMART status | |
107 | out.out_regs.lba_high = 0xc2; out.out_regs.lba_mid = 0x4f; | |
108 | break; | |
109 | case 1: // Bad SMART status | |
110 | out.out_regs.lba_high = 0x2c; out.out_regs.lba_mid = 0xf4; | |
111 | break; | |
112 | } | |
113 | break; | |
114 | default: | |
115 | break; | |
116 | } | |
117 | return true; | |
118 | } | |
119 |