scsireq.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * This is /sys/src/cmd/scuzz/scsireq.c
  11. * changed to add more debug support, to keep
  12. * disk compiling without a scuzz that includes these changes.
  13. * Also, this includes minor tweaks for usb:
  14. * we set req.lun/unit to rp->lun/unit in SRreqsense
  15. * we set the rp->sense[0] bit Sd0valid in SRreqsense
  16. * This does not use libdisk to retrieve the scsi error to make
  17. * user see the diagnostics if we boot with debug enabled.
  18. *
  19. * BUGS:
  20. * no luns
  21. * and incomplete in many other ways
  22. */
  23. #include <u.h>
  24. #include <libc.h>
  25. #include <fcall.h>
  26. #include <disk.h>
  27. #include <usb/scsireq.h>
  28. enum {
  29. Debug = 0,
  30. };
  31. /*
  32. * exabyte tape drives, at least old ones like the 8200 and 8505,
  33. * are dumb: you have to read the exact block size on the tape,
  34. * they don't take 10-byte SCSI commands, and various other fine points.
  35. */
  36. extern int exabyte, force6bytecmds;
  37. static int debug = Debug;
  38. static char *scmdnames[256] = {
  39. [ScmdTur] = "Tur",
  40. [ScmdRewind] = "Rewind",
  41. [ScmdRsense] = "Rsense",
  42. [ScmdFormat] = "Format",
  43. [ScmdRblimits] = "Rblimits",
  44. [ScmdRead] = "Read",
  45. [ScmdWrite] = "Write",
  46. [ScmdSeek] = "Seek",
  47. [ScmdFmark] = "Fmark",
  48. [ScmdSpace] = "Space",
  49. [ScmdInq] = "Inq",
  50. [ScmdMselect6] = "Mselect6",
  51. [ScmdMselect10] = "Mselect10",
  52. [ScmdMsense6] = "Msense6",
  53. [ScmdMsense10] = "Msense10",
  54. [ScmdStart] = "Start",
  55. [ScmdRcapacity] = "Rcapacity",
  56. [ScmdRcapacity16] = "Rcap16",
  57. [ScmdExtread] = "Extread",
  58. [ScmdExtwrite] = "Extwrite",
  59. [ScmdExtseek] = "Extseek",
  60. [ScmdSynccache] = "Synccache",
  61. [ScmdRTOC] = "RTOC",
  62. [ScmdRdiscinfo] = "Rdiscinfo",
  63. [ScmdRtrackinfo] = "Rtrackinfo",
  64. [ScmdReserve] = "Reserve",
  65. [ScmdBlank] = "Blank",
  66. [ScmdCDpause] = "CDpause",
  67. [ScmdCDstop] = "CDstop",
  68. [ScmdCDplay] = "CDplay",
  69. [ScmdCDload] = "CDload",
  70. [ScmdCDscan] = "CDscan",
  71. [ScmdCDstatus] = "CDstatus",
  72. [Scmdgetconf] = "getconf",
  73. };
  74. int32_t
  75. SRready(ScsiReq *rp)
  76. {
  77. uint8_t cmd[6];
  78. memset(cmd, 0, sizeof cmd);
  79. rp->cmd.p = cmd;
  80. rp->cmd.count = sizeof cmd;
  81. rp->data.p = cmd;
  82. rp->data.count = 0;
  83. rp->data.write = 1;
  84. return SRrequest(rp);
  85. }
  86. int32_t
  87. SRrewind(ScsiReq *rp)
  88. {
  89. uint8_t cmd[6];
  90. memset(cmd, 0, sizeof cmd);
  91. cmd[0] = ScmdRewind;
  92. rp->cmd.p = cmd;
  93. rp->cmd.count = sizeof cmd;
  94. rp->data.p = cmd;
  95. rp->data.count = 0;
  96. rp->data.write = 1;
  97. if(SRrequest(rp) >= 0){
  98. rp->offset = 0;
  99. return 0;
  100. }
  101. return -1;
  102. }
  103. int32_t
  104. SRreqsense(ScsiReq *rp)
  105. {
  106. uint8_t cmd[6];
  107. ScsiReq req;
  108. int32_t status;
  109. if(rp->status == Status_SD){
  110. rp->status = STok;
  111. return 0;
  112. }
  113. memset(cmd, 0, sizeof cmd);
  114. cmd[0] = ScmdRsense;
  115. cmd[4] = sizeof(req.sense);
  116. memset(&req, 0, sizeof(req));
  117. if(rp->flags&Fusb)
  118. req.flags |= Fusb;
  119. req.lun = rp->lun;
  120. req.unit = rp->unit;
  121. req.fd = rp->fd;
  122. req.umsc = rp->umsc;
  123. req.cmd.p = cmd;
  124. req.cmd.count = sizeof cmd;
  125. req.data.p = rp->sense;
  126. req.data.count = sizeof(rp->sense);
  127. req.data.write = 0;
  128. status = SRrequest(&req);
  129. rp->status = req.status;
  130. if(status != -1)
  131. rp->sense[0] |= Sd0valid;
  132. return status;
  133. }
  134. int32_t
  135. SRformat(ScsiReq *rp)
  136. {
  137. uint8_t cmd[6];
  138. memset(cmd, 0, sizeof cmd);
  139. cmd[0] = ScmdFormat;
  140. rp->cmd.p = cmd;
  141. rp->cmd.count = sizeof cmd;
  142. rp->data.p = cmd;
  143. rp->data.count = 6;
  144. rp->data.write = 0;
  145. return SRrequest(rp);
  146. }
  147. int32_t
  148. SRrblimits(ScsiReq *rp, uint8_t *list)
  149. {
  150. uint8_t cmd[6];
  151. memset(cmd, 0, sizeof cmd);
  152. cmd[0] = ScmdRblimits;
  153. rp->cmd.p = cmd;
  154. rp->cmd.count = sizeof cmd;
  155. rp->data.p = list;
  156. rp->data.count = 6;
  157. rp->data.write = 0;
  158. return SRrequest(rp);
  159. }
  160. static int
  161. dirdevrw(ScsiReq *rp, uint8_t *cmd, int32_t nbytes)
  162. {
  163. int32_t n;
  164. n = nbytes / rp->lbsize;
  165. if(rp->offset <= Max24off && n <= 256 && (rp->flags & Frw10) == 0){
  166. PUTBE24(cmd+1, rp->offset);
  167. cmd[4] = n;
  168. cmd[5] = 0;
  169. return 6;
  170. }
  171. cmd[0] |= ScmdExtread;
  172. cmd[1] = 0;
  173. PUTBELONG(cmd+2, rp->offset);
  174. cmd[6] = 0;
  175. cmd[7] = n>>8;
  176. cmd[8] = n;
  177. cmd[9] = 0;
  178. return 10;
  179. }
  180. static int
  181. seqdevrw(ScsiReq *rp, uint8_t *cmd, int32_t nbytes)
  182. {
  183. int32_t n;
  184. /* don't set Cmd1sili; we want the ILI bit instead of a fatal error */
  185. cmd[1] = rp->flags&Fbfixed? Cmd1fixed: 0;
  186. n = nbytes / rp->lbsize;
  187. PUTBE24(cmd+2, n);
  188. cmd[5] = 0;
  189. return 6;
  190. }
  191. extern int diskdebug;
  192. int32_t
  193. SRread(ScsiReq *rp, void *buf, int32_t nbytes)
  194. {
  195. uint8_t cmd[10];
  196. int32_t n;
  197. if(rp->lbsize == 0 || (nbytes % rp->lbsize) || nbytes > Maxiosize){
  198. if(diskdebug)
  199. if (nbytes % rp->lbsize)
  200. fprint(2, "disk: i/o size %ld %% %ld != 0\n",
  201. nbytes, rp->lbsize);
  202. else
  203. fprint(2, "disk: i/o size %ld > %d\n",
  204. nbytes, Maxiosize);
  205. rp->status = Status_BADARG;
  206. return -1;
  207. }
  208. /* set up scsi read cmd */
  209. cmd[0] = ScmdRead;
  210. if(rp->flags & Fseqdev)
  211. rp->cmd.count = seqdevrw(rp, cmd, nbytes);
  212. else
  213. rp->cmd.count = dirdevrw(rp, cmd, nbytes);
  214. rp->cmd.p = cmd;
  215. rp->data.p = buf;
  216. rp->data.count = nbytes;
  217. rp->data.write = 0;
  218. /* issue it */
  219. n = SRrequest(rp);
  220. if(n != -1){ /* it worked? */
  221. rp->offset += n / rp->lbsize;
  222. return n;
  223. }
  224. /* request failed; maybe we just read a short record? */
  225. if (exabyte) {
  226. fprint(2, "read error\n");
  227. rp->status = STcheck;
  228. return n;
  229. }
  230. if(rp->status != Status_SD || !(rp->sense[0] & Sd0valid))
  231. return -1;
  232. /* compute # of bytes not read */
  233. n = GETBELONG(rp->sense+3) * rp->lbsize;
  234. if(!(rp->flags & Fseqdev))
  235. return -1;
  236. /* device is a tape or something similar */
  237. if (rp->sense[2] == Sd2filemark || rp->sense[2] == 0x08 ||
  238. rp->sense[2] & Sd2ili && n > 0)
  239. rp->data.count = nbytes - n;
  240. else
  241. return -1;
  242. n = rp->data.count;
  243. if (!rp->readblock++ || debug)
  244. fprint(2, "SRread: tape data count %ld%s\n", n,
  245. (rp->sense[2] & Sd2ili? " with ILI": ""));
  246. rp->status = STok;
  247. rp->offset += n / rp->lbsize;
  248. return n;
  249. }
  250. int32_t
  251. SRwrite(ScsiReq *rp, void *buf, int32_t nbytes)
  252. {
  253. uint8_t cmd[10];
  254. int32_t n;
  255. if(rp->lbsize == 0 || (nbytes % rp->lbsize) || nbytes > Maxiosize){
  256. if(diskdebug)
  257. if (nbytes % rp->lbsize)
  258. fprint(2, "disk: i/o size %ld %% %ld != 0\n",
  259. nbytes, rp->lbsize);
  260. else
  261. fprint(2, "disk: i/o size %ld > %d\n",
  262. nbytes, Maxiosize);
  263. rp->status = Status_BADARG;
  264. return -1;
  265. }
  266. /* set up scsi write cmd */
  267. cmd[0] = ScmdWrite;
  268. if(rp->flags & Fseqdev)
  269. rp->cmd.count = seqdevrw(rp, cmd, nbytes);
  270. else
  271. rp->cmd.count = dirdevrw(rp, cmd, nbytes);
  272. rp->cmd.p = cmd;
  273. rp->data.p = buf;
  274. rp->data.count = nbytes;
  275. rp->data.write = 1;
  276. /* issue it */
  277. if((n = SRrequest(rp)) == -1){
  278. if (exabyte) {
  279. fprint(2, "write error\n");
  280. rp->status = STcheck;
  281. return n;
  282. }
  283. if(rp->status != Status_SD || rp->sense[2] != Sd2eom)
  284. return -1;
  285. if(rp->sense[0] & Sd0valid){
  286. n -= GETBELONG(rp->sense+3) * rp->lbsize;
  287. rp->data.count = nbytes - n;
  288. }
  289. else
  290. rp->data.count = nbytes;
  291. n = rp->data.count;
  292. }
  293. rp->offset += n / rp->lbsize;
  294. return n;
  295. }
  296. int32_t
  297. SRseek(ScsiReq *rp, int32_t offset, int type)
  298. {
  299. uint8_t cmd[10];
  300. switch(type){
  301. case 0:
  302. break;
  303. case 1:
  304. offset += rp->offset;
  305. if(offset >= 0)
  306. break;
  307. /*FALLTHROUGH*/
  308. default:
  309. if(diskdebug)
  310. fprint(2, "disk: seek failed\n");
  311. rp->status = Status_BADARG;
  312. return -1;
  313. }
  314. memset(cmd, 0, sizeof cmd);
  315. if(offset <= Max24off && (rp->flags & Frw10) == 0){
  316. cmd[0] = ScmdSeek;
  317. PUTBE24(cmd+1, offset & Max24off);
  318. rp->cmd.count = 6;
  319. }else{
  320. cmd[0] = ScmdExtseek;
  321. PUTBELONG(cmd+2, offset);
  322. rp->cmd.count = 10;
  323. }
  324. rp->cmd.p = cmd;
  325. rp->data.p = cmd;
  326. rp->data.count = 0;
  327. rp->data.write = 1;
  328. SRrequest(rp);
  329. if(rp->status == STok) {
  330. rp->offset = offset;
  331. return offset;
  332. }
  333. return -1;
  334. }
  335. int32_t
  336. SRfilemark(ScsiReq *rp, uint32_t howmany)
  337. {
  338. uint8_t cmd[6];
  339. memset(cmd, 0, sizeof cmd);
  340. cmd[0] = ScmdFmark;
  341. PUTBE24(cmd+2, howmany);
  342. rp->cmd.p = cmd;
  343. rp->cmd.count = sizeof cmd;
  344. rp->data.p = cmd;
  345. rp->data.count = 0;
  346. rp->data.write = 1;
  347. return SRrequest(rp);
  348. }
  349. int32_t
  350. SRspace(ScsiReq *rp, uint8_t code, int32_t howmany)
  351. {
  352. uint8_t cmd[6];
  353. memset(cmd, 0, sizeof cmd);
  354. cmd[0] = ScmdSpace;
  355. cmd[1] = code;
  356. PUTBE24(cmd+2, howmany);
  357. rp->cmd.p = cmd;
  358. rp->cmd.count = sizeof cmd;
  359. rp->data.p = cmd;
  360. rp->data.count = 0;
  361. rp->data.write = 1;
  362. /*
  363. * what about rp->offset?
  364. */
  365. return SRrequest(rp);
  366. }
  367. int32_t
  368. SRinquiry(ScsiReq *rp)
  369. {
  370. uint8_t cmd[6];
  371. memset(cmd, 0, sizeof cmd);
  372. cmd[0] = ScmdInq;
  373. cmd[4] = sizeof rp->inquiry;
  374. rp->cmd.p = cmd;
  375. rp->cmd.count = sizeof cmd;
  376. memset(rp->inquiry, 0, sizeof rp->inquiry);
  377. rp->data.p = rp->inquiry;
  378. rp->data.count = sizeof rp->inquiry;
  379. rp->data.write = 0;
  380. if(SRrequest(rp) >= 0){
  381. rp->flags |= Finqok;
  382. return 0;
  383. }
  384. rp->flags &= ~Finqok;
  385. return -1;
  386. }
  387. int32_t
  388. SRmodeselect6(ScsiReq *rp, uint8_t *list, int32_t nbytes)
  389. {
  390. uint8_t cmd[6];
  391. memset(cmd, 0, sizeof cmd);
  392. cmd[0] = ScmdMselect6;
  393. if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
  394. cmd[1] = 0x10;
  395. cmd[4] = nbytes;
  396. rp->cmd.p = cmd;
  397. rp->cmd.count = sizeof cmd;
  398. rp->data.p = list;
  399. rp->data.count = nbytes;
  400. rp->data.write = 1;
  401. return SRrequest(rp);
  402. }
  403. int32_t
  404. SRmodeselect10(ScsiReq *rp, uint8_t *list, int32_t nbytes)
  405. {
  406. uint8_t cmd[10];
  407. memset(cmd, 0, sizeof cmd);
  408. if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
  409. cmd[1] = 0x10;
  410. cmd[0] = ScmdMselect10;
  411. cmd[7] = nbytes>>8;
  412. cmd[8] = nbytes;
  413. rp->cmd.p = cmd;
  414. rp->cmd.count = sizeof cmd;
  415. rp->data.p = list;
  416. rp->data.count = nbytes;
  417. rp->data.write = 1;
  418. return SRrequest(rp);
  419. }
  420. int32_t
  421. SRmodesense6(ScsiReq *rp, uint8_t page, uint8_t *list, int32_t nbytes)
  422. {
  423. uint8_t cmd[6];
  424. memset(cmd, 0, sizeof cmd);
  425. cmd[0] = ScmdMsense6;
  426. cmd[2] = page;
  427. cmd[4] = nbytes;
  428. rp->cmd.p = cmd;
  429. rp->cmd.count = sizeof cmd;
  430. rp->data.p = list;
  431. rp->data.count = nbytes;
  432. rp->data.write = 0;
  433. return SRrequest(rp);
  434. }
  435. int32_t
  436. SRmodesense10(ScsiReq *rp, uint8_t page, uint8_t *list, int32_t nbytes)
  437. {
  438. uint8_t cmd[10];
  439. memset(cmd, 0, sizeof cmd);
  440. cmd[0] = ScmdMsense10;
  441. cmd[2] = page;
  442. cmd[7] = nbytes>>8;
  443. cmd[8] = nbytes;
  444. rp->cmd.p = cmd;
  445. rp->cmd.count = sizeof cmd;
  446. rp->data.p = list;
  447. rp->data.count = nbytes;
  448. rp->data.write = 0;
  449. return SRrequest(rp);
  450. }
  451. int32_t
  452. SRstart(ScsiReq *rp, uint8_t code)
  453. {
  454. uint8_t cmd[6];
  455. memset(cmd, 0, sizeof cmd);
  456. cmd[0] = ScmdStart;
  457. cmd[4] = code;
  458. rp->cmd.p = cmd;
  459. rp->cmd.count = sizeof cmd;
  460. rp->data.p = cmd;
  461. rp->data.count = 0;
  462. rp->data.write = 1;
  463. return SRrequest(rp);
  464. }
  465. int32_t
  466. SRrcapacity(ScsiReq *rp, uint8_t *data)
  467. {
  468. uint8_t cmd[10];
  469. memset(cmd, 0, sizeof cmd);
  470. cmd[0] = ScmdRcapacity;
  471. rp->cmd.p = cmd;
  472. rp->cmd.count = sizeof cmd;
  473. rp->data.p = data;
  474. rp->data.count = 8;
  475. rp->data.write = 0;
  476. return SRrequest(rp);
  477. }
  478. int32_t
  479. SRrcapacity16(ScsiReq *rp, uint8_t *data)
  480. {
  481. uint8_t cmd[16];
  482. uint i;
  483. i = 32;
  484. memset(cmd, 0, sizeof cmd);
  485. cmd[0] = ScmdRcapacity16;
  486. cmd[1] = 0x10;
  487. cmd[10] = i>>24;
  488. cmd[11] = i>>16;
  489. cmd[12] = i>>8;
  490. cmd[13] = i;
  491. rp->cmd.p = cmd;
  492. rp->cmd.count = sizeof cmd;
  493. rp->data.p = data;
  494. rp->data.count = i;
  495. rp->data.write = 0;
  496. return SRrequest(rp);
  497. }
  498. void
  499. scsidebug(int d)
  500. {
  501. debug = d;
  502. if(debug)
  503. fprint(2, "scsidebug on\n");
  504. }
  505. static int32_t
  506. request(int fd, ScsiPtr *cmd, ScsiPtr *data, int *status)
  507. {
  508. int32_t n, r;
  509. char buf[16];
  510. /* this was an experiment but it seems to be a good idea */
  511. *status = STok;
  512. /* send SCSI command */
  513. if(write(fd, cmd->p, cmd->count) != cmd->count){
  514. fprint(2, "scsireq: write cmd: %r\n");
  515. *status = Status_SW;
  516. return -1;
  517. }
  518. /* read or write actual data */
  519. werrstr("");
  520. // alarm(5*1000);
  521. if(data->write)
  522. n = write(fd, data->p, data->count);
  523. else {
  524. n = read(fd, data->p, data->count);
  525. if (n < 0)
  526. memset(data->p, 0, data->count);
  527. else if (n < data->count)
  528. memset(data->p + n, 0, data->count - n);
  529. }
  530. // alarm(0);
  531. if (n != data->count && n <= 0) {
  532. if (debug)
  533. fprint(2,
  534. "request: tried to %s %ld bytes of data for cmd 0x%x but got %r\n",
  535. (data->write? "write": "read"),
  536. data->count, cmd->p[0]);
  537. } else if (n != data->count && (data->write || debug))
  538. fprint(2, "request: %s %ld of %ld bytes of actual data\n",
  539. (data->write? "wrote": "read"), n, data->count);
  540. /* read status */
  541. buf[0] = '\0';
  542. r = read(fd, buf, sizeof buf-1);
  543. if(exabyte && r <= 0 || !exabyte && r < 0){
  544. fprint(2, "scsireq: read status: %r\n");
  545. *status = Status_SW;
  546. return -1;
  547. }
  548. if (r >= 0)
  549. buf[r] = '\0';
  550. *status = atoi(buf);
  551. if(n < 0 && (exabyte || *status != STcheck))
  552. fprint(2, "scsireq: status 0x%2.2uX: data transfer: %r\n",
  553. *status);
  554. return n;
  555. }
  556. static char*
  557. seprintcmd(char *s, char* e, char *cmd, int count, int args)
  558. {
  559. uint c;
  560. if(count < 6)
  561. return seprint(s, e, "<short cmd>");
  562. c = cmd[0];
  563. if(scmdnames[c] != nil)
  564. s = seprint(s, e, "%s", scmdnames[c]);
  565. else
  566. s = seprint(s, e, "cmd:%#02uX", c);
  567. if(args != 0)
  568. switch(c){
  569. case ScmdRsense:
  570. case ScmdInq:
  571. case ScmdMselect6:
  572. case ScmdMsense6:
  573. s = seprint(s, e, " sz %d", cmd[4]);
  574. break;
  575. case ScmdSpace:
  576. s = seprint(s, e, " code %d", cmd[1]);
  577. break;
  578. case ScmdStart:
  579. s = seprint(s, e, " code %d", cmd[4]);
  580. break;
  581. }
  582. return s;
  583. }
  584. static char*
  585. seprintdata(char *s, char *se, uint8_t *p, int count)
  586. {
  587. int i;
  588. if(count == 0)
  589. return s;
  590. for(i = 0; i < 20 && i < count; i++)
  591. s = seprint(s, se, " %02x", p[i]);
  592. return s;
  593. }
  594. static void
  595. SRdumpReq(ScsiReq *rp)
  596. {
  597. char buf[128];
  598. char *s;
  599. char *se;
  600. se = buf+sizeof(buf);
  601. s = seprint(buf, se, "lun %d ", rp->lun);
  602. s = seprintcmd(s, se, (char*)rp->cmd.p, rp->cmd.count, 1);
  603. s = seprint(s, se, " [%ld]", rp->data.count);
  604. if(rp->cmd.write)
  605. seprintdata(s, se, rp->data.p, rp->data.count);
  606. fprint(2, "scsi⇒ %s\n", buf);
  607. }
  608. static void
  609. SRdumpRep(ScsiReq *rp)
  610. {
  611. char buf[128];
  612. char *s;
  613. char *se;
  614. se = buf+sizeof(buf);
  615. s = seprint(buf, se, "lun %d ", rp->lun);
  616. s = seprintcmd(s, se, (char*)rp->cmd.p, rp->cmd.count, 0);
  617. switch(rp->status){
  618. case STok:
  619. s = seprint(s, se, " good [%ld] ", rp->data.count);
  620. if(rp->cmd.write == 0)
  621. s = seprintdata(s, se, rp->data.p, rp->data.count);
  622. break;
  623. case STnomem:
  624. s = seprint(s, se, " buffer allocation failed");
  625. break;
  626. case STharderr:
  627. s = seprint(s, se, " controller error");
  628. break;
  629. case STtimeout:
  630. s = seprint(s, se, " bus timeout");
  631. break;
  632. case STcheck:
  633. s = seprint(s, se, " check condition");
  634. break;
  635. case STcondmet:
  636. s = seprint(s, se, " condition met/good");
  637. break;
  638. case STbusy:
  639. s = seprint(s, se, " busy");
  640. break;
  641. case STintok:
  642. s = seprint(s, se, " intermediate/good");
  643. break;
  644. case STintcondmet:
  645. s = seprint(s, se, " intermediate/condition met/good");
  646. break;
  647. case STresconf:
  648. s = seprint(s, se, " reservation conflict");
  649. break;
  650. case STterminated:
  651. s = seprint(s, se, " command terminated");
  652. break;
  653. case STqfull:
  654. s = seprint(s, se, " queue full");
  655. break;
  656. default:
  657. s = seprint(s, se, " sts=%#x", rp->status);
  658. }
  659. USED(s);
  660. fprint(2, "scsi← %s\n", buf);
  661. }
  662. static char*
  663. scsierr(ScsiReq *rp)
  664. {
  665. int ec;
  666. switch(rp->status){
  667. case 0:
  668. return "";
  669. case Status_SD:
  670. ec = (rp->sense[12] << 8) | rp->sense[13];
  671. return scsierrmsg(ec);
  672. case Status_SW:
  673. return "software error";
  674. case Status_BADARG:
  675. return "bad argument";
  676. case Status_RO:
  677. return "device is read only";
  678. default:
  679. return "unknown";
  680. }
  681. }
  682. static void
  683. SRdumpErr(ScsiReq *rp)
  684. {
  685. char buf[128];
  686. char *se;
  687. se = buf+sizeof(buf);
  688. seprintcmd(buf, se, (char*)rp->cmd.p, rp->cmd.count, 0);
  689. fprint(2, "\t%s status: %s\n", buf, scsierr(rp));
  690. }
  691. int32_t
  692. SRrequest(ScsiReq *rp)
  693. {
  694. int32_t n;
  695. int status;
  696. retry:
  697. if(debug)
  698. SRdumpReq(rp);
  699. if(rp->flags&Fusb)
  700. n = umsrequest(rp->umsc, &rp->cmd, &rp->data, &status);
  701. else
  702. n = request(rp->fd, &rp->cmd, &rp->data, &status);
  703. rp->status = status;
  704. if(status == STok)
  705. rp->data.count = n;
  706. if(debug)
  707. SRdumpRep(rp);
  708. switch(status){
  709. case STok:
  710. break;
  711. case STcheck:
  712. if(rp->cmd.p[0] != ScmdRsense && SRreqsense(rp) != -1)
  713. rp->status = Status_SD;
  714. if(debug || exabyte)
  715. SRdumpErr(rp);
  716. werrstr("%s", scsierr(rp));
  717. return -1;
  718. case STbusy:
  719. sleep(1000); /* TODO: try a shorter sleep? */
  720. goto retry;
  721. default:
  722. if(debug || exabyte)
  723. SRdumpErr(rp);
  724. werrstr("%s", scsierr(rp));
  725. return -1;
  726. }
  727. return n;
  728. }
  729. int
  730. SRclose(ScsiReq *rp)
  731. {
  732. if((rp->flags & Fopen) == 0){
  733. if(diskdebug)
  734. fprint(2, "disk: closing closed file\n");
  735. rp->status = Status_BADARG;
  736. return -1;
  737. }
  738. close(rp->fd);
  739. rp->flags = 0;
  740. return 0;
  741. }
  742. static int
  743. dirdevopen(ScsiReq *rp)
  744. {
  745. uint64_t blocks;
  746. uint8_t data[8+4+20]; /* 16-byte result: lba, blksize, reserved */
  747. memset(data, 0, sizeof data);
  748. if(SRstart(rp, 1) == -1 || SRrcapacity(rp, data) == -1)
  749. return -1;
  750. rp->lbsize = GETBELONG(data+4);
  751. blocks = GETBELONG(data);
  752. if(debug)
  753. fprint(2, "disk: dirdevopen: 10-byte logical block size %lu, "
  754. "# blocks %llu\n", rp->lbsize, blocks);
  755. if(blocks == 0xffffffff){
  756. if(SRrcapacity16(rp, data) == -1)
  757. return -1;
  758. rp->lbsize = GETBELONG(data + 8);
  759. blocks = (int64_t)GETBELONG(data)<<32 | GETBELONG(data + 4);
  760. if(debug)
  761. fprint(2, "disk: dirdevopen: 16-byte logical block size"
  762. " %lu, # blocks %llu\n", rp->lbsize, blocks);
  763. }
  764. /* some newer dev's don't support 6-byte commands */
  765. if(blocks > Max24off && !force6bytecmds)
  766. rp->flags |= Frw10;
  767. return 0;
  768. }
  769. static int
  770. seqdevopen(ScsiReq *rp)
  771. {
  772. uint8_t mode[16], limits[6];
  773. if(SRrblimits(rp, limits) == -1)
  774. return -1;
  775. if(limits[1] == 0 && limits[2] == limits[4] && limits[3] == limits[5]){
  776. rp->flags |= Fbfixed;
  777. rp->lbsize = limits[4]<<8 | limits[5];
  778. if(debug)
  779. fprint(2, "disk: seqdevopen: 10-byte logical block size %lu\n",
  780. rp->lbsize);
  781. return 0;
  782. }
  783. /*
  784. * On some older hardware the optional 10-byte
  785. * modeselect command isn't implemented.
  786. */
  787. if (force6bytecmds)
  788. rp->flags |= Fmode6;
  789. if(!(rp->flags & Fmode6)){
  790. /* try 10-byte command first */
  791. memset(mode, 0, sizeof mode);
  792. mode[3] = 0x10; /* device-specific param. */
  793. mode[7] = 8; /* block descriptor length */
  794. /*
  795. * exabytes can't handle this, and
  796. * modeselect(10) is optional.
  797. */
  798. if(SRmodeselect10(rp, mode, sizeof mode) != -1){
  799. rp->lbsize = 1;
  800. return 0; /* success */
  801. }
  802. /* can't do 10-byte commands, back off to 6-byte ones */
  803. rp->flags |= Fmode6;
  804. }
  805. /* 6-byte command */
  806. memset(mode, 0, sizeof mode);
  807. mode[2] = 0x10; /* device-specific param. */
  808. mode[3] = 8; /* block descriptor length */
  809. /*
  810. * bsd sez exabytes need this bit (NBE: no busy enable) in
  811. * vendor-specific page (0), but so far we haven't needed it.
  812. mode[12] |= 8;
  813. */
  814. if(SRmodeselect6(rp, mode, 4+8) == -1)
  815. return -1;
  816. rp->lbsize = 1;
  817. return 0;
  818. }
  819. static int
  820. wormdevopen(ScsiReq *rp)
  821. {
  822. int32_t status;
  823. uint8_t list[MaxDirData];
  824. if (SRstart(rp, 1) == -1 ||
  825. (status = SRmodesense10(rp, Allmodepages, list, sizeof list)) == -1)
  826. return -1;
  827. /* nbytes = list[0]<<8 | list[1]; */
  828. /* # of bytes of block descriptors of 8 bytes each; not even 1? */
  829. if((list[6]<<8 | list[7]) < 8)
  830. rp->lbsize = 2048;
  831. else
  832. /* last 3 bytes of block 0 descriptor */
  833. rp->lbsize = GETBE24(list+13);
  834. if(debug)
  835. fprint(2, "disk: wormdevopen: 10-byte logical block size %lu\n",
  836. rp->lbsize);
  837. return status;
  838. }
  839. int
  840. SRopenraw(ScsiReq *rp, char *unit)
  841. {
  842. char name[128];
  843. if(rp->flags & Fopen){
  844. if(diskdebug)
  845. fprint(2, "disk: opening open file\n");
  846. rp->status = Status_BADARG;
  847. return -1;
  848. }
  849. memset(rp, 0, sizeof *rp);
  850. rp->unit = unit;
  851. snprint(name, sizeof name, "%s/raw", unit);
  852. if((rp->fd = open(name, ORDWR)) == -1){
  853. rp->status = STtimeout;
  854. return -1;
  855. }
  856. rp->flags = Fopen;
  857. return 0;
  858. }
  859. int
  860. SRopen(ScsiReq *rp, char *unit)
  861. {
  862. if(SRopenraw(rp, unit) == -1)
  863. return -1;
  864. SRready(rp);
  865. if(SRinquiry(rp) >= 0){
  866. switch(rp->inquiry[0]){
  867. default:
  868. fprint(2, "unknown device type 0x%.2x\n", rp->inquiry[0]);
  869. rp->status = Status_SW;
  870. break;
  871. case Devdir:
  872. case Devcd:
  873. case Devmo:
  874. if(dirdevopen(rp) == -1)
  875. break;
  876. return 0;
  877. case Devseq:
  878. rp->flags |= Fseqdev;
  879. if(seqdevopen(rp) == -1)
  880. break;
  881. return 0;
  882. case Devprint:
  883. rp->flags |= Fprintdev;
  884. return 0;
  885. case Devworm:
  886. rp->flags |= Fwormdev;
  887. if(wormdevopen(rp) == -1)
  888. break;
  889. return 0;
  890. case Devjuke:
  891. rp->flags |= Fchanger;
  892. return 0;
  893. }
  894. }
  895. SRclose(rp);
  896. return -1;
  897. }