]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - dev_ata_cmd_set.cpp
import smartmontools 7.0
[mirror_smartmontools-debian.git] / dev_ata_cmd_set.cpp
1 /*
2 * dev_ata_cmd_set.cpp
3 *
4 * Home page of code is: http://www.smartmontools.org
5 *
6 * Copyright (C) 2008 Christian Franke <smartmontools-support@lists.sourceforge.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * You should have received a copy of the GNU General Public License
14 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 #include "config.h"
19 #include "int64.h"
20 #include "atacmds.h"
21 #include "dev_ata_cmd_set.h"
22
23 #include <errno.h>
24
25 const char * dev_ata_cmd_set_cpp_cvsid = "$Id: dev_ata_cmd_set.cpp 4122 2015-08-27 19:08:07Z chrfranke $"
26 DEV_ATA_CMD_SET_H_CVSID;
27
28
29 /////////////////////////////////////////////////////////////////////////////
30 // ata_device_with_command_set
31
32 // Adapter routine to implement new ATA pass through with old interface
33
34 bool ata_device_with_command_set::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
35 {
36 if (!ata_cmd_is_ok(in, true)) // data_out_support
37 return false;
38
39 smart_command_set command = (smart_command_set)-1;
40 int select = 0;
41 char * data = (char *)in.buffer;
42 char buffer[512];
43 switch (in.in_regs.command) {
44 case ATA_IDENTIFY_DEVICE:
45 command = IDENTIFY;
46 break;
47 case ATA_IDENTIFY_PACKET_DEVICE:
48 command = PIDENTIFY;
49 break;
50 case ATA_CHECK_POWER_MODE:
51 command = CHECK_POWER_MODE;
52 data = buffer; data[0] = 0;
53 break;
54 case ATA_SMART_CMD:
55 switch (in.in_regs.features) {
56 case ATA_SMART_ENABLE:
57 command = ENABLE;
58 break;
59 case ATA_SMART_READ_VALUES:
60 command = READ_VALUES;
61 break;
62 case ATA_SMART_READ_THRESHOLDS:
63 command = READ_THRESHOLDS;
64 break;
65 case ATA_SMART_READ_LOG_SECTOR:
66 command = READ_LOG;
67 select = in.in_regs.lba_low;
68 break;
69 case ATA_SMART_WRITE_LOG_SECTOR:
70 command = WRITE_LOG;
71 select = in.in_regs.lba_low;
72 break;
73 case ATA_SMART_DISABLE:
74 command = DISABLE;
75 break;
76 case ATA_SMART_STATUS:
77 command = (in.out_needed.lba_high ? STATUS_CHECK : STATUS);
78 break;
79 case ATA_SMART_AUTO_OFFLINE:
80 command = AUTO_OFFLINE;
81 select = in.in_regs.sector_count;
82 break;
83 case ATA_SMART_AUTOSAVE:
84 command = AUTOSAVE;
85 select = in.in_regs.sector_count;
86 break;
87 case ATA_SMART_IMMEDIATE_OFFLINE:
88 command = IMMEDIATE_OFFLINE;
89 select = in.in_regs.lba_low;
90 break;
91 default:
92 return set_err(ENOSYS, "Unknown SMART command");
93 }
94 break;
95 default:
96 return set_err(ENOSYS, "Non-SMART commands not implemented");
97 }
98
99 clear_err(); errno = 0;
100 int rc = ata_command_interface(command, select, data);
101 if (rc < 0) {
102 if (!get_errno())
103 set_err(errno);
104 return false;
105 }
106
107 switch (command) {
108 case CHECK_POWER_MODE:
109 out.out_regs.sector_count = data[0];
110 break;
111 case STATUS_CHECK:
112 switch (rc) {
113 case 0: // Good SMART status
114 out.out_regs.lba_high = 0xc2; out.out_regs.lba_mid = 0x4f;
115 break;
116 case 1: // Bad SMART status
117 out.out_regs.lba_high = 0x2c; out.out_regs.lba_mid = 0xf4;
118 break;
119 }
120 break;
121 default:
122 break;
123 }
124 return true;
125 }
126