Ticket #482: PL2773_ver1.patch

File PL2773_ver1.patch, 6.4 KB (added by TomVe, 9 years ago)

Patch against SVN rev. 4002

  • drivedb.h

     
    32763276    "",
    32773277    "-d usbjmicron,0" // Port number is required
    32783278  },
     3279  { "USB: ; Prolific PL2773", // USB->SATA
     3280    "0x067b:0x2773",
     3281    "",
     3282    "",
     3283    "-d usbprolific"
     3284  },
    32793285  { "USB: ; Prolific PL3507", // USB+IEE1394->PATA
    32803286    "0x067b:0x3507",
    32813287    "", // 0x0001
  • scsiata.cpp

     
    11201120
    11211121/////////////////////////////////////////////////////////////////////////////
    11221122
     1123/// Prolific USB Bridge support. (PL2773) (Probably works on PL2771 also...)
     1124
     1125class usbprolific_device
     1126: public tunnelled_device<
     1127    /*implements*/ ata_device,
     1128    /*by tunnelling through a*/ scsi_device
     1129  >
     1130{
     1131public:
     1132  usbprolific_device(smart_interface * intf, scsi_device * scsidev,
     1133                    const char * req_type);
     1134
     1135  virtual ~usbprolific_device() throw();
     1136
     1137  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
     1138};
     1139
     1140
     1141usbprolific_device::usbprolific_device(smart_interface * intf, scsi_device * scsidev,
     1142                                     const char * req_type)
     1143: smart_device(intf, scsidev->get_dev_name(), "usbprolific", req_type),
     1144  tunnelled_device<ata_device, scsi_device>(scsidev)
     1145{
     1146  set_info().info_name = strprintf("%s [USB Prolific]", scsidev->get_info_name());
     1147}
     1148
     1149usbprolific_device::~usbprolific_device() throw()
     1150{
     1151}
     1152
     1153bool usbprolific_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
     1154{
     1155  if (!ata_cmd_is_supported(in,
     1156//    ata_device::supports_data_out |       // Does not work - better disable for now
     1157    ata_device::supports_smart_status,
     1158    "Prolific" )
     1159  )
     1160    return false;
     1161
     1162  scsi_cmnd_io io_hdr;
     1163  memset(&io_hdr, 0, sizeof(io_hdr));
     1164
     1165  switch (in.direction) {
     1166    case ata_cmd_in::no_data:
     1167      io_hdr.dxfer_dir = DXFER_NONE;
     1168      break;
     1169    case ata_cmd_in::data_in:
     1170      io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
     1171      io_hdr.dxfer_len = in.size;
     1172      io_hdr.dxferp = (unsigned char *)in.buffer;
     1173      memset(in.buffer, 0, in.size);
     1174      break;
     1175    case ata_cmd_in::data_out:
     1176      io_hdr.dxfer_dir = DXFER_TO_DEVICE;
     1177      io_hdr.dxfer_len = in.size;
     1178      io_hdr.dxferp = (unsigned char *)in.buffer;
     1179      break;
     1180    default:
     1181      return set_err(EINVAL);
     1182  }
     1183
     1184  // Based on reverse engineering of iSmart.exe with API Monitor.
     1185  // http://www.prolific.com.tw/US/supportDownload.aspx?FileType=56&FileID=88&pcid=84&Page=0
     1186  // Seen commands:
     1187  // D0  0 0  0 06 7B 0 0 0 0 0 0                 // Read Firmware info?, reads 16 bytes
     1188  // F4  0 0  0 06 7B                             // ??
     1189  // D8 15 0 D8 06 7B 0 0 0 0 1 1 4F C2 A0 B0     // SMART Enable
     1190  // D8 15 0 D0 06 7B 0 0 2 0 1 1 4F C2 A0 B0     // SMART Read values
     1191  // D8 15 0 D1 06 7B 0 0 2 0 1 1 4F C2 A0 B0     // SMART Read thresholds
     1192  // D8 15 0 D4 06 7B 0 0 0 0 0 1 4F C2 A0 B0     // SMART Execute self test
     1193  // D7  0 0  0 06 7B 0 0 0 0 0 0 0 0 0 0         // Read status registers??, Reads 16 bytes of data, changes at self-test
     1194
     1195  // Build pass through command
     1196  unsigned char cdb[16];
     1197  cdb[ 0] = 0xD8;  // Prolific ATA pass through? (OPERATION CODE)
     1198  cdb[ 1] = 0x15;  // Magic?
     1199  cdb[ 2] = 0x0;   // Always 0?
     1200  cdb[ 3] = in.in_regs.features;        // SMART command
     1201  cdb[ 4] = 0x06;  // VendorID magic? (Prolific VendorID: 0x067B)
     1202  cdb[ 5] = 0x7B;  // VendorID magic? (Prolific VendorID: 0x067B)
     1203  cdb[ 6] = 0;     // Always 0?
     1204  cdb[ 7] = 0;     // Always 0?
     1205  cdb[ 8] = (unsigned char)(io_hdr.dxfer_len >> 8);     // 2 when reading a sector
     1206  cdb[ 9] = (unsigned char)(io_hdr.dxfer_len     );     // Always 0? - Seems ok
     1207  cdb[10] = in.in_regs.sector_count;    // 0 when starting selftest
     1208  cdb[11] = in.in_regs.lba_low;         // LBA(7:0)   - Works for Log Address!
     1209  cdb[12] = in.in_regs.lba_mid;         // LBA(15:8)  - 0x4F
     1210  cdb[13] = in.in_regs.lba_high;        // LBA(23:16) - 0xC2
     1211  cdb[14] = in.in_regs.device | 0xA0;   // 0xA0;
     1212  cdb[15] = in.in_regs.command;         // ATA command
     1213
     1214//  printf("DEBUG:CDB %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
     1215//    cdb[0],cdb[1],cdb[2],cdb[3],cdb[4],cdb[5],cdb[6],cdb[7],
     1216//    cdb[8],cdb[9],cdb[10],cdb[11],cdb[12],cdb[13],cdb[14],cdb[15]);
     1217
     1218  io_hdr.cmnd = cdb;
     1219  io_hdr.cmnd_len = 16;
     1220
     1221  scsi_device * scsidev = get_tunnel_dev();
     1222  if (!scsi_pass_through_and_check(scsidev, &io_hdr,
     1223         "usbprolific_device::ata_pass_through: "))
     1224    return set_err(scsidev->get_err());
     1225
     1226  if (in.out_needed.is_set()) {
     1227    // Read ATA output registers
     1228    unsigned char regbuf[16] = {0, };
     1229    memset(&io_hdr, 0, sizeof(io_hdr));
     1230    io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
     1231    io_hdr.dxfer_len = sizeof(regbuf);
     1232    io_hdr.dxferp = regbuf;
     1233
     1234    memset(cdb, 0, sizeof(cdb));
     1235    cdb[ 0] = 0xD7;  // Prolific read registers?
     1236    cdb[ 4] = 0x06;  // VendorID magic? (Prolific VendorID: 0x067B)
     1237    cdb[ 5] = 0x7B;  // VendorID magic? (Prolific VendorID: 0x067B)
     1238    io_hdr.cmnd = cdb;
     1239    io_hdr.cmnd_len = sizeof(cdb);
     1240
     1241    if (!scsi_pass_through_and_check(scsidev, &io_hdr,
     1242           "usbprolific_device::scsi_pass_through (get registers): "))
     1243      return set_err(scsidev->get_err());
     1244
     1245//  printf("DEBUG:REG %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
     1246//    regbuf[0],regbuf[1],regbuf[2],regbuf[3],regbuf[4],regbuf[5],regbuf[6],regbuf[7],
     1247//    regbuf[8],regbuf[9],regbuf[10],regbuf[11],regbuf[12],regbuf[13],regbuf[14],regbuf[15]);
     1248//  // DEBUG:REG 50 0 0 0 0 0 4f 0 c2 0 a0 da 0 b0 0 50
     1249//    out.out_regs.error        = regbuf[X];
     1250//    out.out_regs.sector_count = regbuf[X];
     1251    out.out_regs.lba_low      = regbuf[4];  // Found by testing with other commands
     1252    out.out_regs.lba_mid      = regbuf[6];
     1253    out.out_regs.lba_high     = regbuf[8];
     1254    out.out_regs.device       = regbuf[10];
     1255//    out.out_regs.status       = regbuf[X];
     1256  }
     1257
     1258  return true;
     1259}
     1260
     1261
     1262/////////////////////////////////////////////////////////////////////////////
     1263
    11231264/// SunplusIT USB Bridge support.
    11241265
    11251266class usbsunplus_device
     
    13281469    return new usbjmicron_device(this, scsidev, type, prolific, ata_48bit_support, port);
    13291470  }
    13301471
     1472  else if (!strcmp(type, "usbprolific")) {
     1473    return new usbprolific_device(this, scsidev, type);
     1474  }
     1475
    13311476  else if (!strcmp(type, "usbsunplus")) {
    13321477    return new usbsunplus_device(this, scsidev, type);
    13331478  }