scsi-openserver.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:18k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-openserver.c 1.16 00/01/26 Copyright 1998 J. Schilling, Santa Cruz Operation */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-openserver.c 1.16 00/01/26 Copyright 1998 J. Schilling, Santa Cruz Operation";
  5. #endif
  6. /*
  7.  * Interface for the SCO SCSI implementation.
  8.  *
  9.  * Warning: you may change this source, but if you do that
  10.  * you need to change the _scg_version and _scg_auth* string below.
  11.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  12.  * Choose your name instead of "schily" and make clear that the version
  13.  * string is related to a modified source.
  14.  *
  15.  * Copyright (c) 1998 J. Schilling, Santa Cruz Operation
  16.  */
  17. /*
  18.  * This program is free software; you can redistribute it and/or modify
  19.  * it under the terms of the GNU General Public License as published by
  20.  * the Free Software Foundation; either version 2, or (at your option)
  21.  * any later version.
  22.  *
  23.  * This program is distributed in the hope that it will be useful,
  24.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26.  * GNU General Public License for more details.
  27.  *
  28.  * You should have received a copy of the GNU General Public License
  29.  * along with this program; see the file COPYING.  If not, write to
  30.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  31.  */
  32. #undef sense
  33. #include <sys/scsicmd.h>
  34. /*
  35.  * Warning: you may change this source, but if you do that
  36.  * you need to change the _scg_version and _scg_auth* string below.
  37.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  38.  * Choose your name instead of "schily" and make clear that the version
  39.  * string is related to a modified source.
  40.  */
  41. LOCAL char _scg_trans_version[] = "scsi-openserver.c-1.16"; /* The version for this transport*/
  42. #define MAX_SCG 16 /* Max # of cdrom devices */
  43. #define MAX_TGT 16 /* Not really needed      */
  44. #define MAX_LUN 8 /* Not really needed      */
  45. #define MAX_DMA (32*1024) /* Maybe even more ???    */
  46. #define MAXPATH        256 /* max length of devicepath  */
  47. #define MAXLINE 80 /* max length of input line  */
  48. #define MAXSCSI 99 /* max number of mscsi lines */
  49. #define MAXDRVN 10 /* max length of drivername  */
  50. #define DEV_DIR "/tmp"
  51. #define DEV_NAME "scg.s%1dt%1dl%1d"
  52. /* We will only deal with disks, cdroms and tapes ! */
  53. /* Sflp devices (floptical) 21Mb scsi floppy devices */
  54. /* will be ignored. Hmm, I can't remember that I ever  */
  55. /* have seen one ;^) */
  56. #define DEV_ROOT "/dev/rdsk/0s0"
  57. #define DEV_SDSK "/dev/rdsk/%ds0"
  58. #define DEV_SROM "/dev/rcd%d"
  59. #define DEV_STP "/dev/xStp%d"
  60. #define SCAN_DEV "%s%s%d%d%d%d"
  61. #define SCSI_CFG "/etc/sconf -r" /* no. of configured devices  */
  62. #define SCSI_DEV "/etc/sconf -g %d" /* read line 'n' of mscsi tbl */
  63. #define DRV_ATAPI "wd"
  64. typedef struct scg2sdi {
  65. int valid;
  66. int open;
  67. int atapi;
  68. int fd;
  69. int lmscsi;
  70. } scg2sdi_t;
  71. LOCAL scg2sdi_t sdidevs [MAX_SCG][MAX_TGT][MAX_LUN];
  72. typedef struct amscsi {
  73. char typ[MAXDRVN];
  74. char drv[MAXDRVN];
  75. int hba;
  76. int bus;
  77. int scg;
  78. int tgt;
  79. int lun;
  80. char dev[MAXPATH];
  81. } amscsi_t;
  82. struct scg_local {
  83. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  84. };
  85. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  86. LOCAL int sort_mscsi __PR((const void *l1, const void *l2));
  87. LOCAL int openserver_init __PR((SCSI *scgp));
  88. LOCAL void cp_scg2sco __PR((struct scsicmd2 *sco, struct scg_cmd *scg));
  89. LOCAL void cp_sco2scg __PR((struct scsicmd2 *sco, struct scg_cmd *scg));
  90. /* -------------------------------------------------------------------------
  91. ** SCO OpenServer does not have a generic scsi device driver, which can
  92. ** be used to access any configured scsi device. 
  93. **
  94. ** But we can use the "Srom" scsi peripherial driver (for CD-ROM devices) 
  95. ** etc. to send SCSIUSERCMD2's to any target device controlled by the 
  96. ** corresponding target driver.
  97. **
  98. ** This pass-through implementation for libscg currently allows to 
  99. ** handle the following devices classes:
  100. **
  101. ** 1. DISK handled by Sdsk
  102. ** 2. CD-ROM handled by Srom
  103. ** 3. TAPES handled by Stp
  104. **
  105. ** NOTE: The libscg OpenServer passthrough routines have changed with 
  106. **       cdrecord-1.8 to enable the -scanbus option. Therefore the
  107. **  addressing scheme is now the same as used on many other platforms
  108. **  like Solaris, Linux etc.
  109. **
  110. **   ===============================================================
  111. **   RUN 'cdrecord -scanbus' TO SEE THE DEVICE ADDRESSES YOU CAN USE
  112. **   ===============================================================
  113. **
  114. */
  115. /*
  116.  * Return version information for the low level SCSI transport code.
  117.  * This has been introduced to make it easier to trace down problems
  118.  * in applications.
  119.  */
  120. EXPORT char *
  121. scg__version(scgp, what)
  122. SCSI *scgp;
  123. int what;
  124. {
  125. if (scgp != (SCSI *)0) {
  126. switch (what) {
  127. case SCG_VERSION:
  128. return (_scg_trans_version);
  129. /*
  130.  * If you changed this source, you are not allowed to
  131.  * return "schily" for the SCG_AUTHOR request.
  132.  */
  133. case SCG_AUTHOR:
  134. return (_scg_auth_schily);
  135. case SCG_SCCS_ID:
  136. return (__sccsid);
  137. }
  138. }
  139. return ((char *)0);
  140. }
  141. /* ---------------------------------------------------------------
  142. ** This routine sorts the amscsi_t lines on the following columns
  143. ** in ascending order:
  144. **
  145. ** 1. drv  - driver name
  146. ** 2. bus  - scsibus per controller
  147. ** 3. tgt  - target id of device
  148. ** 4. lun  - lun of the device
  149. **
  150. */
  151. LOCAL int
  152. sort_mscsi(l1, l2)
  153. const void *l1;
  154. const void *l2;
  155. {
  156. amscsi_t *t1 = (amscsi_t *) l1;
  157. amscsi_t *t2 = (amscsi_t *) l2;
  158. if ( strcmp(t1->drv, t2->drv) == 0 ) {
  159. if (t1->bus < t2->bus) {
  160. return (-1);
  161. } else if (t1->bus > t2->bus) {
  162. return (1);
  163. } else if (t1->tgt < t2->tgt) {
  164. return (-1);
  165. } else if (t1->tgt > t2->tgt) {
  166. return (1);
  167. } else if (t1->lun < t2->lun) {
  168. return (-1);
  169. } else if (t1->lun > t2->lun) {
  170. return (1);
  171. } else {
  172. return (0);
  173. }
  174. } else {
  175. return (strcmp(t1->drv, t2->drv));
  176. }
  177. }
  178. /* ---------------------------------------------------------------
  179. ** This routine is introduced to find all scsi devices which are
  180. ** currently configured into the kernel. This is done by reading
  181. ** the dynamic kernel mscsi tables and parse the resulting lines.
  182. ** As the output of 'sconf' is not directly usable the information
  183. ** found is to be sorted and re-arranged to be used with the libscg
  184. ** routines.
  185. **
  186. ** NOTE: One problem is currently still not solved ! If you don't
  187. **       have a media in your CD-ROM/CD-Writer we are not able to 
  188. **       do an open() and therefore will set the drive to be not 
  189. **       available (valid=0).
  190. **
  191. **       This will for example cause cdrecord to not list the drive 
  192. **  in the -scanbus output.
  193. **
  194. */
  195. LOCAL int 
  196. openserver_init(scgp)
  197. SCSI *scgp;
  198. {
  199. FILE *cmd;
  200. int nscg  = -1, lhba  = -1, lbus = -1;
  201. int nSrom = -1, nSdsk = -1, nStp = -1;
  202. int atapi, fd, nopen = 0;
  203. int pos = 0, len = 0, nlm = 0;
  204. int s = 0, t = 0, l = 0;
  205. int mscsi;
  206. char sconf[MAXLINE];
  207. char lines[MAXLINE];
  208. char drvid[MAXDRVN];
  209. amscsi_t cmtbl[MAXSCSI];
  210. char dname[MAXPATH];
  211. char **evsave;
  212. extern char **environ;
  213. for (s = 0; s < MAX_SCG; s++) {
  214. for (t = 0; t < MAX_TGT; t++) {
  215. for (l = 0; l < MAX_LUN ; l++) {
  216.   sdidevs[s][t][l].valid  =  0;
  217.   sdidevs[s][t][l].open   = -1;
  218.   sdidevs[s][t][l].atapi  = -1;
  219.   sdidevs[s][t][l].fd     = -1;
  220.   sdidevs[s][t][l].lmscsi = -1;
  221. }
  222. }
  223. }
  224. /* read sconf -r and get number of kernel mscsi lines ! */
  225. evsave = environ;
  226. environ = 0;
  227. if ((cmd = popen(SCSI_CFG,"r")) == NULL) {
  228. if (scgp->errstr)
  229. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  230. "Error popen() for "%s"",
  231. SCSI_CFG);
  232. environ = evsave;
  233. return (-1);
  234. }
  235. environ = evsave;
  236. if (fgets(lines, MAXLINE, cmd) == NULL) {
  237. errno = EIO;
  238. if (scgp->errstr)
  239. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  240. "Error reading popen() for "%s"",
  241. SCSI_CFG);
  242. return (-1);
  243. } else
  244. nlm = atoi(lines);
  245. if (scgp->debug) {
  246. printf("-------------------- n");
  247. printf("mscsi lines = %dn", nlm);
  248. printf("-------------------- n");
  249. }
  250. if (pclose(cmd) == -1) {
  251. if (scgp->errstr)
  252. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  253. "Error pclose() for "%s"",
  254. SCSI_CFG);
  255. return (-1);
  256. }
  257. for (l = 0; l < nlm; l++) {
  258. /* initialize cmtbl entry */
  259. cmtbl[l].hba = -1;
  260. cmtbl[l].bus = -1;
  261. cmtbl[l].tgt = -1;
  262. cmtbl[l].lun = -1;
  263. cmtbl[l].scg = -1;
  264. memset( cmtbl[l].typ, '', MAXDRVN);
  265. memset( cmtbl[l].drv, '', MAXDRVN);
  266. memset( cmtbl[l].dev, '', MAXDRVN);
  267. /* read sconf -g 'n' and get line of kernel mscsi table! */
  268. /* the order the lines will be received in will determine */
  269. /* the device name we can use to open the device         */
  270. sprintf(sconf, SCSI_DEV, l + 1); /* enumeration starts with 1 */
  271. evsave = environ;
  272. environ = 0;
  273. if ((cmd = popen(sconf,"r")) == NULL) {
  274. if (scgp->errstr)
  275. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  276. "Error popen() for "%s"",
  277. sconf);
  278. environ = evsave;
  279. return (-1);
  280. }
  281. environ = evsave;
  282. if (fgets(lines, MAXLINE, cmd) == NULL) 
  283. break;
  284. if (pclose(cmd) == -1) {
  285. if (scgp->errstr)
  286. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  287. "Error pclose() for "%s"",
  288. sconf);
  289. return (-1);
  290. }
  291. sscanf(lines, SCAN_DEV,  cmtbl[l].typ, 
  292.  cmtbl[l].drv,
  293. &cmtbl[l].hba, 
  294. &cmtbl[l].bus, 
  295. &cmtbl[l].tgt, 
  296. &cmtbl[l].lun);
  297. if ( strstr(cmtbl[l].typ, "Sdsk") != NULL ){
  298. sprintf(cmtbl[l].dev, DEV_SDSK, ++nSdsk);
  299. }
  300. if ( strstr(cmtbl[l].typ, "Srom") != NULL ){
  301. sprintf(cmtbl[l].dev, DEV_SROM, ++nSrom);
  302. }
  303. if ( strstr(cmtbl[l].typ, "Stp") != NULL ){
  304. sprintf(cmtbl[l].dev, DEV_STP, ++nStp);
  305. }
  306. if (scgp->debug) {
  307. printf("%-4s = %5s(%d,%d,%d,%d) -> %sn", 
  308. cmtbl[l].typ, 
  309. cmtbl[l].drv, 
  310. cmtbl[l].hba, 
  311. cmtbl[l].bus, 
  312. cmtbl[l].tgt, 
  313. cmtbl[l].lun,
  314. cmtbl[l].dev);
  315. }
  316. }
  317. if (scgp->debug) {
  318. printf("-------------------- n");
  319. printf("%2d DISK  n", nSdsk + 1);
  320. printf("%2d CD-ROMn", nSrom + 1);
  321. printf("%2d TAPE  n", nStp  + 1);
  322. printf("-------------------- n");
  323. }
  324. /* ok, now let's sort this array of scsi devices */
  325. qsort((void *) cmtbl, nlm, sizeof(amscsi_t), sort_mscsi);
  326. if (scgp->debug) {
  327. for (l = 0; l < nlm; l++)
  328. printf("%-4s = %5s(%d,%d,%d,%d) -> %sn", 
  329. cmtbl[l].typ, 
  330. cmtbl[l].drv, 
  331. cmtbl[l].hba, 
  332. cmtbl[l].bus, 
  333. cmtbl[l].tgt, 
  334. cmtbl[l].lun,
  335. cmtbl[l].dev);
  336. printf("-------------------- n");
  337. }
  338. /* find root disk controller to make it scg 0      */
  339. for (l = 0; l < nlm; l++)
  340. if (strcmp(cmtbl[l].dev, DEV_ROOT) == 0)
  341. t = l;
  342. if (scgp->debug) {
  343. printf("root = %5s(%d,%d,%d,%d) -> %sn", 
  344. cmtbl[t].drv, 
  345. cmtbl[t].hba, 
  346. cmtbl[t].bus, 
  347. cmtbl[t].tgt, 
  348. cmtbl[t].lun,
  349. cmtbl[t].dev);
  350. printf("-------------------- n");
  351. }
  352. /* calculate scg from drv, hba and bus  */
  353. strcpy(drvid, "");
  354. for (l = 0, s = t; l < nlm; l++, s = (t + l) % nlm) {
  355. if (strcmp(drvid, cmtbl[s].drv) != 0) {
  356. strcpy(drvid, cmtbl[s].drv);
  357. lhba = cmtbl[s].hba;
  358. lbus = cmtbl[s].bus;
  359. cmtbl[s].scg = ++nscg;
  360. } else if (cmtbl[s].hba != lhba) {
  361. lhba = cmtbl[s].hba;
  362. lbus = cmtbl[s].bus;
  363. cmtbl[s].scg = ++nscg;
  364. } else if (cmtbl[s].bus != lbus) {
  365. lbus = cmtbl[s].bus;
  366. cmtbl[s].scg = ++nscg;
  367. } else {
  368. cmtbl[s].scg = nscg;
  369. }
  370. sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].valid  = 1;
  371. sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].open   = 0;
  372. if (strcmp(cmtbl[s].drv, DRV_ATAPI) == 0) 
  373. sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].atapi = 1;
  374. sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].lmscsi = s;
  375. }
  376. /* open all device nodes */
  377. for (s = 0; s < MAX_SCG; s++) {
  378. for (t = 0; t < MAX_TGT; t++) {
  379. for (l = 0; l < MAX_LUN ; l++) {
  380.   if ( sdidevs[s][t][l].valid == 0) 
  381.    continue;
  382.   /* Open pass-through device node */
  383. mscsi = sdidevs[s][t][l].lmscsi;
  384. strcpy(dname, cmtbl[mscsi].dev);
  385. /* ------------------------------------------------------------------
  386. ** NOTE: If we can't open the device, we will set the device invalid!
  387. ** ------------------------------------------------------------------
  388. */
  389. if ((fd = open(dname, O_RDONLY | O_NONBLOCK)) < 0) {
  390. sdidevs[s][t][l].valid = 0;
  391. continue;
  392. }
  393. if (scgp->debug) {
  394. printf("%d,%d,%d => %5s(%d,%d,%d,%d) -> %d : %s n", 
  395. s, t, l,
  396. cmtbl[mscsi].drv, 
  397. cmtbl[mscsi].hba, 
  398. cmtbl[mscsi].bus, 
  399. cmtbl[mscsi].tgt, 
  400. cmtbl[mscsi].lun,
  401. cmtbl[mscsi].scg,
  402. cmtbl[mscsi].dev);
  403. }
  404. sdidevs[s][t][l].fd   = fd;
  405. sdidevs[s][t][l].open = 1;
  406. nopen++;
  407. scglocal(scgp)->scgfiles[s][t][l] = (short) fd;
  408. }
  409. }
  410. }
  411. if (scgp->debug) {
  412. printf("-------------------- n");
  413. printf("nopen = %d devices   n", nopen);
  414. printf("-------------------- n");
  415. }
  416. return (nopen);
  417. }
  418. EXPORT int
  419. scsi_open(scgp, device, busno, tgt, tlun)
  420. SCSI *scgp;
  421. char *device;
  422. int busno;
  423. int tgt;
  424. int tlun;
  425. {
  426. int f, b, t, l;
  427. int nopen = 0;
  428. char devname[64];
  429. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  430. errno = EINVAL;
  431. if (scgp->errstr)
  432. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  433. "Illegal value for busno, target or lun '%d,%d,%d'",
  434. busno, tgt, tlun);
  435. return (-1);
  436. }
  437. if (scgp->local == NULL) {
  438. scgp->local = malloc(sizeof(struct scg_local));
  439. if (scgp->local == NULL)
  440. return (0);
  441. for (b = 0; b < MAX_SCG; b++) {
  442. for (t = 0; t < MAX_TGT; t++) {
  443. for (l = 0; l < MAX_LUN ; l++)
  444. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  445. }
  446. }
  447. }
  448. if (*device != '') {          /* we don't allow old dev usage */
  449. errno = EINVAL;
  450. if (scgp->errstr)
  451. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  452. "Open by 'devname' no longer supported on this OS");
  453. return (-1);
  454. return ( openserver_init(scgp) );
  455. }
  456. EXPORT int
  457. scsi_close(scgp)
  458. SCSI *scgp;
  459. {
  460. register int f;
  461. register int b;
  462. register int t;
  463. register int l;
  464. if (scgp->local == NULL)
  465. return (-1);
  466. for (b=0; b < MAX_SCG; b++) {
  467. for (t=0; t < MAX_TGT; t++) {
  468. for (l=0; l < MAX_LUN ; l++)
  469. f = scglocal(scgp)->scgfiles[b][t][l];
  470. if (f >= 0)
  471. close(f);
  472. sdidevs[b][t][l].fd    = -1;
  473. sdidevs[b][t][l].open  =  0;
  474. sdidevs[b][t][l].valid =  0;
  475. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  476. }
  477. }
  478. return (0);
  479. }
  480. LOCAL long
  481. scsi_maxdma(scgp)
  482. SCSI *scgp;
  483. {
  484. return (MAX_DMA);
  485. }
  486. EXPORT void *
  487. scsi_getbuf(scgp, amt)
  488. SCSI *scgp;
  489. long amt;
  490. {
  491. if (amt <= 0 || amt > scsi_maxdma(scgp))
  492. return ((void *)0);
  493. if (scgp->debug)
  494. printf("scsi_getbuf: %ld bytesn", amt);
  495. scgp->bufbase = valloc((size_t)(amt));
  496. return (scgp->bufbase);
  497. }
  498. EXPORT void
  499. scsi_freebuf(scgp)
  500. SCSI *scgp;
  501. {
  502. if (scgp->bufbase)
  503. free(scgp->bufbase);
  504. scgp->bufbase = NULL;
  505. }
  506. EXPORT
  507. BOOL scsi_havebus(scgp, busno)
  508. SCSI *scgp;
  509. int busno;
  510. {
  511. register int t;
  512. register int l;
  513. if (busno < 0 || busno >= MAX_SCG)
  514. return (FALSE);
  515. if (scgp->local == NULL)
  516. return (FALSE);
  517. for (t=0; t < MAX_TGT; t++) {
  518. for (l=0; l < MAX_LUN ; l++)
  519. if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
  520. return (TRUE);
  521. }
  522. return (FALSE);
  523. }
  524. EXPORT
  525. int scsi_fileno(scgp, busno, tgt, tlun)
  526. SCSI *scgp;
  527. int busno;
  528. int tgt;
  529. int tlun;
  530. {
  531. if (busno < 0 || busno >= MAX_SCG ||
  532.     tgt   < 0 || tgt   >= MAX_TGT ||
  533.     tlun  < 0 || tlun  >= MAX_LUN)
  534. return (-1);
  535. if (scgp->local == NULL)
  536. return (-1);
  537. return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
  538. }
  539. EXPORT int
  540. scsi_initiator_id(scgp)
  541. SCSI *scgp;
  542. {
  543. return (-1);
  544. /* We don't know the initiator ID yet, but we can if we parse the 
  545. ** output of the command 'cat /dev/string/cfg | grep "%adapter"'  
  546. **
  547. ** Sample line:                                                   
  548. **
  549.   **   %adapter 0xE800-0xE8FF 11 - type=alad ha=0 bus=0 id=7 fts=sto  
  550. **
  551. ** This tells us that the alad controller 0 has an id of 7 !
  552. ** The parsing should be done in openserver_init().
  553. **
  554. */
  555. }
  556. EXPORT
  557. int scsi_isatapi(scgp)
  558. SCSI *scgp;
  559. {
  560. return (sdidevs[scgp->scsibus][scgp->target][scgp->lun].atapi);
  561. }
  562. EXPORT
  563. int scsireset(scgp)
  564. SCSI *scgp;
  565. {
  566. return(-1); /* no scsi reset available */
  567. }
  568. LOCAL void
  569. cp_scg2sco(sco, scg)
  570. struct scsicmd2 *sco;
  571. struct scg_cmd *scg;
  572. {
  573. sco->cmd.data_ptr = (char *) scg->addr;
  574. sco->cmd.data_len = scg->size;
  575. sco->cmd.cdb_len  = scg->cdb_len;
  576. sco->sense_len    = scg->sense_len;
  577. sco->sense_ptr    = scg->u_sense.cmd_sense;
  578. if (!(scg->flags & SCG_RECV_DATA) && (scg->size > 0))
  579. sco->cmd.is_write = 1;
  580. if (scg->cdb_len == SC_G0_CDBLEN )
  581. memcpy(sco->cmd.cdb, &scg->cdb.g0_cdb, scg->cdb_len);
  582. if (scg->cdb_len == SC_G1_CDBLEN )
  583. memcpy(sco->cmd.cdb, &scg->cdb.g1_cdb, scg->cdb_len);
  584. if (scg->cdb_len == SC_G5_CDBLEN )
  585. memcpy(sco->cmd.cdb, &scg->cdb.g5_cdb, scg->cdb_len);
  586. }
  587. LOCAL void
  588. cp_sco2scg(sco, scg)
  589. struct scsicmd2 *sco;
  590. struct scg_cmd *scg;
  591. {
  592. scg->size      = sco->cmd.data_len;
  593. memset(&scg->scb, 0, sizeof(scg->scb));
  594. if (sco->sense_len > SCG_MAX_SENSE)
  595. scg->sense_count = SCG_MAX_SENSE;
  596. else
  597. scg->sense_count = sco->sense_len;
  598. scg->resid = 0;
  599. scg->u_scb.cmd_scb[0] = sco->cmd.target_sts;
  600. }
  601. LOCAL int
  602. scsi_send(scgp, fd, sp)
  603. SCSI *scgp;
  604. int fd;
  605. struct scg_cmd *sp;
  606. {
  607. struct scsicmd2 scsi_cmd;
  608. int i;
  609. u_char sense_buf[SCG_MAX_SENSE];
  610. if ( fd < 0 ) {
  611. sp->error = SCG_FATAL;
  612. return (0);
  613. }
  614. memset(&scsi_cmd, 0, sizeof(scsi_cmd));
  615. memset(sense_buf,  0, sizeof(sense_buf));
  616. scsi_cmd.sense_ptr = sense_buf;
  617. scsi_cmd.sense_len = sizeof(sense_buf);
  618. cp_scg2sco(&scsi_cmd, sp);
  619. errno = 0;
  620. for (;;) {
  621. int ioctlStatus;
  622. if ((ioctlStatus = ioctl(fd, SCSIUSERCMD2, &scsi_cmd)) < 0) {
  623. if (errno == EINTR)
  624. continue;
  625. cp_sco2scg(&scsi_cmd, sp);
  626. sp->ux_errno = errno;
  627. if (errno == 0)
  628. sp->ux_errno = EIO;
  629. sp->error    = SCG_RETRYABLE;
  630. return (0);
  631. }
  632. break;
  633. }
  634. cp_sco2scg(&scsi_cmd, sp);
  635. sp->ux_errno = errno;
  636. if (scsi_cmd.cmd.target_sts & 0x02) {
  637. if (errno == 0)
  638. sp->ux_errno = EIO;
  639. sp->error    = SCG_RETRYABLE;
  640. } else {
  641. sp->error    = SCG_NO_ERROR;
  642. }
  643. return 0;
  644. }
  645. #define sense u_sense.Sense