Ticket #1853: smart_7.4_ps3stor2smart.patch

File smart_7.4_ps3stor2smart.patch, 52.5 KB (added by babyxong, 4 months ago)

Add ps3stor RAID(ps3stor RAID Controller) support on Linux

  • AUTHORS

     
    4646Hank Wu                 <hank@areca.com.tw>
    4747Shengfeng Zhou          <linux@highpoint-tech.com>
    4848Richard Zybert          <richard.zybert@zybert.co.uk>
     49Hong Xu                 <babyxong@88.com>
    4950
    5051The first smartmontools code was derived from the smartsuite package,
    5152written by Michael Cornwell and Andre Hedrick.
  • ChangeLog

     
    11$Id$
    22
     32024-07-17  Hong Xu  <babyxong@88.com>
     4        Add PS3StorRAID (PS3Stor RAID Controller) support on Linux.
     5
    362024-05-08  Christian Franke  <franke@computer.org>
    47
    58        smartctl.cpp, smartd.cpp: Fix segfault on missing option argument (#1830).
  • configure.ac

     
    627627os_nvme_devicescan_changed=no
    628628case "${host}" in
    629629  *-*-linux*)
    630     os_deps='os_linux.o cciss.o dev_areca.o'
     630    os_deps='os_linux.o cciss.o dev_areca.o ps3stor.o'
    631631    os_dnsdomainname="'dnsdomainname' 'hostname -d'"
    632632    os_nisdomainname="'nisdomainname' 'hostname -y' 'domainname'"
    633633    os_man_filter=Linux
  • Makefile.am

     
    132132        dev_legacy.cpp \
    133133        linux_nvme_ioctl.h \
    134134        megaraid.h \
    135         sssraid.h
     135        sssraid.h \
     136        ps3stor.cpp \
     137        ps3stor.h
    136138
    137139if OS_WIN32_MINGW
    138140
     
    206208        freebsd_nvme_ioctl.h \
    207209        netbsd_nvme_ioctl.h \
    208210        megaraid.h \
    209         sssraid.h
     211        sssraid.h \
     212        ps3stor.cpp \
     213        ps3stor.h
    210214
    211215if OS_POSIX
    212216
  • os_linux.cpp

     
    2929 *  Kernel compatibility By:    Andre Hedrick <andre@suse.com>
    3030 *  Non-Copyright (C) 2000      Andre Hedrick <andre@suse.com>
    3131 *
     32 * Original PS3stor code:
     33 *  Copyright (C) 2021-2024 Hong Xu <babyxong@88.com>
     34 *
    3235 * Other ars of this file are derived from code that was
    3336 *
    3437 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
     
    8487// "include/uapi/linux/nvme_ioctl.h" from Linux kernel sources
    8588#include "linux_nvme_ioctl.h" // nvme_passthru_cmd, NVME_IOCTL_ADMIN_CMD
    8689
     90#include "ps3stor.h"
     91#include <map>
    8792#ifndef ENOTSUP
    8893#define ENOTSUP ENOSYS
    8994#endif
     
    15231528}
    15241529
    15251530/////////////////////////////////////////////////////////////////////////////
     1531/// PS3 STOR support
     1532class linux_smart_interface;
     1533class linux_ps3stor_channel;
     1534class linux_ps3stor_device
     1535: public /* implements */ scsi_device,
     1536  public /* extends */ linux_smart_device
     1537{
     1538public:
     1539
     1540  linux_ps3stor_device(smart_interface *intf, const char *name,
     1541    unsigned int tgt);
     1542
     1543  virtual ~linux_ps3stor_device();
     1544
     1545  virtual smart_device * autodetect_open() override;
     1546
     1547  virtual bool is_open() const override;
     1548  virtual bool open() override;
     1549  virtual bool close() override;
     1550
     1551  virtual bool scsi_pass_through(scsi_cmnd_io *iop) override;
     1552
     1553private:
     1554  unsigned int  m_did;
     1555  bool          m_open_flag;
     1556  encl_id_t     m_eid;
     1557  slot_id_t     m_sid;
     1558  unsigned int  m_host;
     1559  bool scsi_cmd(scsi_cmnd_io *iop);
     1560  bool get_pd_position(encl_id_t &eid, slot_id_t &sid);
     1561};
     1562
     1563linux_ps3stor_device::linux_ps3stor_device(smart_interface *intf,
     1564  const char *dev_name, unsigned int tgt)
     1565 : smart_device(intf, dev_name, "ps3stor", "ps3stor"),
     1566   linux_smart_device(O_RDWR | O_NONBLOCK),
     1567   m_did(tgt),
     1568   m_open_flag(false),
     1569   m_eid(PS3STOR_INVALID_ENCL_ID),
     1570   m_sid(PS3STOR_INVALID_SLOT_ID),
     1571   m_host(0)
     1572{
     1573  set_info().info_name = strprintf("%s [ps3stor_disk_%02d]", dev_name, m_did);
     1574  set_info().dev_type = strprintf("ps3stor,%d", tgt);
     1575}
     1576
     1577linux_ps3stor_device::~linux_ps3stor_device()
     1578{
     1579  if (m_open_flag) {
     1580    m_open_flag = false;
     1581  }
     1582  set_fd(-1); // for ~linux_smart_device
     1583}
     1584
     1585smart_device * linux_ps3stor_device::autodetect_open()
     1586{
     1587  int report = scsi_debugmode;
     1588
     1589  // Open device
     1590  if (!open())
     1591    return this;
     1592
     1593  // The code below is based on smartd.cpp:SCSIFilterKnown()
     1594  if (strcmp(get_req_type(), "ps3stor"))
     1595    return this;
     1596
     1597  // Get INQUIRY
     1598  unsigned char req_buff[64] = {0, };
     1599  int req_len = 36;
     1600  if (scsiStdInquiry(this, req_buff, req_len)) {
     1601      close();
     1602      set_err(EIO, "INQUIRY failed");
     1603      return this;
     1604  }
     1605
     1606  int avail_len = req_buff[4] + 5;
     1607  int len = (avail_len < req_len ? avail_len : req_len);
     1608  if (len < 36)
     1609      return this;
     1610
     1611  if (report)
     1612    pout("Got ps3stor inquiry.. %s\n", req_buff+8);
     1613
     1614  // Use INQUIRY to detect type
     1615  {
     1616    // SAT?
     1617    ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
     1618    if (newdev) // NOTE: 'this' is now owned by '*newdev'
     1619      return newdev;
     1620  }
     1621
     1622  return this;
     1623}
     1624
     1625bool linux_ps3stor_device::is_open() const
     1626{
     1627    return m_open_flag;
     1628}
     1629
     1630bool linux_ps3stor_device::open()
     1631{
     1632  if(!m_open_flag) {
     1633 
     1634    if (sscanf(get_dev_name(), "/dev/bus/%u", &m_host) == 0) {
     1635      if (!linux_smart_device::open())
     1636        return false;
     1637      /* Get device HBA */
     1638      struct sg_scsi_id sgid;
     1639      if (ioctl(get_fd(), SG_GET_SCSI_ID, &sgid) == 0) {
     1640        m_host = sgid.host_no;
     1641      }
     1642      else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_host) != 0) {
     1643        int err = errno;
     1644        linux_smart_device::close();
     1645        return set_err(err, "can't get bus number");
     1646      } // we don't need this device anymore
     1647      linux_smart_device::close();
     1648    }
     1649    m_open_flag = true;
     1650  }
     1651  return true;
     1652}
     1653
     1654bool linux_ps3stor_device::close()
     1655{
     1656  m_open_flag = false;
     1657  return true;
     1658}
     1659
     1660bool linux_ps3stor_device::scsi_pass_through(scsi_cmnd_io *iop)
     1661{
     1662  int report = scsi_debugmode;
     1663
     1664  if (report > 0) {
     1665        int k, j;
     1666        const unsigned char * ucp = iop->cmnd;
     1667        const char * np;
     1668        char buff[256];
     1669        const int sz = (int)sizeof(buff);
     1670
     1671        np = scsi_get_opcode_name(ucp);
     1672        j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
     1673        for (k = 0; k < (int)iop->cmnd_len; ++k)
     1674            j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
     1675        if ((report > 1) &&
     1676            (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
     1677            int trunc = (iop->dxfer_len > 256) ? 1 : 0;
     1678
     1679            snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n  Outgoing "
     1680                     "data, len=%d%s:\n", (int)iop->dxfer_len,
     1681                     (trunc ? " [only first 256 bytes shown]" : ""));
     1682            dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
     1683        }
     1684        else
     1685            snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
     1686        pout("%s", buff);
     1687  }
     1688
     1689  if (iop->cmnd[0] == 0x00)
     1690    return true;
     1691
     1692  return scsi_cmd(iop);
     1693}
     1694
     1695bool linux_ps3stor_device::scsi_cmd(scsi_cmnd_io *iop)
     1696{
     1697 // Controller rejects Test Unit Ready
     1698  if (iop->cmnd[0] == 0x00)
     1699    return true;
     1700
     1701  if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) {
     1702    // Controller does not return ATA output registers in SAT sense data
     1703    if (iop->cmnd[2] & (1 << 5)) // chk_cond
     1704      return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware");
     1705  }
     1706  // SMART WRITE LOG SECTOR causing media errors
     1707  if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 // SAT16 WRITE LOG
     1708      && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) ||
     1709      (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 // SAT12 WRITE LOG
     1710       && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR))
     1711  {
     1712    if(!failuretest_permissive)
     1713       return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
     1714  }
     1715
     1716  if(iop->cmnd_len > PS3STOR_SCSI_MAX_CDB_LENGTH) {
     1717    return set_err(ENOSYS, "ps3stor cannot support scsi cdb longer than %d", PS3STOR_SCSI_MAX_CDB_LENGTH);
     1718  }
     1719
     1720  //get enclid slotid
     1721  encl_id_t eid = 0;
     1722  slot_id_t sid = 0;
     1723  if(!get_pd_position(eid, sid)) {
     1724    pout("linux_ps3stor_device::scsi_cmd: get_pd_position of device %u failed.\n", m_did);
     1725    return set_err(EIO, "linux_ps3stor_device::scsi_cmd: get_pd_position of device %u failed.", m_did);
     1726  }
     1727
     1728  // ps3stor_scsi_req
     1729
     1730  ps3stor_scsi_req_t  scsireq = {};
     1731  scsireq.reserved = 1;
     1732  switch (iop->dxfer_dir) {
     1733  case DXFER_NONE:
     1734    scsireq.cmddir = PS3STOR_SCSI_CMD_DIR_NONE;
     1735    break;
     1736  case DXFER_FROM_DEVICE:
     1737    scsireq.cmddir = PS3STOR_SCSI_CMD_DIR_TO_HOST;
     1738    break;
     1739  case DXFER_TO_DEVICE:
     1740    scsireq.cmddir = PS3STOR_SCSI_CMD_DIR_FROM_HOST;
     1741    break;
     1742  default:
     1743    pout("scsi_cmd: bad dxfer_dir\n");
     1744    return set_err(EINVAL, "scsi_cmd: bad dxfer_dir\n");
     1745  }
     1746  scsireq.checklen = 0;
     1747  memcpy(scsireq.cdb, iop->cmnd, iop->cmnd_len);
     1748
     1749
     1750  // ps3stor_scsi_rsp
     1751  struct ps3stor_scsi_rsp scsirsp = {};
     1752
     1753  if(PS3STOR_ERRNO_SUCCESS != ps3chn()->pd_scsi_passthrough(m_host, eid, sid, scsireq, scsirsp, iop->dxferp, iop->dxfer_len)) {
     1754    return -1;
     1755  }
     1756
     1757  if(scsirsp.entry.status != 0) {
     1758    if(scsirsp.entry.status == 12) {
     1759      return set_err(EIO, "linux_ps3stor_device::scsi_cmd: Device %u does not exist\n", m_did);
     1760    } else {
     1761        uint8_t scsi_status = scsirsp.entry.status;
     1762        //ignore underrun
     1763        if(scsi_status != PS3STOR_SCSI_STATUS_UNDERRUN) {
     1764          //free(scsi_passthru);
     1765          return set_err((errno ? errno : EIO), "linux_ps3stor_device::scsi_cmd result: %u.%u = %d/%hhu",
     1766                      m_host, m_did, errno, scsi_status
     1767                );
     1768        }
     1769    }
     1770  }
     1771  iop->scsi_status = scsirsp.entry.status;
     1772  memcpy(iop->sensep, scsirsp.entry.sensebuf, PS3STOR_MIN(iop->max_sense_len, sizeof(scsirsp.entry.sensebuf)));
     1773  return true;
     1774}
     1775
     1776bool linux_ps3stor_device::get_pd_position(encl_id_t &eid, slot_id_t &sid)
     1777{
     1778  ps3stor_pd_baseinfo_t baseinfo = {};
     1779  //1.get enclId and slotId from ioc for the first time
     1780  if(m_eid == PS3STOR_INVALID_ENCL_ID && m_sid == PS3STOR_INVALID_SLOT_ID) {
     1781    if(PS3STOR_ERRNO_SUCCESS != ps3chn()->pd_get_baseinfo_by_devid(m_host, m_did, baseinfo)) {
     1782      return false;
     1783    }   
     1784    m_eid = baseinfo.enclid;
     1785    m_sid = baseinfo.slotid;
     1786  }
     1787  //2.copy value from member
     1788  eid = m_eid;
     1789  sid = m_sid;
     1790
     1791  return true;
     1792}
     1793
     1794/////////////////////////////////////////////////////////////////////////////
    15261795/// CCISS RAID support
    15271796
    15281797#ifdef HAVE_LINUX_CCISS_IOCTL_H
     
    28633132  bool get_dev_sssraid(smart_device_list & devlist);
    28643133  int sssraid_pd_add_list(int bus_no, smart_device_list & devlist);
    28653134  int sssraid_pdlist_cmd(int bus_no, uint16_t start_idx, void *buf, size_t bufsize, uint8_t *statusp);
     3135
     3136  bool get_dev_ps3stor(smart_device_list & devlist);
     3137  int ps3stor_pd_add_list(int bus_no, smart_device_list & devlist);
     3138  int ps3stor_pdlist_cmd(int bus_no, std::vector<uint16_t> &devidlist);
     3139
    28663140};
    28673141
    28683142std::string linux_smart_interface::get_os_version_str()
     
    31373411    get_dev_megasas(devlist);
    31383412    // get device list from the sssraid device
    31393413    get_dev_sssraid(devlist);
     3414
     3415    // get device list from the ps3stor device
     3416    get_dev_ps3stor(devlist);
    31403417  }
    31413418
    31423419  if (type_nvme) {
     
    33233600  return (0);
    33243601}
    33253602
     3603// getting devices from ps3 and ps3stor, if available
     3604bool linux_smart_interface::get_dev_ps3stor(smart_device_list &devlist)
     3605{
     3606  // init ps3stor and get controller list , return false on err or not found
     3607  if(!ps3stor_init()) {
     3608    return false;
     3609  }
     3610  // try to add device for each controller
     3611  std::vector<unsigned> hostlist;
     3612  ps3chn()->get_host_list(hostlist);
     3613  for(uint16_t i = 0; i < hostlist.size(); i++)
     3614  {
     3615    ps3stor_pd_add_list(hostlist.at(i), devlist);
     3616  }
     3617  return true;
     3618}
     3619
     3620int linux_smart_interface::ps3stor_pd_add_list(int bus_no, smart_device_list &devlist)
     3621{
     3622  // get pd device id list
     3623  std::vector<uint16_t> devid_list;
     3624  ps3stor_pdlist_cmd(bus_no, devid_list);
     3625
     3626  // add all SCSI devices
     3627  for (unsigned i = 0; i < devid_list.size(); i++) {
     3628    char line[128];
     3629    snprintf(line, sizeof(line) - 1, "/dev/bus/%d", bus_no);
     3630    smart_device * dev = new linux_ps3stor_device(this, line, devid_list.at(i));
     3631    devlist.push_back(dev);
     3632  }
     3633  return (0); 
     3634}
     3635
     3636int linux_smart_interface::ps3stor_pdlist_cmd(int bus_no, std::vector<uint16_t> &devidlist)
     3637{
     3638  // get enclist and get devlsit for each encl
     3639  uint8_t enclcount = 0;
     3640  struct ps3stor_encl_list *encllist = NULL;
     3641
     3642  //1.get encl count
     3643  if(PS3STOR_ERRNO_SUCCESS != ps3chn()->get_enclcount(bus_no, enclcount))
     3644  {
     3645    return -1;
     3646  }
     3647
     3648  //2.get encl list
     3649  if(enclcount > 0)
     3650  {
     3651    size_t listsize = sizeof(struct ps3stor_encl_list) + enclcount * sizeof(uint8_t);
     3652    encllist = (struct ps3stor_encl_list*)malloc(listsize) ;
     3653    if(PS3STOR_ERRNO_SUCCESS != ps3chn()->get_encllist(bus_no, encllist, listsize)) {
     3654      free(encllist);
     3655      encllist = NULL;
     3656      return -1;
     3657    }
     3658  }
     3659
     3660  //3.get pd list for each encl
     3661  if(encllist != NULL && encllist->count > 0) {
     3662    enclcount = PS3STOR_MIN(enclcount, encllist->count);
     3663    for(uint8_t i = 0; i < enclcount; i++){
     3664      uint16_t devcount = 0;
     3665      uint8_t eid = encllist->idlist[i];
     3666      if(PS3STOR_ERRNO_SUCCESS != ps3chn()->pd_get_devcount_by_encl(bus_no, eid, devcount)) {
     3667        return -1;
     3668      }
     3669      if(devcount > 0)
     3670      {
     3671        size_t listsize = sizeof(uint16_t) * devcount;
     3672        uint16_t *devlist = (uint16_t*)malloc(listsize);
     3673        memset(devlist, 0, listsize);
     3674        if(PS3STOR_ERRNO_SUCCESS != ps3chn()->pd_get_devlist_by_encl(bus_no, eid, devlist, listsize)) {
     3675          free(devlist);
     3676          devlist = NULL;
     3677          return -1;
     3678        }
     3679        for(int j = 0; j < devcount; j++)
     3680        {
     3681          devidlist.push_back(devlist[j]);
     3682        }         
     3683        free(devlist);
     3684        devlist = NULL;
     3685      }
     3686
     3687    }
     3688  }
     3689 
     3690  if(encllist != NULL) {
     3691    free(encllist);
     3692    encllist = NULL;
     3693  }
     3694
     3695  return 0;
     3696}
     3697
    33263698int
    33273699linux_smart_interface::sssraid_pd_add_list(int bus_no, smart_device_list & devlist)
    33283700{
     
    36133985
    36143986  }
    36153987
     3988  // ps3stor ?
     3989  if (sscanf(type, "ps3stor,%d", &disknum) == 1) {
     3990    if(ps3stor_init()) {
     3991      return new linux_ps3stor_device(this, name, disknum);
     3992    } else {
     3993      pout("get_custom_smart_device: ps3stor_init failed.\n");
     3994      set_err_np(EINVAL, "get_custom_smart_device: ps3stor_init failed.\n");
     3995    }
     3996   
     3997  }
     3998
    36163999  return nullptr;
    36174000}
    36184001
    36194002std::string linux_smart_interface::get_valid_custom_dev_types_str()
    36204003{
    3621   return "areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N, aacraid,H,L,ID, sssraid,E,S"
     4004  return "areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N, aacraid,H,L,ID, sssraid,E,S, ps3stor,N"
    36224005#ifdef HAVE_LINUX_CCISS_IOCTL_H
    36234006                                                                                ", cciss,N"
    36244007#endif
     
    36254008    ;
    36264009}
    36274010
     4011/// Linux ps3stor channel
     4012class linux_ps3stor_channel
     4013: public /*implements*/ ps3stor_channel
     4014{
     4015public:
     4016  linux_ps3stor_channel();
     4017  virtual ~linux_ps3stor_channel();
     4018  enum ps3stor_device_type {
     4019    PS3STOR_DEVICE_TYPE_PS3 = 0,
     4020    PS3STOR_DEVICE_TYPE_PS3STOR,
     4021    PS3STOR_DEVICE_TYPE_NR
     4022  };
     4023
     4024public:
     4025  virtual ps3stor_errno channel_init() override;
     4026
     4027  virtual ps3stor_errno get_host_list(std::vector<unsigned> &hostlist) override;
     4028
     4029protected:
     4030  virtual ps3stor_errno firecmd(unsigned hostid, struct ps3stor_msg_info * info, struct ps3stor_msg_info * ackinfo, unsigned acksize) override;
     4031
     4032  virtual ps3stor_errno firecmd_scsi(unsigned hostid, struct ps3stor_msg_info * reqinfo, struct ps3stor_msg_info * ackinfo,
     4033                                             unsigned acksize, struct ps3stor_data * scsidata, unsigned scsicount) override;
     4034
     4035
     4036  virtual struct ps3stor_tlv *add_tlv_data(struct ps3stor_tlv *tlv, unsigned type, const void *data, uint16_t size) override;
     4037  virtual bool set_err(int no, const char * msg) override;
     4038  virtual bool set_err(int no) override;
     4039
     4040private:
     4041  int   m_devfd_ps3;
     4042  int   m_devfd_ps3stor;
     4043  std::map<unsigned, struct ps3stor_pci_info> m_host_map;
     4044
     4045  int open_node(enum ps3stor_device_type dev_type);
     4046  ps3stor_errno get_func_by_host(unsigned hostid, uint8_t &funcid);
     4047  ps3stor_errno get_pci_info(unsigned host, struct ps3stor_pci_info &pci_info);
     4048  void find_device(enum ps3stor_device_type dev_type);
     4049  ps3stor_errno get_devfd(unsigned host, int &devfd);
     4050
     4051  void print_packet(struct ps3stor_ioctl_sync_cmd &packet); // print packet msg for debug
     4052
     4053};
     4054
     4055linux_ps3stor_channel::linux_ps3stor_channel()
     4056{
     4057  m_devfd_ps3 = -1;
     4058  m_devfd_ps3stor = -1;
     4059}
     4060
     4061linux_ps3stor_channel::~linux_ps3stor_channel()
     4062{
     4063  if(m_devfd_ps3 >= 0)
     4064    ::close(m_devfd_ps3);
     4065 
     4066  if(m_devfd_ps3stor >= 0)
     4067    ::close(m_devfd_ps3stor);
     4068}
     4069
     4070ps3stor_errno linux_ps3stor_channel::channel_init()
     4071{
     4072  ps3stor_errno err = PS3STOR_ERRNO_SUCCESS;
     4073  if(m_init) {
     4074    return err;
     4075  }
     4076
     4077  m_devfd_ps3 = open_node(PS3STOR_DEVICE_TYPE_PS3);
     4078  if(m_devfd_ps3 > 0) {
     4079    find_device(PS3STOR_DEVICE_TYPE_PS3);
     4080  }
     4081 
     4082  m_devfd_ps3stor = open_node(PS3STOR_DEVICE_TYPE_PS3STOR);
     4083  if(m_devfd_ps3stor > 0) {
     4084    find_device(PS3STOR_DEVICE_TYPE_PS3STOR);
     4085  }
     4086
     4087  if(m_host_map.size() > 0) {
     4088    m_init = true;
     4089  }
     4090
     4091  return err;
     4092}
     4093
     4094ps3stor_errno linux_ps3stor_channel::get_host_list(std::vector<unsigned> &hostlist)
     4095{
     4096  for(auto it : m_host_map)
     4097  {
     4098    hostlist.push_back(it.first);
     4099  }
     4100  return PS3STOR_ERRNO_SUCCESS;
     4101}
     4102
     4103ps3stor_errno linux_ps3stor_channel::firecmd(unsigned hostid, struct ps3stor_msg_info * reqinfo, struct ps3stor_msg_info * ackinfo, unsigned acksize)
     4104{
     4105  ps3stor_errno err = PS3STOR_ERRNO_SUCCESS;
     4106  int   devfd = -1;
     4107  const size_t insize = (reqinfo == NULL ? 0 : reqinfo->length);
     4108  uint8_t funcid = 0;
     4109
     4110  reqinfo->magic = PS3STOR_MSG_MAGIC_CODE;
     4111  reqinfo->error = PS3STOR_ERRNO_SUCCESS;
     4112  reqinfo->timeout = 0;
     4113  reqinfo->start_time = 0;
     4114  reqinfo->runver = PS3STOR_ITR_VER;
     4115  reqinfo->uuid = 0;
     4116  reqinfo->service = PS3STOR_SMARTCTL_SERVICE;
     4117  reqinfo->traceid = 0xffc73a859920e01;
     4118  get_func_by_host(hostid, funcid);
     4119  reqinfo->funcid = funcid;
     4120
     4121  const uint16_t inblk = (uint16_t)((insize + PS3STOR_SGL_SIZE -1) / PS3STOR_SGL_SIZE);
     4122  const uint16_t outblk = (uint16_t)((acksize + PS3STOR_SGL_SIZE -1) / PS3STOR_SGL_SIZE);
     4123
     4124  struct ps3stor_ioctl_sync_cmd packet = {};
     4125  packet.hostid = (uint16_t)hostid;
     4126  packet.sge_count = inblk + outblk;
     4127  packet.sgl_offset = offsetof(struct ps3stor_ioctl_sync_cmd, sgl) / sizeof(uint32_t); // 4 bytes
     4128  packet.traceid = reqinfo->traceid;
     4129
     4130  reqinfo->index.tlv = 0;
     4131  reqinfo->index.ack = (uint8_t)(inblk);
     4132  reqinfo->ack_length = acksize;
     4133  reqinfo->ack_offset = (uint32_t)insize;
     4134
     4135  for(uint16_t i = 0; i < inblk; i++) {
     4136    packet.sgl[i].addr = (uint64_t)(intptr_t) & ((uint8_t*)reqinfo)[PS3STOR_SGL_SIZE * i];
     4137    packet.sgl[i].length = (uint32_t)((i == inblk - 1) ? (insize - (PS3STOR_SGL_SIZE * i)) : PS3STOR_SGL_SIZE);
     4138  }
     4139
     4140  for(uint16_t i = 0; i < outblk; i++) {
     4141    packet.sgl[inblk + i].addr = (uint64_t)(intptr_t) & ((uint8_t*)ackinfo)[PS3STOR_SGL_SIZE * i];
     4142    packet.sgl[inblk + i].length = (uint32_t)((i == outblk - 1) ? (acksize - (PS3STOR_SGL_SIZE * i)) : PS3STOR_SGL_SIZE);
     4143  }
     4144
     4145  err = get_devfd(hostid, devfd);
     4146  if(err != PS3STOR_ERRNO_SUCCESS) {
     4147    return err;
     4148  }
     4149  int res = ioctl(devfd, PS3STOR_CMD_IOCTL_SYNC_CMD, &packet);
     4150  if(res < 0) {
     4151    set_err(errno, "ioctl failed.\n");
     4152    return -1;
     4153  }
     4154  if(ackinfo->magic != PS3STOR_MSG_MAGIC_CODE) {
     4155    set_err(EIO, "check magic code failed.\n");
     4156    return -1;
     4157  }
     4158  if(ackinfo->error != PS3STOR_ERRNO_SUCCESS) {
     4159    set_err(EIO, "err form ioc.\n");
     4160    return -1;
     4161  }
     4162  return err;
     4163}
     4164
     4165ps3stor_errno linux_ps3stor_channel::firecmd_scsi(unsigned hostid, struct ps3stor_msg_info * reqinfo, struct ps3stor_msg_info * ackinfo,
     4166                                                          unsigned acksize, struct ps3stor_data * scsidata, unsigned scsicount)
     4167{
     4168  ps3stor_errno err = PS3STOR_ERRNO_SUCCESS;
     4169  int   devfd = -1;
     4170  const size_t insize = (reqinfo == NULL ? 0 : reqinfo->length);
     4171  uint8_t funcid = 0;
     4172
     4173  reqinfo->magic = PS3STOR_MSG_MAGIC_CODE;
     4174  reqinfo->error = PS3STOR_ERRNO_SUCCESS;
     4175  reqinfo->timeout = 0;
     4176  reqinfo->start_time = 0;
     4177  reqinfo->runver = PS3STOR_ITR_VER;
     4178  reqinfo->uuid = 0;
     4179  reqinfo->service = PS3STOR_SMARTCTL_SERVICE;
     4180  reqinfo->traceid = 0xffc73a859920e01;
     4181  get_func_by_host(hostid, funcid);
     4182  reqinfo->funcid = funcid;
     4183
     4184  const uint16_t inblk = (uint16_t)((insize + PS3STOR_SGL_SIZE -1) / PS3STOR_SGL_SIZE);
     4185  const uint16_t outblk = (uint16_t)((acksize + PS3STOR_SGL_SIZE -1) / PS3STOR_SGL_SIZE);
     4186  const uint16_t scsiblk = (uint16_t)scsicount;
     4187
     4188  struct ps3stor_ioctl_sync_cmd packet = {};
     4189  packet.hostid = (uint16_t)hostid;
     4190  packet.sge_count = inblk + outblk + scsiblk;
     4191  packet.sgl_offset = offsetof(struct ps3stor_ioctl_sync_cmd, sgl) / sizeof(uint32_t); // 4 bytes
     4192  packet.traceid = reqinfo->traceid;
     4193
     4194  //todo check for sge_count <= 16
     4195
     4196  reqinfo->index.tlv = 0;
     4197  reqinfo->index.ack = (uint8_t)(inblk);
     4198  reqinfo->ack_length = acksize;
     4199  reqinfo->ack_offset = (uint32_t)insize;
     4200
     4201  for(uint16_t i = 0; i < inblk; i++) {
     4202    packet.sgl[i].addr = (uint64_t)(intptr_t) & ((uint8_t*)reqinfo)[PS3STOR_SGL_SIZE * i];
     4203    packet.sgl[i].length = (uint32_t)((i == inblk - 1) ? (insize - (PS3STOR_SGL_SIZE * i)) : PS3STOR_SGL_SIZE);
     4204  }
     4205
     4206  for(uint16_t i = 0; i < outblk; i++) {
     4207    packet.sgl[inblk + i].addr = (uint64_t)(intptr_t) & ((uint8_t*)ackinfo)[PS3STOR_SGL_SIZE * i];
     4208    packet.sgl[inblk + i].length = (uint32_t)((i == outblk - 1) ? (acksize - (PS3STOR_SGL_SIZE * i)) : PS3STOR_SGL_SIZE);
     4209  }
     4210
     4211  for(uint16_t i = 0; i < scsiblk; i++) {
     4212    packet.sgl[inblk + outblk + i].addr = (uint64_t)(intptr_t)scsidata[i].pdata;
     4213    packet.sgl[inblk + outblk + i].length = scsidata[i].size;
     4214  }
     4215  err = get_devfd(hostid, devfd);
     4216  if(err != PS3STOR_ERRNO_SUCCESS) {
     4217    return err;
     4218  }
     4219
     4220  int res = ioctl(devfd, PS3STOR_CMD_IOCTL_SYNC_CMD, &packet);
     4221  if(res < 0) {
     4222    set_err(errno, "ioctl failed.\n");
     4223    return -1;
     4224  }
     4225  if(ackinfo->magic != PS3STOR_MSG_MAGIC_CODE) {
     4226    set_err(EIO, "check magic code failed.\n");
     4227    return -1;
     4228  }
     4229  if(ackinfo->error != PS3STOR_ERRNO_SUCCESS) {
     4230    set_err(EIO, "err form ioc.\n");
     4231    return -1;
     4232  }
     4233  return err;
     4234}
     4235
     4236struct ps3stor_tlv *linux_ps3stor_channel::add_tlv_data(struct ps3stor_tlv *tlv, unsigned type, const void *data, uint16_t size)
     4237{
     4238  if(data == NULL || size == 0) {
     4239    return tlv;
     4240  }
     4241
     4242  unsigned tlvcode = type;
     4243
     4244  // calculate tlvsize
     4245  uint16_t tlvsize = (uint16_t)(sizeof(*tlv)                      ///< tlv 头
     4246                                + ((tlv == NULL) ? 0 : tlv->size) ///< 已存在tlv的长度
     4247                                + sizeof(tlvcode)                 ///< 新 tlv:type 长度
     4248                                + sizeof(size)                    ///< 新 tlv:length 长度
     4249                                + size);
     4250
     4251  if(tlv == NULL) {
     4252    tlv = (struct ps3stor_tlv *)malloc(tlvsize);
     4253    memset(tlv, 0, tlvsize);
     4254  } else {
     4255    struct ps3stor_tlv * tmp = (struct ps3stor_tlv *)realloc(tlv, tlvsize);
     4256    if(tmp == NULL) {
     4257      free(tlv);
     4258    }
     4259    tlv = tmp;
     4260  }
     4261
     4262  // add data
     4263  if (tlv != NULL)
     4264  {
     4265    memcpy(tlv->buff + tlv->size, &tlvcode, sizeof(tlvcode));
     4266    tlv->size += sizeof(tlvcode);
     4267    memcpy(tlv->buff + tlv->size, &size, sizeof(size));
     4268    tlv->size += sizeof(size);
     4269    memcpy(tlv->buff + tlv->size, data, size);
     4270    tlv->size += size;
     4271  }
     4272 
     4273  return tlv;
     4274}
     4275
     4276bool linux_ps3stor_channel::set_err(int no, const char * msg)
     4277{
     4278  return smi()->set_err(no, "%s", msg);
     4279}
     4280
     4281bool linux_ps3stor_channel::set_err(int no)
     4282{
     4283  return smi()->set_err(no);
     4284}
     4285
     4286int linux_ps3stor_channel::open_node(enum ps3stor_device_type dev_type)
     4287{
     4288  /* Scanning of disks on ps3stor device */
     4289  /* Perform mknod of device ioctl node */
     4290  char line[128];
     4291  int  mjr = -1; //major device number
     4292  int  n1 = -1;
     4293  int  devnode_fd = -1;
     4294  // scan ps3stor
     4295  FILE * fp = fopen(PS3STOR_DRIVE_DEVICE_ID, "r");
     4296  if (!fp)
     4297    return devnode_fd;
     4298
     4299  switch (dev_type)
     4300  {
     4301  case PS3STOR_DEVICE_TYPE_PS3:
     4302    while (fgets(line, sizeof(line), fp) != NULL) {
     4303      n1=0;
     4304      int tmp = sscanf(line, "%d ps3-ioctl%n", &mjr, &n1);
     4305      //if (sscanf(line, "%d ps3-ioctl%n", &mjr, &n1) == 1 && n1 == 13) {
     4306      if (tmp == 1 && n1 == 13) {
     4307        n1=mknod("/dev/ps3-ioctl", S_IFCHR|0600, makedev(mjr, 0));
     4308        if(scsi_debugmode > 0)
     4309          pout("Creating /dev/ps3-ioctl = %d\n", n1 >= 0 ? 0 : errno);
     4310        if (n1 >= 0 || errno == EEXIST) {
     4311          devnode_fd = ::open("/dev/ps3-ioctl", O_RDWR);
     4312          break;
     4313        } else {
     4314          break;
     4315        }       
     4316      }
     4317    }
     4318    break;
     4319  case PS3STOR_DEVICE_TYPE_PS3STOR:
     4320    while (fgets(line, sizeof(line), fp) != NULL) {
     4321      n1=0;
     4322      int tmp = sscanf(line, "%d ps3stor-ioctl%n", &mjr, &n1);
     4323      //if (sscanf(line, "%d ps3stor-ioctl%n", &mjr, &n1) == 1 && n1 == 17) {
     4324      if (tmp == 1 && n1 == 17) {
     4325        n1=mknod("/dev/ps3stor-ioctl", S_IFCHR|0600, makedev(mjr, 0));
     4326        if(scsi_debugmode > 0)
     4327          pout("Creating /dev/ps3stor-ioctl = %d\n", n1 >= 0 ? 0 : errno);
     4328        if (n1 >= 0 || errno == EEXIST) {
     4329          devnode_fd = ::open("/dev/ps3stor-ioctl", O_RDWR);
     4330          break;
     4331        } else {
     4332          break;
     4333        }       
     4334      }
     4335    }
     4336    break;
     4337  default:
     4338    break;
     4339  }
     4340  fclose(fp);
     4341  return devnode_fd;
     4342}
     4343
     4344ps3stor_errno linux_ps3stor_channel::get_func_by_host(unsigned hostid, uint8_t &funcid)
     4345{
     4346  for(auto it : m_host_map)
     4347  {
     4348    if(it.first == hostid) {
     4349      funcid = it.second.function;
     4350      return PS3STOR_ERRNO_SUCCESS;
     4351    }
     4352  }
     4353  return -1;
     4354}
     4355
     4356ps3stor_errno linux_ps3stor_channel::get_pci_info(unsigned host, ps3stor_pci_info &pci_info)
     4357{
     4358  ps3stor_errno err = PS3STOR_ERRNO_SUCCESS;
     4359  char path[128] = {};
     4360  char filelink[128] = {};
     4361
     4362  snprintf(path, sizeof(path) - 1, "/sys/class/scsi_host/host%u", host);
     4363  err = readlink(path, filelink, sizeof(filelink));
     4364  if(err < 0) {
     4365    return errno;
     4366  }
     4367  err = -1;
     4368  const char templatestr[] = "0000:00:00.0"; // look up pci addr by file link
     4369  unsigned templen = strlen(templatestr);
     4370  if(strlen(path) < templen) {
     4371    return -1;
     4372  }
     4373 
     4374  for(unsigned i = 0; *(filelink + i + templen) != '\0'; i++){
     4375    char *begin = filelink + i;
     4376    bool match = true;
     4377    for(unsigned j = 0; j < templen; j++) {
     4378      if(begin[j] == templatestr[j]) {
     4379        continue;
     4380      } else if (isxdigit(begin[j]) && templatestr[j] == '0'){
     4381        continue;
     4382      } else {
     4383        match = false;
     4384        break;
     4385      }
     4386    }
     4387    if(match) {
     4388      err = PS3STOR_ERRNO_SUCCESS;
     4389      memcpy(pci_info.pci_addr, begin, templen + 1);
     4390      sscanf(pci_info.pci_addr, "%x:%hhx:%hhx.%hhx",
     4391             &pci_info.domainid, &pci_info.busid, &pci_info.deviceid, &pci_info.function);
     4392    }
     4393  }
     4394  return err;
     4395}
     4396
     4397void linux_ps3stor_channel::find_device(enum ps3stor_device_type dev_type)
     4398{
     4399  // getting bus numbers with ps3stor controllers
     4400  // we are using sysfs to get list of all scsi hosts
     4401  char procctx[16] = {};
     4402  size_t  proclen = 0;
     4403  switch (dev_type)
     4404  {
     4405  case PS3STOR_DEVICE_TYPE_PS3:
     4406    snprintf(procctx, sizeof(procctx) - 1, "%s", "ps3\n");
     4407    proclen = 4;
     4408    break;
     4409  case PS3STOR_DEVICE_TYPE_PS3STOR:
     4410    snprintf(procctx, sizeof(procctx) - 1, "%s", "ps3stor\n");
     4411    proclen = 7;
     4412    break;
     4413  default:
     4414    return;
     4415    break;
     4416  }
     4417
     4418  DIR * dp = opendir(PS3STOR_SYS_CLASS_SCSI_HOST_PATH);
     4419  if (dp != NULL)
     4420  {
     4421    struct dirent *ep;
     4422    FILE*   fp = NULL;
     4423    char line[128] = {};
     4424    while ((ep = readdir (dp)) != NULL) {
     4425      unsigned int host_no = 0;
     4426      if (!sscanf(ep->d_name, "host%u", &host_no))
     4427        continue;
     4428      /* proc_name should be  procctx */
     4429      char sysfsdir[256] = {};
     4430      snprintf(sysfsdir, sizeof(sysfsdir) - 1,
     4431        "/sys/class/scsi_host/host%u/proc_name", host_no);
     4432      if((fp = fopen(sysfsdir, "r")) == NULL)
     4433        continue;
     4434      if(fgets(line, sizeof(line), fp) != NULL && !strncmp(line, procctx, proclen)) {
     4435        struct ps3stor_pci_info pci = {};
     4436        if(get_pci_info(host_no, pci) == PS3STOR_ERRNO_SUCCESS) {
     4437          pci.devtype = dev_type;
     4438          m_host_map[host_no] = pci;
     4439        }
     4440      }
     4441      fclose(fp);
     4442    }
     4443    (void) closedir(dp);
     4444  }
     4445  return;
     4446}
     4447
     4448ps3stor_errno linux_ps3stor_channel::get_devfd(unsigned host, int &devfd)
     4449{
     4450  ps3stor_errno err = -1;
     4451  for(auto it : m_host_map)
     4452  {
     4453    if(it.first == host) {
     4454      switch (it.second.devtype)
     4455      {
     4456      case PS3STOR_DEVICE_TYPE_PS3:
     4457        devfd = m_devfd_ps3;
     4458        err = PS3STOR_ERRNO_SUCCESS;
     4459        return err;
     4460      case PS3STOR_DEVICE_TYPE_PS3STOR:
     4461        devfd = m_devfd_ps3stor;
     4462        err = PS3STOR_ERRNO_SUCCESS;
     4463        return err;     
     4464      default:
     4465        break;
     4466      };
     4467      break;
     4468    }
     4469  }
     4470  return err;
     4471}
     4472
     4473void linux_ps3stor_channel::print_packet(ps3stor_ioctl_sync_cmd &packet)
     4474{
     4475  for(uint16_t i = 0; i < packet.sge_count; i++) {
     4476    char tmp_buf[1024 * 4] = {};
     4477    uint32_t sz = 1024 * 4;
     4478    uint32_t len = 0;
     4479    len = snprintf(tmp_buf, sz, "=============sgl[%hu]:length = %u =============:\n", i, packet.sgl[i].length);
     4480    for(uint32_t j = 0; j < packet.sgl[i].length && len < sz ; j++) {
     4481      if(j % 32 == 0){
     4482        len += snprintf(&tmp_buf[len], (sz > len ? (sz - len) : 0), "0x%04x: ", j);
     4483      }
     4484      uint8_t* buff = (uint8_t*)(intptr_t)packet.sgl[i].addr;
     4485      len += snprintf(&tmp_buf[len], (sz > len ? (sz - len) : 0), "%02x ", buff[j]);
     4486      if((j + 1) % 4 == 0) {
     4487        len += snprintf(&tmp_buf[len], (sz > len ? (sz - len) : 0), " ");
     4488      }
     4489      if((j + 1) % 32 == 0) {
     4490        len += snprintf(&tmp_buf[len], (sz > len ? (sz - len) : 0), "\n");
     4491      }
     4492    }
     4493    pout("%s\n=================================\n", tmp_buf);
     4494  }
     4495
     4496}
     4497
    36284498} // namespace
    36294499
    36304500/////////////////////////////////////////////////////////////////////////////
     
    36354505  static os_linux::linux_smart_interface the_interface;
    36364506  smart_interface::set(&the_interface);
    36374507}
     4508
     4509void ps3stor_channel::init()
     4510{
     4511  static os_linux::linux_ps3stor_channel the_ps3stor_instance;
     4512  ps3stor_channel::set(&the_ps3stor_instance);
     4513}
     4514
     4515bool ps3stor_init()
     4516{
     4517  if(!ps3chn()) {
     4518    ps3stor_channel::init();
     4519    if (!ps3chn())
     4520      return false;   
     4521  }
     4522  if(PS3STOR_ERRNO_SUCCESS != ps3chn()->channel_init()) {
     4523    return false;
     4524  } 
     4525  return true;
     4526}
     4527 No newline at end of file
  • ps3stor.cpp

     
     1/*
     2 * ps3stor.cpp
     3 *
     4 * Home page of code is: http://www.smartmontools.org
     5 *
     6 * Copyright (C) 2024 Hong Xu
     7 *
     8 * SPDX-License-Identifier: GPL-2.0-or-later
     9 */
     10
     11#include "ps3stor.h"
     12ps3stor_channel * ps3stor_channel::s_channel;
     13
     14ps3stor_errno ps3stor_channel::get_enclcount(unsigned hostid, uint8_t &enclcount)
     15{
     16    struct ps3stor_msg_info* reqinfo = NULL;
     17    size_t insize = sizeof(struct ps3stor_msg_info);
     18    reqinfo = (struct ps3stor_msg_info*)malloc(insize);
     19    memset(reqinfo, 0, insize);
     20    reqinfo->length = insize;
     21    reqinfo->opcode = PS3STOR_CMD_ENCL_GET_COUNT;
     22
     23    struct ps3stor_msg_info* rspinfo = NULL;
     24    size_t outsize = sizeof(struct ps3stor_msg_info) + sizeof(enclcount);
     25    rspinfo = (struct ps3stor_msg_info*)malloc(outsize);
     26    memset(rspinfo, 0, outsize);
     27
     28    if(PS3STOR_ERRNO_SUCCESS != firecmd(hostid, reqinfo, rspinfo, outsize)) {
     29      free(reqinfo);
     30      free(rspinfo);
     31      return -1;
     32    }
     33    memcpy(&enclcount, rspinfo->body, sizeof(enclcount));
     34    free(reqinfo);
     35    free(rspinfo);
     36    return 0;
     37}
     38
     39ps3stor_errno ps3stor_channel::get_encllist(unsigned hostid, ps3stor_encl_list *&encllist, size_t listsize)
     40{
     41    struct ps3stor_msg_info* reqinfo = NULL;
     42    size_t insize = sizeof(struct ps3stor_msg_info);
     43    reqinfo = (struct ps3stor_msg_info*)malloc(insize);
     44    memset(reqinfo, 0, insize);
     45    reqinfo->length = insize;
     46    reqinfo->opcode = PS3STOR_CMD_ENCL_GET_LIST;
     47
     48    struct ps3stor_msg_info* rspinfo = NULL;
     49    size_t outsize = sizeof(struct ps3stor_msg_info) + listsize;
     50    rspinfo = (struct ps3stor_msg_info*)malloc(outsize);
     51    memset(rspinfo, 0, outsize);
     52
     53    if(PS3STOR_ERRNO_SUCCESS != firecmd(hostid, reqinfo, rspinfo, outsize)) {
     54      free(reqinfo);
     55      free(rspinfo);
     56      return -1;
     57    }
     58    memcpy(encllist, rspinfo->body, listsize);
     59    free(reqinfo);
     60    free(rspinfo);
     61    return 0;
     62}
     63
     64ps3stor_errno ps3stor_channel::pd_get_devcount_by_encl(unsigned hostid, uint8_t enclid, uint16_t &devcount)
     65{
     66    struct ps3stor_msg_info* reqinfo = NULL;
     67    size_t insize = sizeof(struct ps3stor_msg_info);
     68    reqinfo = (struct ps3stor_msg_info*)malloc(insize);
     69    memset(reqinfo, 0, insize);
     70    reqinfo->length = insize;
     71    reqinfo->opcode = PS3STOR_CMD_PD_GET_COUNT_IN_ENCL;
     72    reqinfo->id.type = PS3STOR_ID_GROUP_TYPE_PD_POSITION;
     73    reqinfo->id.pd_position.enclid = enclid;
     74
     75    struct ps3stor_msg_info* rspinfo = NULL;
     76    size_t outsize = sizeof(struct ps3stor_msg_info) + sizeof(devcount);
     77    rspinfo = (struct ps3stor_msg_info*)malloc(outsize);
     78    memset(rspinfo, 0, outsize);
     79
     80    if(PS3STOR_ERRNO_SUCCESS != firecmd(hostid, reqinfo, rspinfo, outsize)) {
     81        free(reqinfo);
     82        free(rspinfo);
     83        return -1;
     84    }
     85    memcpy(&devcount, rspinfo->body, sizeof(devcount));
     86    free(reqinfo);
     87    free(rspinfo);
     88    return 0;
     89}
     90
     91ps3stor_errno ps3stor_channel::pd_get_devlist_by_encl(unsigned hostid, uint8_t enclid, uint16_t *&devlist, size_t listsize)
     92{
     93  ps3stor_errno err = PS3STOR_ERRNO_SUCCESS;
     94
     95  struct ps3stor_msg_info* reqinfo = NULL;
     96  size_t insize = sizeof(struct ps3stor_msg_info);
     97  reqinfo = (struct ps3stor_msg_info*)malloc(insize);
     98  memset(reqinfo, 0, insize);
     99  reqinfo->length = insize;
     100  reqinfo->opcode = PS3STOR_CMD_PD_GET_DEV_LIST_IN_ENCL;
     101
     102  struct ps3stor_msg_info* rspinfo = NULL;
     103  size_t outsize = sizeof(struct ps3stor_msg_info) + listsize;
     104  rspinfo = (struct ps3stor_msg_info*)malloc(outsize);
     105  memset(rspinfo, 0, outsize);
     106  reqinfo->id.type = PS3STOR_ID_GROUP_TYPE_PD_POSITION;
     107  reqinfo->id.pd_position.enclid = enclid;
     108
     109  if(PS3STOR_ERRNO_SUCCESS != firecmd(hostid, reqinfo, rspinfo, outsize)) {
     110    free(reqinfo);
     111    free(rspinfo);
     112    return -1;
     113  }
     114  memcpy(devlist, rspinfo->body, listsize);
     115  free(reqinfo);
     116  free(rspinfo);
     117  return err;
     118}
     119
     120ps3stor_errno ps3stor_channel::pd_get_baseinfo_by_devid(unsigned hostid, unsigned devid, ps3stor_pd_baseinfo_t &baseinfo)
     121{
     122    baseinfo.enclid = 0;
     123    baseinfo.slotid = 0;
     124    ps3stor_batch_req_t *batchreq = NULL;
     125    struct ps3stor_tlv *req_tlv = NULL;
     126    uint32_t id_count = 1;
     127    uint32_t data_size = sizeof(ps3stor_pd_baseinfo_t);
     128
     129    unsigned reqsize = sizeof(ps3stor_batch_req_t) + id_count * sizeof(struct ps3stor_id_group);
     130    batchreq = (ps3stor_batch_req_t*)malloc(reqsize);
     131    memset(batchreq, 0, reqsize);
     132    batchreq->idcount = id_count;
     133    batchreq->datasize = data_size;
     134    batchreq->idgroup[0].type = PS3STOR_ID_GROUP_TYPE_DEVICE_ID;
     135    batchreq->idgroup[0].deviceid = (uint16_t)devid;
     136
     137    //packet batchreq
     138
     139    req_tlv = add_tlv_data(req_tlv, PS3STOR_MK_TLV_CODE(PS3STOR_BATCH_TLV_CODE_MASK, ps3stor_batch_req_t, idcount),
     140                                    &batchreq->idcount, (uint16_t)sizeof(batchreq->idcount));
     141    req_tlv = add_tlv_data(req_tlv, PS3STOR_MK_TLV_CODE(PS3STOR_BATCH_TLV_CODE_MASK, ps3stor_batch_req_t, datasize),
     142                                    &batchreq->datasize, (uint16_t)sizeof(batchreq->datasize));
     143    req_tlv = add_tlv_data(req_tlv, PS3STOR_MK_TLV_CODE(PS3STOR_BATCH_TLV_CODE_MASK, ps3stor_batch_req_t, idgroup),
     144                                    &batchreq->idgroup, (uint16_t)(id_count * sizeof(struct ps3stor_id_group)));
     145    if(req_tlv == NULL) {
     146        free(batchreq);
     147        return -1;
     148    }
     149
     150    ps3stor_batch_rsp_t *batchrsp = NULL;                               
     151    unsigned rspsize = sizeof(ps3stor_batch_rsp_t) + id_count * (sizeof(ps3stor_rsp_entry_t) + sizeof(ps3stor_pd_baseinfo_t));                                                                 
     152    batchrsp = (ps3stor_batch_rsp_t*)malloc(rspsize);
     153    memset(batchrsp, 0, rspsize);
     154
     155    // call ioc
     156    struct ps3stor_msg_info* reqinfo = NULL;
     157    size_t insize = sizeof(struct ps3stor_msg_info) + req_tlv->size;
     158    reqinfo = (struct ps3stor_msg_info*)malloc(insize);
     159    memset(reqinfo, 0, insize);
     160    reqinfo->length = insize;
     161    reqinfo->opcode = PS3STOR_CMD_PD_BASE_INFO;
     162    memcpy(reqinfo->body, req_tlv->buff, req_tlv->size);
     163
     164    struct ps3stor_msg_info* rspinfo = NULL;
     165    size_t outsize = sizeof(struct ps3stor_msg_info) + rspsize;
     166    rspinfo = (struct ps3stor_msg_info*)malloc(outsize);
     167    memset(rspinfo, 0, outsize);
     168
     169    if(PS3STOR_ERRNO_SUCCESS != firecmd(hostid, reqinfo, rspinfo, outsize)) {
     170        free(batchreq);
     171        free(req_tlv);
     172        free(batchrsp);
     173        free(reqinfo);
     174        free(rspinfo);
     175        return -1;
     176    }
     177    memcpy(batchrsp, rspinfo->body, rspsize);
     178    ps3stor_rsp_entry_t* entry = (ps3stor_rsp_entry_t*)batchrsp->rsp_entry;
     179    if(entry != NULL && entry->result == PS3STOR_ERRNO_SUCCESS) {
     180        memcpy(&baseinfo, entry->data, PS3STOR_MIN(entry->size, sizeof(ps3stor_pd_baseinfo_t)));
     181    } else {
     182        free(batchreq);
     183        free(req_tlv);
     184        free(batchrsp);
     185        free(reqinfo);
     186        free(rspinfo);
     187        return -1;
     188    }
     189
     190    free(batchreq);
     191    free(req_tlv);
     192    free(batchrsp);
     193    free(reqinfo);
     194    free(rspinfo);
     195    return 0;
     196}
     197
     198
     199ps3stor_errno ps3stor_channel::pd_scsi_passthrough(unsigned hostid, uint8_t eid, uint16_t sid,
     200                                                              ps3stor_scsi_req_t &scsireq, ps3stor_scsi_rsp &scsirsp,
     201                                                              uint8_t *&scsidata, const size_t scsilen)
     202{
     203    // 1. scsi data align
     204    unsigned scsicount = scsilen / PS3STOR_SGL_SIZE;
     205    scsicount = (scsilen % PS3STOR_SGL_SIZE == 0) ? (scsicount) : ((scsicount + 1));
     206    struct ps3stor_data scsiblks[PS3STOR_SCSI_MAX_BLK_CNT] = {};
     207    if (scsicount > PS3STOR_SCSI_MAX_BLK_CNT)
     208    {
     209        set_err(EIO, "linux_ps3stor_device::scsi_cmd: request for scsi data is too large.");
     210        return -1;
     211    }
     212
     213    for(unsigned i = 0; i < scsicount; i++) {
     214        unsigned size = PS3STOR_SGL_SIZE;
     215        if(i == scsicount - 1) {
     216        size = scsilen - i * PS3STOR_SGL_SIZE;
     217        }
     218        size = (size % PS3STOR_SCSI_ALIGN_SIZE == 0) ? (size) : ((size / PS3STOR_SCSI_ALIGN_SIZE + 1) * PS3STOR_SCSI_ALIGN_SIZE);
     219        scsiblks[i].pdata = malloc(size);
     220        memset(scsiblks[i].pdata, 0, size);
     221        scsiblks[i].size = size;
     222        scsireq.req.datalen += size;
     223    }
     224
     225    scsireq.req.sgecount = (scsireq.req.datalen + PS3STOR_SCSI_BYTE_PER_CMD - 1) / PS3STOR_SCSI_BYTE_PER_CMD;
     226    scsireq.req.sgeindex = PS3STOR_SCSI_SGE_INDEX_BASE;
     227
     228    scsireq.req.id.type = PS3STOR_ID_GROUP_TYPE_PD_POSITION;
     229    scsireq.req.id.pd_position.enclid = eid;
     230    scsireq.req.id.pd_position.slotid = sid;
     231
     232    // 2. packet scsireq
     233    struct ps3stor_tlv *scsireq_tlv = NULL;
     234    scsireq_tlv = add_tlv_data(scsireq_tlv, PS3STOR_MK_TLV_CODE(PS3STOR_SCSI_TLV_CODE_MASK, ps3stor_scsi_req_t, reserved),
     235                                        &scsireq.reserved, (uint16_t)sizeof(scsireq.reserved));
     236    scsireq_tlv = add_tlv_data(scsireq_tlv, PS3STOR_MK_TLV_CODE(PS3STOR_SCSI_TLV_CODE_MASK, ps3stor_scsi_req_t, cmddir),
     237                                        &scsireq.cmddir, (uint16_t)sizeof(scsireq.cmddir));                                         
     238    scsireq_tlv = add_tlv_data(scsireq_tlv, PS3STOR_MK_TLV_CODE(PS3STOR_SCSI_TLV_CODE_MASK, ps3stor_scsi_req_t, checklen),
     239                                        &scsireq.checklen, (uint16_t)sizeof(scsireq.checklen));
     240    scsireq_tlv = add_tlv_data(scsireq_tlv, PS3STOR_MK_TLV_CODE(PS3STOR_SCSI_TLV_CODE_MASK, ps3stor_scsi_req_t, cdb),
     241                                        &scsireq.cdb, (uint16_t)PS3STOR_SCSI_CDB_LEN);
     242    scsireq_tlv = add_tlv_data(scsireq_tlv, PS3STOR_MK_TLV_CODE(PS3STOR_SCSI_TLV_CODE_MASK, ps3stor_scsi_req_t, req),
     243                                        &scsireq.req, (uint16_t)sizeof(scsireq.req));
     244    if(scsireq_tlv == NULL) {
     245        for(unsigned i = 0; i < scsicount; i++) {
     246            free(scsiblks[i].pdata);
     247        }
     248        return -1;
     249    }
     250
     251    // 3. call scsi passthrough
     252    struct ps3stor_msg_info* reqinfo = NULL;
     253    size_t insize = sizeof(struct ps3stor_msg_info) + scsireq_tlv->size;
     254    reqinfo = (struct ps3stor_msg_info*)malloc(insize);
     255    memset(reqinfo, 0, insize);
     256    reqinfo->length = insize;
     257    reqinfo->opcode = PS3STOR_CMD_PD_SCSI_PASSTHROUGH;
     258    memcpy(&reqinfo->id, &scsireq.req.id, sizeof(struct ps3stor_id_group));
     259    memcpy(reqinfo->body, scsireq_tlv->buff, scsireq_tlv->size);
     260
     261    struct ps3stor_msg_info* rspinfo = NULL;
     262    size_t outsize = sizeof(struct ps3stor_msg_info) + sizeof( struct ps3stor_scsi_rsp);
     263    rspinfo = (struct ps3stor_msg_info*)malloc(outsize);
     264    memset(rspinfo, 0, outsize);
     265
     266    if(PS3STOR_ERRNO_SUCCESS != firecmd_scsi(hostid, reqinfo, rspinfo, outsize, scsiblks, scsicount)) {
     267        for(unsigned i = 0; i < scsicount; i++) {
     268            free(scsiblks[i].pdata);
     269        }
     270        free(reqinfo);
     271        free(rspinfo);
     272        free(scsireq_tlv);
     273        return -1;
     274    }
     275
     276    // 4. copy and free memory
     277    memcpy(&scsirsp, rspinfo->body, sizeof(scsirsp));
     278    for(unsigned i = 0; i < scsicount; i++) {
     279        unsigned size = PS3STOR_SGL_SIZE;
     280        if(i == scsicount - 1) {
     281        size = scsilen - i * PS3STOR_SGL_SIZE;
     282        }
     283        memcpy(scsidata + i * PS3STOR_SGL_SIZE, scsiblks[i].pdata, size);
     284        free(scsiblks[i].pdata);
     285    }
     286    free(scsireq_tlv);
     287    free(reqinfo);
     288    free(rspinfo);
     289    return 0;
     290}
  • ps3stor.h

     
     1/*
     2 * ps3stor.h
     3 *
     4 * Home page of code is: http://www.smartmontools.org
     5 *
     6 * Copyright (C) 2024 Hong Xu
     7 *
     8 * SPDX-License-Identifier: GPL-2.0-or-later
     9 */
     10
     11#ifndef __PS3STOR_H__
     12#define __PS3STOR_H__
     13
     14#include "utility.h"
     15
     16#include <stdint.h>
     17#include <string>
     18#include <vector>
     19#include <stddef.h>
     20
     21typedef uint8_t                    encl_id_t;
     22typedef uint16_t                   slot_id_t;
     23typedef int32_t                    ps3stor_errno;
     24
     25#define PS3STOR_ERRNO_SUCCESS           (0)
     26
     27#define PS3STOR_ID_LIST_MAX_COUNT       (128)
     28#define PS3STOR_SCSI_STATUS_UNDERRUN    (140)
     29#define PS3STOR_MSG_MAGIC_CODE          (0x12345678)
     30#define PS3STOR_SGL_SIZE                (4 * 1024)
     31#define PS3STOR_ITR_VER                 (0x2000000)
     32#define PS3STOR_SMARTCTL_SERVICE        (0)
     33#define PS3STOR_SCSI_CDB_LEN            (32)
     34#define PS3STOR_SCSI_MAX_CDB_LENGTH     (32)
     35#define PS3STOR_SCSI_SENSE_BUFFER_LEN   (96)
     36#define PS3STOR_SCSI_MAX_BLK_CNT        (14)
     37#define PS3STOR_SCSI_ALIGN_SIZE         (512)
     38#define PS3STOR_SCSI_BYTE_PER_CMD       (4 * 1024)
     39#define PS3STOR_SCSI_SGE_INDEX_BASE     (2)
     40
     41#define  PS3STOR_DRIVE_DEVICE_ID                 "/proc/devices"
     42#define  PS3STOR_SYS_CLASS_SCSI_HOST_PATH        "/sys/class/scsi_host/"
     43#define  PS3STOR_SYS_BUS_PCI_DEVICE              "/sys/bus/pci/devices"
     44
     45#define PS3STOR_CMD_ENCL_GET_COUNT              (0x3040101)
     46#define PS3STOR_CMD_ENCL_GET_LIST               (0x3040102)
     47#define PS3STOR_CMD_PD_GET_COUNT_IN_ENCL        (0x3050101)
     48#define PS3STOR_CMD_PD_GET_DEV_LIST_IN_ENCL     (0x3050115)
     49#define PS3STOR_CMD_PD_SCSI_PASSTHROUGH         (0x23051c01)
     50#define PS3STOR_CMD_PD_BASE_INFO                (0x3050104)
     51
     52#define PS3STOR_SCSI_TLV_CODE_MASK              (0x41c01000)
     53#define PS3STOR_BATCH_TLV_CODE_MASK             (0x6000)
     54
     55#define PS3STOR_MIN(x,y)                ((x) < (y) ? (x) : (y))
     56#define PS3STOR_MK_TLV_CODE(code, struct_name, struct_member) \
     57        ((uint32_t) (code | offsetof(struct_name, struct_member)))
     58
     59#define PS3STOR_ID_GROUP_TYPE_UNKNOWN       (0)
     60#define PS3STOR_ID_GROUP_TYPE_DEVICE_ID     (1)
     61#define PS3STOR_ID_GROUP_TYPE_PD_POSITION   (2)
     62#define PS3STOR_SCSI_CMD_DIR_FROM_HOST      (1)
     63#define PS3STOR_SCSI_CMD_DIR_TO_HOST        (2)
     64#define PS3STOR_SCSI_CMD_DIR_NONE           (0)
     65
     66#define PS3STOR_INVALID_U64         (0xFFFFFFFFFFFFFFFF)
     67#define PS3STOR_INVALID_U32         (0xFFFFFFFF)
     68#define PS3STOR_INVALID_U16         (0xFFFF)
     69#define PS3STOR_INVALID_U8          (0xFF)
     70
     71#define PS3STOR_INVALID_ENCL_ID     (PS3STOR_INVALID_U8)
     72#define PS3STOR_INVALID_SLOT_ID     (PS3STOR_INVALID_U16)
     73
     74
     75struct ps3stor_pd_position {
     76    uint8_t     enclid;
     77    uint8_t     pad;
     78    uint16_t    slotid;
     79};
     80
     81struct ps3stor_id_group {
     82    uint8_t type;
     83    uint8_t pad[7];
     84    union{
     85        uint16_t                    deviceid;
     86        struct ps3stor_pd_position  pd_position;
     87        uint64_t                    reserved;   // align as 8 bytes
     88        uint8_t                     value[24];  // max for 24 bytes
     89    };
     90};
     91
     92struct ps3stor_tlv {
     93    int32_t size;
     94    uint8_t buff[0];
     95};
     96
     97struct ps3stor_encl_list
     98{
     99    uint8_t count;
     100    uint8_t idlist[0];
     101};
     102
     103struct ps3stor_msg_info {
     104    uint32_t magic;
     105    uint32_t opcode;
     106    uint32_t error;
     107    uint32_t timeout;
     108    uint32_t start_time;
     109    uint32_t runver;
     110    uint32_t length;
     111    uint32_t ack_offset;
     112    uint32_t ack_length;
     113    uint32_t leftmsg_count;
     114    uint32_t msg_index;
     115    uint8_t  reserved[4];
     116    uint64_t uuid;
     117    uint8_t  service;
     118    struct {
     119        uint8_t ack : 4;
     120        uint8_t tlv : 4;
     121    } index;
     122    uint8_t funcid : 1;
     123    uint8_t pad    : 7;
     124    uint8_t reserved2[5];
     125    struct ps3stor_id_group id;
     126    uint64_t traceid;
     127    uint8_t  body[0];
     128};
     129
     130#define PS3STOR_MSG_INFO_SIZE (sizeof(struct ps3stor_msg_info))
     131
     132struct ps3stor_sge {
     133    uint64_t    addr;
     134    uint32_t    length;
     135    uint32_t    reserved1 : 30;
     136    uint32_t    last_sge  : 1;
     137    uint32_t    ext       : 1;
     138};
     139
     140struct ps3stor_ioctl_sync_cmd {
     141    uint16_t    hostid;
     142    uint16_t    sgl_offset;
     143    uint16_t    sge_count;
     144    uint16_t    reserved1;
     145    uint32_t    result_code;
     146    uint8_t     reserved2[100];
     147    uint64_t    traceid;
     148    uint8_t     reserved3[120];
     149    uint8_t     reserved4[128];
     150    struct ps3stor_sge sgl[16];   
     151};
     152
     153#define PS3STOR_CMD_IOCTL_SYNC_CMD      _IOWR('M', 1, struct ps3stor_ioctl_sync_cmd)
     154
     155typedef struct  {
     156    uint32_t count;
     157    uint8_t  pad[4];
     158    int64_t  values[PS3STOR_ID_LIST_MAX_COUNT];
     159} ps3stor_id_list;
     160
     161struct ps3stor_pci_info {
     162    uint32_t domainid;
     163    uint8_t  busid;
     164    uint8_t  deviceid;
     165    uint8_t  function;
     166    uint8_t  devtype;
     167    char     pci_addr[32];
     168};
     169
     170struct ps3stor_data {
     171    void*    pdata;
     172    uint32_t size;
     173};
     174
     175struct ps3stor_scsi_info
     176{
     177    uint32_t datalen;
     178    uint32_t sgecount;
     179    uint32_t sgeindex;
     180    uint8_t  pad[4];
     181    struct ps3stor_id_group id;
     182};
     183
     184typedef struct ps3stor_scsi_req {
     185    uint32_t reserved;
     186    uint8_t  cmddir;
     187    uint8_t  checklen;
     188    uint8_t  pad[2];
     189    uint8_t  cdb[PS3STOR_SCSI_CDB_LEN];
     190    struct ps3stor_scsi_info req;
     191} ps3stor_scsi_req_t;
     192
     193struct ps3stor_scsi_rsp_entry {
     194    uint8_t  sensebuf[PS3STOR_SCSI_SENSE_BUFFER_LEN];
     195    uint8_t  status;
     196    uint8_t  pad1[3];
     197    uint32_t xfercnt;
     198    uint8_t  pad2[4];
     199    uint32_t result;
     200};
     201
     202struct ps3stor_scsi_rsp {
     203    uint32_t reserved;
     204    struct ps3stor_scsi_rsp_entry entry;
     205};
     206
     207typedef struct ps3stor_pd_baseinfo{
     208  uint16_t deviceid;
     209  uint8_t  reserved1[2];
     210  uint8_t  enclid;
     211  uint8_t  reserved2;
     212  uint16_t slotid;
     213  uint64_t reserved[22];
     214} ps3stor_pd_baseinfo_t;
     215
     216typedef struct ps3stor_batch_req{
     217  uint32_t   idcount;
     218  uint32_t   datasize;
     219  struct ps3stor_id_group idgroup[0];
     220} ps3stor_batch_req_t;
     221
     222typedef struct ps3stor_rsp_entry {
     223  int32_t   result;
     224  uint32_t  size;
     225  uint8_t   data[0];
     226} ps3stor_rsp_entry_t;
     227
     228typedef struct ps3stor_batch_rsp {
     229  uint32_t count;
     230  uint8_t rsp_entry[0]; // ps3stor_rsp_entry_t
     231} ps3stor_batch_rsp_t;
     232
     233
     234bool ps3stor_init();
     235/////////////////////////////////////////////////////////////////////////////
     236// ps3stor_channel
     237
     238/// The platform ps3stor channel abstraction
     239class ps3stor_channel
     240{
     241public:
     242  /// Initialize platform channel and register with ps3chn().
     243  /// Must be implemented by platform module and register channel with set()
     244  static void init();
     245
     246  ps3stor_channel()
     247    { m_init = false; }
     248
     249  virtual ~ps3stor_channel()
     250    { }
     251 
     252   /// Error (number,message) pair
     253  struct error_info {
     254    explicit error_info(int n = 0)
     255      : no(n) { }
     256    error_info(int n, const char * m)
     257      : no(n), msg(m) { }
     258    void clear()
     259      { no = 0; msg.erase(); }
     260
     261    int no;          ///< Error number
     262    std::string msg; ///< Error message
     263  };
     264protected:
     265  /// Set channel to use, must be called from init().
     266  static void set(ps3stor_channel * channel)
     267    { s_channel = channel; }
     268
     269public:
     270  virtual ps3stor_errno channel_init() = 0;
     271
     272  virtual ps3stor_errno get_host_list(std::vector<unsigned> &hostlist) = 0;
     273
     274  ps3stor_errno get_enclcount(unsigned hostid, uint8_t &enclcount); 
     275
     276  ps3stor_errno get_encllist(unsigned hostid, struct ps3stor_encl_list* &encllist, size_t listsize);
     277
     278  ps3stor_errno pd_get_devcount_by_encl(unsigned hostid, uint8_t enclid, uint16_t &devcount);                                           
     279
     280  ps3stor_errno pd_get_devlist_by_encl(unsigned hostid, uint8_t enclid, uint16_t* &devlist, size_t listsize);
     281
     282  ps3stor_errno pd_get_baseinfo_by_devid(unsigned hostid, unsigned devid, ps3stor_pd_baseinfo_t &basinfo);
     283
     284  ps3stor_errno pd_scsi_passthrough(unsigned hostid, uint8_t eid, uint16_t sid,
     285                                            ps3stor_scsi_req_t &scsireq, ps3stor_scsi_rsp &scsirsp,
     286                                            uint8_t * &scsidata, const size_t scsilen);
     287
     288protected:
     289  virtual ps3stor_errno firecmd(unsigned hostid, struct ps3stor_msg_info *info, struct ps3stor_msg_info * ackinfo, unsigned acksize) = 0;
     290
     291  virtual ps3stor_errno firecmd_scsi(unsigned hostid, struct ps3stor_msg_info * reqinfo, struct ps3stor_msg_info * ackinfo,
     292                                             unsigned acksize, struct ps3stor_data * scsidata, unsigned scsicount) = 0;
     293
     294  virtual struct ps3stor_tlv *add_tlv_data(struct ps3stor_tlv *tlv, unsigned type, const void *data, uint16_t size) = 0;
     295  ///////////////////////////////////////////////
     296  // Last error information
     297  /// Set last error number and message.
     298  /// Returns false always to allow use as a return expression.
     299  virtual bool set_err(int no, const char * msg) = 0;
     300
     301  /// Set last error number and default message.
     302  /// Message is retrieved from interface's get_msg_for_errno(no).
     303  virtual bool set_err(int no) = 0;
     304
     305  bool   m_init;
     306
     307private:
     308
     309  friend ps3stor_channel * ps3chn(); // below
     310  static ps3stor_channel * s_channel; ///< Pointer to the channel object.
     311
     312  // Prevent copy/assignment
     313  ps3stor_channel(const ps3stor_channel &);
     314  void operator=(const ps3stor_channel &);
     315
     316};
     317
     318/// Global access to the (usually singleton) ps3stor_channel
     319inline ps3stor_channel * ps3chn()
     320  { return ps3stor_channel::s_channel; }
     321
     322#endif
     323 No newline at end of file
  • smartctl.8.in

     
    778778\- the device consists of multiple SATA disks connected to a JMicron JMS56x
    779779USB to SATA RAID bridge.
    780780See \*(Aqjmb39x...\*(Aq above for valid arguments.
     781.Sp
     782.I ps3stor,n
     783\- [Linux only]
     784the device consists of one or more SCSI/SAS or SATA disks connected to a
     785PS3StorRAID controller.
     786The non-negative integer N (in the range of 0 to 127 inclusive) denotes the enclosure
     787and S (range 0 to 128) denotes the slot.
     788Use syntax such as:
     789.br
     790\fBsmartctl \-a \-d ps3stor,1 /dev/bus/0
     791.br
     792It is possible to set RAID device name as /dev/bus/N, where N is a
     793SCSI bus number.
     794.Sp
     795.\" %ENDIF OS Linux
    781796.TP
    782797.B \-T TYPE, \-\-tolerance=TYPE
    783798[ATA only] Specifies how tolerant \fBsmartctl\fP should be of ATA and SMART