Skip to content
Snippets Groups Projects
Commit 14c53659 authored by chrfranke's avatar chrfranke
Browse files

Add new SMART STATUS check command for JMicron USB bridges.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2748 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent 59cdc689
No related branches found
No related tags found
No related merge requests found
CHANGELOG for smartmontools
$Id: CHANGELOG,v 1.778 2009/03/03 20:13:08 chrfranke Exp $
$Id: CHANGELOG,v 1.779 2009/03/03 20:23:55 chrfranke Exp $
The most recent version of this file is:
http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup
......@@ -41,6 +41,10 @@ NOTES FOR FUTURE RELEASES: see TODO file.
<DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
[CF] Add new SMART STATUS check command for JMicron USB bridges.
Should support also older chip versions and prevents a race
condition.
[CF] Windows: Fix win_scsi_device::scsi_pass_through() for single byte
data transfers. Required for JMicron SMART STATUS check.
......
......@@ -3,7 +3,8 @@
*
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2006-8 Douglas Gilbert <dougg@torque.net>
* Copyright (C) 2006-9 Douglas Gilbert <dougg@torque.net>
* Copyright (C) 2009 Christian Franke <smartmontools-support@lists.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -50,7 +51,7 @@
#include "dev_ata_cmd_set.h" // ata_device_with_command_set
#include "dev_tunnelled.h" // tunnelled_device<>
const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.22 2009/02/27 22:42:52 chrfranke Exp $"
const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.23 2009/03/03 20:23:55 chrfranke Exp $"
CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID;
/* for passing global control variables */
......@@ -832,7 +833,7 @@ bool usbjmicron_device::open()
// Detect port if not specified
if (m_port < 0) {
unsigned char regbuf[2] = {0, 0};
unsigned char regbuf[1] = {0};
if (!get_registers(0x720f, regbuf, sizeof(regbuf))) {
close();
return false;
......@@ -861,11 +862,16 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
)
return false;
bool is_smart_status = ( in.in_regs.command == ATA_SMART_CMD
&& in.in_regs.features == ATA_SMART_STATUS);
// Support output registers for SMART STATUS
if (in.out_needed.is_set() && !is_smart_status)
return set_err(ENOSYS, "ATA output registers not supported");
// Support 48-bit commands with zero high bytes
if (in.in_regs.is_48bit_cmd()) {
if (in.in_regs.is_real_48bit_cmd() || in.out_needed.is_set())
if (in.in_regs.is_real_48bit_cmd())
return set_err(ENOSYS, "48-bit ATA commands not fully supported");
}
if (m_port < 0)
return set_err(EIO, "Unknown JMicron port");
......@@ -874,7 +880,14 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
memset(&io_hdr, 0, sizeof(io_hdr));
bool rwbit = true;
switch (in.direction) {
unsigned char smart_status = 0;
if (is_smart_status && in.out_needed.is_set()) {
io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
io_hdr.dxfer_len = 1;
io_hdr.dxferp = &smart_status;
}
else switch (in.direction) {
case ata_cmd_in::no_data:
io_hdr.dxfer_dir = DXFER_NONE;
break;
......@@ -926,7 +939,23 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
}
if (in.out_needed.is_set()) {
if (is_smart_status) {
switch (smart_status) {
case 0x01: case 0xc2:
out.out_regs.lba_high = 0xc2;
out.out_regs.lba_mid = 0x4f;
break;
case 0x00: case 0x2c:
out.out_regs.lba_high = 0x2c;
out.out_regs.lba_mid = 0xf4;
break;
}
}
#if 0 // Not needed for SMART STATUS, see also notes below
else {
// Read ATA output registers
// NOTE: The register addresses are not valid for some older chip revisions
// NOTE: There is a small race condition here!
unsigned char regbuf[16] = {0, };
if (!get_registers((m_port == 0 ? 0x8000 : 0x9000), regbuf, sizeof(regbuf)))
......@@ -940,6 +969,8 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
out.out_regs.error = regbuf[13];
out.out_regs.status = regbuf[14];
}
#endif
}
return true;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment