| 1123 | /// Prolific USB Bridge support. (PL2773) (Probably works on PL2771 also...) |
| 1124 | |
| 1125 | class usbprolific_device |
| 1126 | : public tunnelled_device< |
| 1127 | /*implements*/ ata_device, |
| 1128 | /*by tunnelling through a*/ scsi_device |
| 1129 | > |
| 1130 | { |
| 1131 | public: |
| 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 | |
| 1141 | usbprolific_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 | |
| 1149 | usbprolific_device::~usbprolific_device() throw() |
| 1150 | { |
| 1151 | } |
| 1152 | |
| 1153 | bool 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 | |