scsireq.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  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. #include <u.h>
  10. #include <libc.h>
  11. /*
  12. * BUGS:
  13. * no luns
  14. * and incomplete in many other ways
  15. */
  16. #include <disk.h>
  17. #include "scsireq.h"
  18. enum {
  19. Debug = 0,
  20. };
  21. /*
  22. * exabyte tape drives, at least old ones like the 8200 and 8505,
  23. * are dumb: you have to read the exact block size on the tape,
  24. * they don't take 10-byte SCSI commands, and various other fine points.
  25. */
  26. extern int exabyte, force6bytecmds;
  27. static int debug = Debug;
  28. int32_t
  29. SRready(ScsiReq *rp)
  30. {
  31. uint8_t cmd[6];
  32. memset(cmd, 0, sizeof cmd);
  33. rp->cmd.p = cmd;
  34. rp->cmd.count = sizeof cmd;
  35. rp->data.p = cmd;
  36. rp->data.count = 0;
  37. rp->data.write = 1;
  38. return SRrequest(rp);
  39. }
  40. int32_t
  41. SRrewind(ScsiReq *rp)
  42. {
  43. uint8_t cmd[6];
  44. memset(cmd, 0, sizeof cmd);
  45. cmd[0] = ScmdRewind;
  46. rp->cmd.p = cmd;
  47. rp->cmd.count = sizeof cmd;
  48. rp->data.p = cmd;
  49. rp->data.count = 0;
  50. rp->data.write = 1;
  51. if(SRrequest(rp) >= 0){
  52. rp->offset = 0;
  53. return 0;
  54. }
  55. return -1;
  56. }
  57. int32_t
  58. SRreqsense(ScsiReq *rp)
  59. {
  60. uint8_t cmd[6];
  61. ScsiReq req;
  62. int32_t status;
  63. if(rp->status == Status_SD){
  64. rp->status = STok;
  65. return 0;
  66. }
  67. memset(cmd, 0, sizeof cmd);
  68. cmd[0] = ScmdRsense;
  69. cmd[4] = sizeof(req.sense);
  70. memset(&req, 0, sizeof(req));
  71. if(rp->flags&Fusb)
  72. req.flags |= Fusb;
  73. req.fd = rp->fd;
  74. req.umsc = rp->umsc;
  75. req.cmd.p = cmd;
  76. req.cmd.count = sizeof cmd;
  77. req.data.p = rp->sense;
  78. req.data.count = sizeof(rp->sense);
  79. req.data.write = 0;
  80. status = SRrequest(&req);
  81. rp->status = req.status;
  82. return status;
  83. }
  84. int32_t
  85. SRformat(ScsiReq *rp)
  86. {
  87. uint8_t cmd[6];
  88. memset(cmd, 0, sizeof cmd);
  89. cmd[0] = ScmdFormat;
  90. rp->cmd.p = cmd;
  91. rp->cmd.count = sizeof cmd;
  92. rp->data.p = cmd;
  93. rp->data.count = 6;
  94. rp->data.write = 0;
  95. return SRrequest(rp);
  96. }
  97. int32_t
  98. SRrblimits(ScsiReq *rp, uint8_t *list)
  99. {
  100. uint8_t cmd[6];
  101. memset(cmd, 0, sizeof cmd);
  102. cmd[0] = ScmdRblimits;
  103. rp->cmd.p = cmd;
  104. rp->cmd.count = sizeof cmd;
  105. rp->data.p = list;
  106. rp->data.count = 6;
  107. rp->data.write = 0;
  108. return SRrequest(rp);
  109. }
  110. static int
  111. dirdevrw(ScsiReq *rp, uint8_t *cmd, int32_t nbytes)
  112. {
  113. int32_t n;
  114. n = nbytes / rp->lbsize;
  115. if(rp->offset <= Max24off && n <= 256 && (rp->flags & Frw10) == 0){
  116. PUTBE24(cmd+1, rp->offset);
  117. cmd[4] = n;
  118. cmd[5] = 0;
  119. return 6;
  120. }
  121. cmd[0] |= ScmdExtread;
  122. cmd[1] = 0;
  123. PUTBELONG(cmd+2, rp->offset);
  124. cmd[6] = 0;
  125. cmd[7] = n>>8;
  126. cmd[8] = n;
  127. cmd[9] = 0;
  128. return 10;
  129. }
  130. static int
  131. seqdevrw(ScsiReq *rp, uint8_t *cmd, int32_t nbytes)
  132. {
  133. int32_t n;
  134. /* don't set Cmd1sili; we want the ILI bit instead of a fatal error */
  135. cmd[1] = rp->flags&Fbfixed? Cmd1fixed: 0;
  136. n = nbytes / rp->lbsize;
  137. PUTBE24(cmd+2, n);
  138. cmd[5] = 0;
  139. return 6;
  140. }
  141. int32_t
  142. SRread(ScsiReq *rp, void *buf, int32_t nbytes)
  143. {
  144. uint8_t cmd[10];
  145. int32_t n;
  146. if((nbytes % rp->lbsize) || nbytes > maxiosize){
  147. if(debug){
  148. if (nbytes % rp->lbsize)
  149. fprint(2, "scuzz: i/o size %ld %% %ld != 0\n",
  150. nbytes, rp->lbsize);
  151. else
  152. fprint(2, "scuzz: i/o size %ld > %ld\n",
  153. nbytes, maxiosize);
  154. }
  155. rp->status = Status_BADARG;
  156. return -1;
  157. }
  158. /* set up scsi read cmd */
  159. cmd[0] = ScmdRead;
  160. if(rp->flags & Fseqdev)
  161. rp->cmd.count = seqdevrw(rp, cmd, nbytes);
  162. else
  163. rp->cmd.count = dirdevrw(rp, cmd, nbytes);
  164. rp->cmd.p = cmd;
  165. rp->data.p = buf;
  166. rp->data.count = nbytes;
  167. rp->data.write = 0;
  168. /* issue it */
  169. n = SRrequest(rp);
  170. if(n != -1){ /* it worked? */
  171. rp->offset += n / rp->lbsize;
  172. return n;
  173. }
  174. /* request failed; maybe we just read a short record? */
  175. if (exabyte) {
  176. fprint(2, "read error\n");
  177. rp->status = STcheck;
  178. return n;
  179. }
  180. if(rp->status != Status_SD || !(rp->sense[0] & Sd0valid))
  181. return -1;
  182. /* compute # of bytes not read */
  183. n = GETBELONG(rp->sense+3) * rp->lbsize;
  184. if (debug)
  185. fprint(2,
  186. "SRread: request failed with sense data; sense byte count %ld\n",
  187. n);
  188. if(!(rp->flags & Fseqdev))
  189. return -1;
  190. /* device is a tape or something similar */
  191. if (rp->sense[2] == Sd2filemark || rp->sense[2] == 0x08 ||
  192. (rp->sense[2] & Sd2ili && n > 0))
  193. rp->data.count = nbytes - n;
  194. else
  195. return -1;
  196. n = rp->data.count;
  197. if (!rp->readblock++ || debug)
  198. fprint(2, "SRread: tape data count %ld%s\n", n,
  199. (rp->sense[2] & Sd2ili? " with ILI": ""));
  200. rp->status = STok;
  201. rp->offset += n / rp->lbsize;
  202. return n;
  203. }
  204. int32_t
  205. SRwrite(ScsiReq *rp, void *buf, int32_t nbytes)
  206. {
  207. uint8_t cmd[10];
  208. int32_t n;
  209. if((nbytes % rp->lbsize) || nbytes > maxiosize){
  210. if(debug){
  211. if (nbytes % rp->lbsize)
  212. fprint(2, "scuzz: i/o size %ld %% %ld != 0\n",
  213. nbytes, rp->lbsize);
  214. else
  215. fprint(2, "scuzz: i/o size %ld > %ld\n",
  216. nbytes, maxiosize);
  217. }
  218. rp->status = Status_BADARG;
  219. return -1;
  220. }
  221. /* set up scsi write cmd */
  222. cmd[0] = ScmdWrite;
  223. if(rp->flags & Fseqdev)
  224. rp->cmd.count = seqdevrw(rp, cmd, nbytes);
  225. else
  226. rp->cmd.count = dirdevrw(rp, cmd, nbytes);
  227. rp->cmd.p = cmd;
  228. rp->data.p = buf;
  229. rp->data.count = nbytes;
  230. rp->data.write = 1;
  231. /* issue it */
  232. if((n = SRrequest(rp)) == -1){
  233. if (exabyte) {
  234. fprint(2, "write error\n");
  235. rp->status = STcheck;
  236. return n;
  237. }
  238. if(rp->status != Status_SD || rp->sense[2] != Sd2eom)
  239. return -1;
  240. if(rp->sense[0] & Sd0valid){
  241. n -= GETBELONG(rp->sense+3) * rp->lbsize;
  242. rp->data.count = nbytes - n;
  243. }
  244. else
  245. rp->data.count = nbytes;
  246. n = rp->data.count;
  247. }
  248. rp->offset += n / rp->lbsize;
  249. return n;
  250. }
  251. int32_t
  252. SRseek(ScsiReq *rp, int32_t offset, int type)
  253. {
  254. uint8_t cmd[10];
  255. switch(type){
  256. case 0:
  257. break;
  258. case 1:
  259. offset += rp->offset;
  260. if(offset >= 0)
  261. break;
  262. /*FALLTHROUGH*/
  263. default:
  264. if(debug)
  265. fprint(2, "scuzz: seek failed\n");
  266. rp->status = Status_BADARG;
  267. return -1;
  268. }
  269. memset(cmd, 0, sizeof cmd);
  270. if(offset <= Max24off && (rp->flags & Frw10) == 0){
  271. cmd[0] = ScmdSeek;
  272. PUTBE24(cmd+1, offset & Max24off);
  273. rp->cmd.count = 6;
  274. }else{
  275. cmd[0] = ScmdExtseek;
  276. PUTBELONG(cmd+2, offset);
  277. rp->cmd.count = 10;
  278. }
  279. rp->cmd.p = cmd;
  280. rp->data.p = cmd;
  281. rp->data.count = 0;
  282. rp->data.write = 1;
  283. SRrequest(rp);
  284. if(rp->status == STok)
  285. return rp->offset = offset;
  286. return -1;
  287. }
  288. int32_t
  289. SRfilemark(ScsiReq *rp, uint32_t howmany)
  290. {
  291. uint8_t cmd[6];
  292. memset(cmd, 0, sizeof cmd);
  293. cmd[0] = ScmdFmark;
  294. PUTBE24(cmd+2, howmany);
  295. rp->cmd.p = cmd;
  296. rp->cmd.count = sizeof cmd;
  297. rp->data.p = cmd;
  298. rp->data.count = 0;
  299. rp->data.write = 1;
  300. return SRrequest(rp);
  301. }
  302. int32_t
  303. SRspace(ScsiReq *rp, uint8_t code, int32_t howmany)
  304. {
  305. uint8_t cmd[6];
  306. memset(cmd, 0, sizeof cmd);
  307. cmd[0] = ScmdSpace;
  308. cmd[1] = code;
  309. PUTBE24(cmd+2, howmany);
  310. rp->cmd.p = cmd;
  311. rp->cmd.count = sizeof cmd;
  312. rp->data.p = cmd;
  313. rp->data.count = 0;
  314. rp->data.write = 1;
  315. /*
  316. * what about rp->offset?
  317. */
  318. return SRrequest(rp);
  319. }
  320. int32_t
  321. SRinquiry(ScsiReq *rp)
  322. {
  323. uint8_t cmd[6];
  324. memset(cmd, 0, sizeof cmd);
  325. cmd[0] = ScmdInq;
  326. cmd[4] = sizeof rp->inquiry;
  327. rp->cmd.p = cmd;
  328. rp->cmd.count = sizeof cmd;
  329. memset(rp->inquiry, 0, sizeof rp->inquiry);
  330. rp->data.p = rp->inquiry;
  331. rp->data.count = sizeof rp->inquiry;
  332. rp->data.write = 0;
  333. if(SRrequest(rp) >= 0){
  334. rp->flags |= Finqok;
  335. return 0;
  336. }
  337. rp->flags &= ~Finqok;
  338. return -1;
  339. }
  340. int32_t
  341. SRmodeselect6(ScsiReq *rp, uint8_t *list, int32_t nbytes)
  342. {
  343. uint8_t cmd[6];
  344. memset(cmd, 0, sizeof cmd);
  345. cmd[0] = ScmdMselect6;
  346. if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
  347. cmd[1] = 0x10;
  348. cmd[4] = nbytes;
  349. rp->cmd.p = cmd;
  350. rp->cmd.count = sizeof cmd;
  351. rp->data.p = list;
  352. rp->data.count = nbytes;
  353. rp->data.write = 1;
  354. return SRrequest(rp);
  355. }
  356. int32_t
  357. SRmodeselect10(ScsiReq *rp, uint8_t *list, int32_t nbytes)
  358. {
  359. uint8_t cmd[10];
  360. memset(cmd, 0, sizeof cmd);
  361. if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
  362. cmd[1] = 0x10;
  363. cmd[0] = ScmdMselect10;
  364. cmd[7] = nbytes>>8;
  365. cmd[8] = nbytes;
  366. rp->cmd.p = cmd;
  367. rp->cmd.count = sizeof cmd;
  368. rp->data.p = list;
  369. rp->data.count = nbytes;
  370. rp->data.write = 1;
  371. return SRrequest(rp);
  372. }
  373. int32_t
  374. SRmodesense6(ScsiReq *rp, uint8_t page, uint8_t *list, int32_t nbytes)
  375. {
  376. uint8_t cmd[6];
  377. memset(cmd, 0, sizeof cmd);
  378. cmd[0] = ScmdMsense6;
  379. cmd[2] = page;
  380. cmd[4] = nbytes;
  381. rp->cmd.p = cmd;
  382. rp->cmd.count = sizeof cmd;
  383. rp->data.p = list;
  384. rp->data.count = nbytes;
  385. rp->data.write = 0;
  386. return SRrequest(rp);
  387. }
  388. int32_t
  389. SRmodesense10(ScsiReq *rp, uint8_t page, uint8_t *list, int32_t nbytes)
  390. {
  391. uint8_t cmd[10];
  392. memset(cmd, 0, sizeof cmd);
  393. cmd[0] = ScmdMsense10;
  394. cmd[2] = page;
  395. cmd[7] = nbytes>>8;
  396. cmd[8] = nbytes;
  397. rp->cmd.p = cmd;
  398. rp->cmd.count = sizeof cmd;
  399. rp->data.p = list;
  400. rp->data.count = nbytes;
  401. rp->data.write = 0;
  402. return SRrequest(rp);
  403. }
  404. int32_t
  405. SRstart(ScsiReq *rp, uint8_t code)
  406. {
  407. uint8_t cmd[6];
  408. memset(cmd, 0, sizeof cmd);
  409. cmd[0] = ScmdStart;
  410. cmd[4] = code;
  411. rp->cmd.p = cmd;
  412. rp->cmd.count = sizeof cmd;
  413. rp->data.p = cmd;
  414. rp->data.count = 0;
  415. rp->data.write = 1;
  416. return SRrequest(rp);
  417. }
  418. int32_t
  419. SRrcapacity(ScsiReq *rp, uint8_t *data)
  420. {
  421. uint8_t cmd[10];
  422. memset(cmd, 0, sizeof cmd);
  423. cmd[0] = ScmdRcapacity;
  424. rp->cmd.p = cmd;
  425. rp->cmd.count = sizeof cmd;
  426. rp->data.p = data;
  427. rp->data.count = 8;
  428. rp->data.write = 0;
  429. return SRrequest(rp);
  430. }
  431. static int32_t
  432. request(int fd, ScsiPtr *cmd, ScsiPtr *data, int *status)
  433. {
  434. int32_t n, r;
  435. char buf[16];
  436. /* this was an experiment but it seems to be a good idea */
  437. *status = STok;
  438. /* send SCSI command */
  439. if(write(fd, cmd->p, cmd->count) != cmd->count){
  440. fprint(2, "scsireq: write cmd: %r\n");
  441. *status = Status_SW;
  442. return -1;
  443. }
  444. /* read or write actual data */
  445. werrstr("");
  446. if(data->write)
  447. n = write(fd, data->p, data->count);
  448. else {
  449. n = read(fd, data->p, data->count);
  450. if (n < 0)
  451. memset(data->p, 0, data->count);
  452. else if (n < data->count)
  453. memset(data->p + n, 0, data->count - n);
  454. }
  455. if (n != data->count && n <= 0) {
  456. if (debug)
  457. fprint(2,
  458. "request: tried to %s %ld bytes of data for cmd 0x%x but got %r\n",
  459. (data->write? "write": "read"),
  460. data->count, cmd->p[0]);
  461. } else if (n != data->count && (data->write || debug))
  462. fprint(2, "request: %s %ld of %ld bytes of actual data\n",
  463. (data->write? "wrote": "read"), n, data->count);
  464. /* read status */
  465. buf[0] = '\0';
  466. r = read(fd, buf, sizeof buf-1);
  467. if((exabyte && r <= 0) || (!exabyte && r < 0)){
  468. fprint(2, "scsireq: read status: %r\n");
  469. *status = Status_SW;
  470. return -1;
  471. }
  472. if (r >= 0)
  473. buf[r] = '\0';
  474. *status = atoi(buf);
  475. if(n < 0 && (exabyte || *status != STcheck))
  476. fprint(2, "scsireq: status 0x%2.2X: data transfer: %r\n",
  477. *status);
  478. return n;
  479. }
  480. int32_t
  481. SRrequest(ScsiReq *rp)
  482. {
  483. int32_t n;
  484. int status;
  485. retry:
  486. if(rp->flags&Fusb)
  487. n = umsrequest(rp->umsc, &rp->cmd, &rp->data, &status);
  488. else
  489. n = request(rp->fd, &rp->cmd, &rp->data, &status);
  490. switch(rp->status = status){
  491. case STok:
  492. rp->data.count = n;
  493. break;
  494. case STcheck:
  495. if(rp->cmd.p[0] != ScmdRsense && SRreqsense(rp) != -1)
  496. rp->status = Status_SD;
  497. if (exabyte)
  498. fprint(2, "SRrequest: STcheck, returning -1\n");
  499. return -1;
  500. case STbusy:
  501. sleep(1000);
  502. goto retry;
  503. default:
  504. fprint(2, "status 0x%2.2X\n", status);
  505. return -1;
  506. }
  507. return n;
  508. }
  509. int
  510. SRclose(ScsiReq *rp)
  511. {
  512. if((rp->flags & Fopen) == 0){
  513. if(debug)
  514. fprint(2, "scuzz: closing closed file\n");
  515. rp->status = Status_BADARG;
  516. return -1;
  517. }
  518. close(rp->fd);
  519. rp->flags = 0;
  520. return 0;
  521. }
  522. uint
  523. mkascq(ScsiReq *r)
  524. {
  525. uint8_t *u;
  526. u = r->sense;
  527. return u[2]<<16 | u[12]<<8 | u[13];
  528. }
  529. static int
  530. dirdevopen(ScsiReq *rp)
  531. {
  532. uint32_t blocks;
  533. uint8_t data[8];
  534. if(SRstart(rp, 1) == -1)
  535. /*
  536. * it's okay for removable media to say
  537. * "check condition: medium not present".
  538. * 3a is "medium not present".
  539. */
  540. return rp->inquiry[1] & 0x80 && (mkascq(rp) >> 8) == 0x023a?
  541. 0: -1;
  542. memset(data, 0, sizeof data);
  543. if(SRrcapacity(rp, data) == -1)
  544. return -1;
  545. rp->lbsize = GETBELONG(data+4);
  546. blocks = GETBELONG(data);
  547. if(debug)
  548. fprint(2, "scuzz: dirdevopen: logical block size %lu, "
  549. "# blocks %lu\n", rp->lbsize, blocks);
  550. /* some newer dev's don't support 6-byte commands */
  551. if(blocks > Max24off && !force6bytecmds)
  552. rp->flags |= Frw10;
  553. return 0;
  554. }
  555. static int
  556. seqdevopen(ScsiReq *rp)
  557. {
  558. uint8_t mode[16], limits[6];
  559. if(SRrblimits(rp, limits) == -1)
  560. return -1;
  561. if(limits[1] == 0 && limits[2] == limits[4] && limits[3] == limits[5]){
  562. rp->flags |= Fbfixed;
  563. rp->lbsize = limits[4]<<8 | limits[5];
  564. if(debug)
  565. fprint(2, "scuzz: seqdevopen: logical block size %lu\n",
  566. rp->lbsize);
  567. return 0;
  568. }
  569. /*
  570. * On some older hardware the optional 10-byte
  571. * modeselect command isn't implemented.
  572. */
  573. if (force6bytecmds)
  574. rp->flags |= Fmode6;
  575. if(!(rp->flags & Fmode6)){
  576. /* try 10-byte command first */
  577. memset(mode, 0, sizeof mode);
  578. mode[3] = 0x10; /* device-specific param. */
  579. mode[7] = 8; /* block descriptor length */
  580. /*
  581. * exabytes can't handle this, and
  582. * modeselect(10) is optional.
  583. */
  584. if(SRmodeselect10(rp, mode, sizeof mode) != -1){
  585. rp->lbsize = 1;
  586. return 0; /* success */
  587. }
  588. /* can't do 10-byte commands, back off to 6-byte ones */
  589. rp->flags |= Fmode6;
  590. }
  591. /* 6-byte command */
  592. memset(mode, 0, sizeof mode);
  593. mode[2] = 0x10; /* device-specific param. */
  594. mode[3] = 8; /* block descriptor length */
  595. /*
  596. * bsd sez exabytes need this bit (NBE: no busy enable) in
  597. * vendor-specific page (0), but so far we haven't needed it.
  598. mode[12] |= 8;
  599. */
  600. if(SRmodeselect6(rp, mode, 4+8) == -1)
  601. return -1;
  602. rp->lbsize = 1;
  603. return 0;
  604. }
  605. static int
  606. wormdevopen(ScsiReq *rp)
  607. {
  608. int32_t status;
  609. uint8_t list[MaxDirData];
  610. if (SRstart(rp, 1) == -1 ||
  611. (status = SRmodesense10(rp, Allmodepages, list, sizeof list)) == -1)
  612. return -1;
  613. /* nbytes = list[0]<<8 | list[1]; */
  614. /* # of bytes of block descriptors of 8 bytes each; not even 1? */
  615. if((list[6]<<8 | list[7]) < 8)
  616. rp->lbsize = 2048;
  617. else
  618. /* last 3 bytes of block 0 descriptor */
  619. rp->lbsize = GETBE24(list+13);
  620. if(debug)
  621. fprint(2, "scuzz: wormdevopen: logical block size %lu\n",
  622. rp->lbsize);
  623. return status;
  624. }
  625. int
  626. SRopenraw(ScsiReq *rp, char *unit)
  627. {
  628. char name[128];
  629. if(rp->flags & Fopen){
  630. if(debug)
  631. fprint(2, "scuzz: opening open file\n");
  632. rp->status = Status_BADARG;
  633. return -1;
  634. }
  635. memset(rp, 0, sizeof *rp);
  636. rp->unit = unit;
  637. sprint(name, "%s/raw", unit);
  638. if((rp->fd = open(name, ORDWR)) == -1){
  639. rp->status = STtimeout;
  640. return -1;
  641. }
  642. rp->flags = Fopen;
  643. return 0;
  644. }
  645. int
  646. SRopen(ScsiReq *rp, char *unit)
  647. {
  648. if(SRopenraw(rp, unit) == -1)
  649. return -1;
  650. SRready(rp);
  651. if(SRinquiry(rp) >= 0){
  652. switch(rp->inquiry[0]){
  653. default:
  654. fprint(2, "unknown device type 0x%.2x\n", rp->inquiry[0]);
  655. rp->status = Status_SW;
  656. break;
  657. case 0x00: /* Direct access (disk) */
  658. case 0x05: /* CD-ROM */
  659. case 0x07: /* rewriteable MO */
  660. if(dirdevopen(rp) == -1)
  661. break;
  662. return 0;
  663. case 0x01: /* Sequential eg: tape */
  664. rp->flags |= Fseqdev;
  665. if(seqdevopen(rp) == -1)
  666. break;
  667. return 0;
  668. case 0x02: /* Printer */
  669. rp->flags |= Fprintdev;
  670. return 0;
  671. case 0x04: /* Worm */
  672. rp->flags |= Fwormdev;
  673. if(wormdevopen(rp) == -1)
  674. break;
  675. return 0;
  676. case 0x08: /* medium-changer */
  677. rp->flags |= Fchanger;
  678. return 0;
  679. }
  680. }
  681. SRclose(rp);
  682. return -1;
  683. }