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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsitransp.c 1.48 99/11/12 Copyright 1988,1995 J. Schilling */
  2. #ifndef lint
  3. static char sccsid[] =
  4. "@(#)scsitransp.c 1.48 99/11/12 Copyright 1988,1995 J. Schilling";
  5. #endif
  6. /*
  7.  * SCSI user level command transport routines for
  8.  * the SCSI general driver 'scg'.
  9.  *
  10.  * Warning: you may change this source, but if you do that
  11.  * you need to change the _scg_version and _scg_auth* string below.
  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) 1988,1995 J. Schilling
  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. #include <mconfig.h>
  33. #ifdef HAVE_SYS_PARAM_H
  34. #include <sys/param.h> /* XXX nonportable to use u_char */
  35. #endif
  36. #include <stdio.h>
  37. #include <standard.h>
  38. #include <stdxlib.h>
  39. #include <unixstd.h>
  40. #include <errno.h>
  41. #include <timedefs.h>
  42. #include <sys/ioctl.h>
  43. #include <fctldefs.h>
  44. #include <scg/scgio.h>
  45. #include <scg/scsireg.h>
  46. #include <scg/scsitransp.h>
  47. #ifdef sun
  48. # define HAVE_SCG /* Currently only on SunOS/Solaris */
  49. #endif
  50. /*
  51.  * Warning: you may change this source, but if you do that
  52.  * you need to change the _scg_version and _scg_auth* string below.
  53.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  54.  * Choose your name instead of "schily" and make clear that the version
  55.  * string is related to a modified source.
  56.  */
  57. LOCAL char _scg_version[] = "0.1"; /* The global libscg version */
  58. LOCAL char _scg_auth_schily[] = "schily"; /* The author for this module */
  59. #ifdef HAVE_SCG
  60. LOCAL char _scg_trans_version[] = "scg-1.48"; /* The version for /dev/scg */
  61. #endif
  62. #define DEFTIMEOUT 20 /* Default timeout for SCSI command transport */
  63. /*
  64.  * Need to move this into an scg driver ioctl.
  65.  */
  66. /*#define MAX_DMA_SUN4M (1024*1024)*/
  67. #define MAX_DMA_SUN4M (124*1024) /* Currently max working size */
  68. /*#define MAX_DMA_SUN4C (126*1024)*/
  69. #define MAX_DMA_SUN4C (124*1024) /* Currently max working size */
  70. #define MAX_DMA_SUN3 (63*1024)
  71. #define MAX_DMA_SUN386 (56*1024)
  72. #define MAX_DMA_OTHER (32*1024)
  73. #define ARCH_MASK 0xF0
  74. #define ARCH_SUN2 0x00
  75. #define ARCH_SUN3 0x10
  76. #define ARCH_SUN4 0x20
  77. #define ARCH_SUN386 0x30
  78. #define ARCH_SUN3X 0x40
  79. #define ARCH_SUN4C 0x50
  80. #define ARCH_SUN4E 0x60
  81. #define ARCH_SUN4M 0x70
  82. #define ARCH_SUNX 0x80
  83. EXPORT char *scg_version __PR((SCSI *scgp, int what));
  84. EXPORT char *scg__version __PR((SCSI *scgp, int what));
  85. EXPORT int scsi_open __PR((SCSI *scgp, char *device, int busno, int tgt, int tlun));
  86. EXPORT int scsi_close __PR((SCSI *scgp));
  87. LOCAL long scsi_maxdma __PR((SCSI *scgp));
  88. EXPORT BOOL scsi_havebus __PR((SCSI *scgp, int));
  89. EXPORT int scsi_fileno __PR((SCSI *scgp, int, int, int));
  90. EXPORT int scsi_initiator_id __PR((SCSI *scgp));
  91. EXPORT int scsi_isatapi __PR((SCSI *scgp));
  92. EXPORT int scsireset __PR((SCSI *scgp));
  93. EXPORT void *scsi_getbuf __PR((SCSI *scgp, long));
  94. EXPORT void scsi_freebuf __PR((SCSI *scgp));
  95. EXPORT long scsi_bufsize __PR((SCSI *scgp, long));
  96. EXPORT void scsi_setnonstderrs __PR((SCSI *scgp, const char **));
  97. EXPORT BOOL scsi_yes __PR((char *));
  98. #ifdef nonono
  99. LOCAL void scsi_sighandler __PR((int));
  100. #endif
  101. EXPORT int scsicmd __PR((SCSI *scgp));
  102. EXPORT int scsigetresid __PR((SCSI *scgp));
  103. LOCAL void scsitimes __PR((SCSI *scgp));
  104. LOCAL BOOL scsierr __PR((SCSI *scgp));
  105. LOCAL int scsicheckerr __PR((SCSI *scgp));
  106. EXPORT void scsiprinterr __PR((SCSI *scgp));
  107. EXPORT void scsiprintcdb __PR((SCSI *scgp));
  108. EXPORT void scsiprintwdata __PR((SCSI *scgp));
  109. EXPORT void scsiprintrdata __PR((SCSI *scgp));
  110. EXPORT void scsiprintresult __PR((SCSI *scgp));
  111. EXPORT void scsiprintstatus __PR((SCSI *scgp));
  112. EXPORT void scsiprbytes __PR((char *, unsigned char *, int));
  113. EXPORT void scsiprsense __PR((unsigned char *, int));
  114. EXPORT int scsi_sense_key __PR((SCSI *scgp));
  115. EXPORT int scsi_sense_code __PR((SCSI *scgp));
  116. EXPORT int scsi_sense_qual __PR((SCSI *scgp));
  117. EXPORT void scsiprintdev __PR((struct scsi_inquiry *));
  118. #ifdef HAVE_SCG
  119. # include <libport.h> /* Needed for gethostid() */
  120. #ifdef sun
  121. #ifdef HAVE_SUN_DKIO_H
  122. # include <sun/dkio.h>
  123. # define dk_cinfo dk_conf
  124. # define dki_slave dkc_slave
  125. # define DKIO_GETCINFO DKIOCGCONF
  126. #endif
  127. #ifdef HAVE_SYS_DKIO_H
  128. # include <sys/dkio.h>
  129. # define DKIO_GETCINFO DKIOCINFO
  130. #endif
  131. #define TARGET(slave) ((slave >> 3) & 07)
  132. #endif /* sun */
  133. /*
  134.  * We are using a "real" /dev/scg?
  135.  */
  136. # define scsi_send(scgp, f, cmdp) ioctl((f), SCGIO_CMD, (cmdp))
  137. # define MAX_SCG 16 /* Max # of SCSI controllers */
  138. struct scg_local {
  139. int scgfiles[MAX_SCG];
  140. };
  141. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  142. #define scgfiles(p) ((int *)((p)->local)) 
  143. #else
  144. /*
  145.  * We are emulating the functionality of /dev/scg? with the local
  146.  * SCSI user land implementation.
  147.  */
  148. # include "scsihack.c"
  149. #endif /* HAVE_SCG */
  150. /*
  151.  * Return version information for the SCSI transport code.
  152.  * This has been introduced to make it easier to trace down problems
  153.  * in applications.
  154.  *
  155.  * If scgp is NULL, return general library version information.
  156.  * If scgp is != NULL, return version information for the low level transport.
  157.  */
  158. EXPORT char *
  159. scg_version(scgp, what)
  160. SCSI *scgp;
  161. int what;
  162. {
  163. if (scgp == (SCSI *)0) {
  164. switch (what) {
  165. case SCG_VERSION:
  166. return (_scg_version);
  167. /*
  168.  * If you changed this source, you are not allowed to
  169.  * return "schily" for the SCG_AUTHOR request.
  170.  */
  171. case SCG_AUTHOR:
  172. return (_scg_auth_schily);
  173. case SCG_SCCS_ID:
  174. return (sccsid);
  175. default:
  176. return ((char *)0);
  177. }
  178. }
  179. return (scg__version(scgp, what));
  180. }
  181. #ifdef HAVE_SCG
  182. /*
  183.  * Return version information for the low level SCSI transport code.
  184.  * This has been introduced to make it easier to trace down problems
  185.  * in applications.
  186.  */
  187. EXPORT char *
  188. scg__version(scgp, what)
  189. SCSI *scgp;
  190. int what;
  191. {
  192. if (scgp != (SCSI *)0) {
  193. switch (what) {
  194. case SCG_VERSION:
  195. return (_scg_trans_version);
  196. /*
  197.  * If you changed this source, you are not allowed to
  198.  * return "schily" for the SCG_AUTHOR request.
  199.  */
  200. case SCG_AUTHOR:
  201. return (_scg_auth_schily);
  202. case SCG_SCCS_ID:
  203. return (sccsid);
  204. }
  205. }
  206. return ((char *)0);
  207. }
  208. EXPORT int
  209. scsi_open(scgp, device, busno, tgt, tlun)
  210. SCSI *scgp;
  211. char *device;
  212. int busno;
  213. int tgt;
  214. int tlun;
  215. {
  216. register int f;
  217. register int i;
  218. register int nopen = 0;
  219. char devname[32];
  220. if (busno >= MAX_SCG) {
  221. errno = EINVAL;
  222. if (scgp->errstr)
  223. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  224. "Illegal value for busno '%d'", busno);
  225. return (-1);
  226. }
  227. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2)) {
  228. errno = EINVAL;
  229. if (scgp->errstr)
  230. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  231. "Open by 'devname' not supported on this OS");
  232. return (-1);
  233. }
  234. if (scgp->local == NULL) {
  235. scgp->local = malloc(sizeof(struct scg_local));
  236. if (scgp->local == NULL) {
  237. if (scgp->errstr)
  238. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "No memory for scg_local");
  239. return (0);
  240. }
  241. for (i=0; i < MAX_SCG; i++) {
  242. scgfiles(scgp)[i] = -1;
  243. }
  244. }
  245. for (i=0; i < MAX_SCG; i++) {
  246. sprintf(devname, "/dev/scg%d", i);
  247. f = open(devname, 2);
  248. if (f < 0) {
  249. if (errno != ENOENT && errno != ENXIO) {
  250. if (scgp->errstr)
  251. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  252. "Cannot open '%s'", devname);
  253. return (-1);
  254. }
  255. } else {
  256. nopen++;
  257. }
  258. scgfiles(scgp)[i] = f;
  259. }
  260. return (nopen);
  261. }
  262. EXPORT int
  263. scsi_close(scgp)
  264. SCSI *scgp;
  265. {
  266. register int i;
  267. if (scgfiles(scgp) == NULL)
  268. return (-1);
  269. for (i=0; i < MAX_SCG; i++) {
  270. if (scgfiles(scgp)[i] >= 0)
  271. close(scgfiles(scgp)[i]);
  272. scgfiles(scgp)[i] = -1;
  273. }
  274. return (0);
  275. }
  276. LOCAL long
  277. scsi_maxdma(scgp)
  278. SCSI *scgp;
  279. {
  280. long maxdma = 0L;
  281. #ifdef sun
  282. #if defined(__i386_) || defined(i386)
  283. return (MAX_DMA_SUN386);
  284. #else
  285. int cpu_type = gethostid() >> 24;
  286. switch (cpu_type & ARCH_MASK) {
  287. case ARCH_SUN4C:
  288. case ARCH_SUN4E:
  289. maxdma = MAX_DMA_SUN4C;
  290. break;
  291. case ARCH_SUN4M:
  292. case ARCH_SUNX:
  293. maxdma = MAX_DMA_SUN4M;
  294. break;
  295. default:
  296. maxdma = MAX_DMA_SUN3;
  297. }
  298. #endif /* sun */
  299. #else
  300. maxdma = MAX_DMA_OTHER;
  301. #endif
  302. #ifndef __SVR4
  303. /*
  304.  * SunOS 4.x allows esp hardware on VME boards and thus
  305.  * limits DMA on esp to 64k-1
  306.  */
  307. if (maxdma > MAX_DMA_SUN3)
  308. maxdma = MAX_DMA_SUN3;
  309. #endif
  310. return (maxdma);
  311. }
  312. EXPORT
  313. BOOL scsi_havebus(scgp, busno)
  314. SCSI *scgp;
  315. int busno;
  316. {
  317. if (scgfiles(scgp) == NULL)
  318. return (FALSE);
  319. return (busno < 0 || busno >= MAX_SCG) ? FALSE : (scgfiles(scgp)[busno] >= 0);
  320. }
  321. EXPORT
  322. int scsi_fileno(scgp, busno, tgt, tlun)
  323. SCSI *scgp;
  324. int busno;
  325. int tgt;
  326. int tlun;
  327. {
  328. if (scgfiles(scgp) == NULL)
  329. return (-1);
  330. return (busno < 0 || busno >= MAX_SCG) ? -1 : scgfiles(scgp)[busno];
  331. }
  332. EXPORT int
  333. scsi_initiator_id(scgp)
  334. SCSI *scgp;
  335. {
  336. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  337. int id = -1;
  338. #ifdef DKIO_GETCINFO
  339. struct dk_cinfo conf;
  340. if (ioctl(f, DKIO_GETCINFO, &conf) < 0)
  341. return (id);
  342. if (TARGET(conf.dki_slave) != -1)
  343. id = TARGET(conf.dki_slave);
  344. #endif
  345. return (id);
  346. }
  347. EXPORT
  348. int scsi_isatapi(scgp)
  349. SCSI *scgp;
  350. {
  351. return (FALSE);
  352. }
  353. EXPORT
  354. int scsireset(scgp)
  355. SCSI *scgp;
  356. {
  357. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  358. return (ioctl(f, SCGIORESET, 0));
  359. }
  360. EXPORT void *
  361. scsi_getbuf(scgp, amt)
  362. SCSI *scgp;
  363. long amt;
  364. {
  365. if (amt <= 0 || amt > scsi_maxdma(scgp))
  366. return ((void *)0);
  367. scgp->bufbase = (void *)valloc((size_t)amt);
  368. return (scgp->bufbase);
  369. }
  370. EXPORT void
  371. scsi_freebuf(scgp)
  372. SCSI *scgp;
  373. {
  374. if (scgp->bufbase)
  375. free(scgp->bufbase);
  376. scgp->bufbase = NULL;
  377. }
  378. #endif /* HAVE_SCG */
  379. EXPORT long
  380. scsi_bufsize(scgp, amt)
  381. SCSI *scgp;
  382. long amt;
  383. {
  384. long maxdma;
  385. maxdma = scsi_maxdma(scgp);
  386. if (amt <= 0 || amt > maxdma)
  387. return (maxdma);
  388. return (amt);
  389. }
  390. EXPORT void
  391. scsi_setnonstderrs(scgp, vec)
  392. SCSI *scgp;
  393. const char **vec;
  394. {
  395. scgp->nonstderrs = vec;
  396. }
  397. EXPORT
  398. BOOL scsi_yes(msg)
  399. char *msg;
  400. {
  401. char okbuf[10];
  402. printf("%s", msg);
  403. flush();
  404. if (getline(okbuf, sizeof(okbuf)) == EOF)
  405. exit(EX_BAD);
  406. if(streql(okbuf, "y") || streql(okbuf, "yes") ||
  407.    streql(okbuf, "Y") || streql(okbuf, "YES"))
  408. return(TRUE);
  409. else
  410. return(FALSE);
  411. }
  412. #ifdef nonono
  413. LOCAL void
  414. scsi_sighandler(sig)
  415. int sig;
  416. {
  417. printf("n");
  418. if (scsi_running) {
  419. printf("Running command: %sn", scsi_command);
  420. printf("Resetting SCSI - Bus.n");
  421. if (scsireset(scgp) < 0)
  422. errmsg("Cannot reset SCSI - Bus.n");
  423. }
  424. if (scsi_yes("EXIT ? "))
  425. exit(sig);
  426. }
  427. #endif
  428. EXPORT
  429. int scsicmd(scgp)
  430. SCSI *scgp;
  431. {
  432.  int f;
  433.  int ret;
  434. register struct scg_cmd *scmd = scgp->scmd;
  435. f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  436. scmd->kdebug = scgp->kdebug;
  437. if (scmd->timeout == 0 || scmd->timeout < scgp->deftimeout)
  438. scmd->timeout = scgp->deftimeout;
  439. if (scgp->disre_disable)
  440. scmd->flags &= ~SCG_DISRE_ENA;
  441. if (scgp->noparity)
  442. scmd->flags |= SCG_NOPARITY;
  443. scmd->u_sense.cmd_sense[0] = 0; /* Paranioa */
  444. if (scgp->verbose) {
  445. printf("nExecuting '%s' command on Bus %d Target %d, Lun %d timeout %dsn",
  446. scgp->cmdname, scgp->scsibus, scgp->target, scmd->cdb.g0_cdb.lun,
  447. scmd->timeout);
  448. scsiprintcdb(scgp);
  449. if (scgp->verbose > 1)
  450. scsiprintwdata(scgp);
  451. flush();
  452. }
  453. if (scgp->running) {
  454. if (scgp->curcmdname) {
  455. error("Currently running '%s' command.n",
  456. scgp->curcmdname);
  457. }
  458. raisecond("SCSI ALREADY RUNNING !!", 0L);
  459. }
  460. gettimeofday(scgp->cmdstart, (struct timezone *)0);
  461. scgp->curcmdname = scgp->cmdname;
  462. scgp->running = TRUE;
  463. ret = scsi_send(scgp, f, scmd);
  464. scgp->running = FALSE;
  465. scsitimes(scgp);
  466. if (ret < 0) {
  467. /*
  468.  * Old /dev/scg versions will not allow to access targets > 7.
  469.  * Include a workaround to make this non fatal.
  470.  */
  471. if (scgp->target < 8 || geterrno() != EINVAL)
  472. comerr("Cannot send SCSI cmd via ioctln");
  473. if (scmd->ux_errno == 0)
  474. scmd->ux_errno = geterrno();
  475. if (scmd->error == SCG_NO_ERROR)
  476. scmd->error = SCG_FATAL;
  477. if (scgp->debug) {
  478. errmsg("ret < 0 errno: %d ux_errno: %d error: %dn",
  479. geterrno(), scmd->ux_errno, scmd->error);
  480. }
  481. }
  482. ret = scsicheckerr(scgp);
  483. if (scgp->verbose || (ret && scgp->silent <= 0)) {
  484. scsiprintresult(scgp);
  485. }
  486. return (ret);
  487. }
  488. EXPORT
  489. int scsigetresid(scgp)
  490. SCSI *scgp;
  491. {
  492. return (scgp->scmd->resid);
  493. }
  494. LOCAL
  495. void scsitimes(scgp)
  496. SCSI *scgp;
  497. {
  498. struct timeval *stp = scgp->cmdstop;
  499. gettimeofday(stp, (struct timezone *)0);
  500. stp->tv_sec -= scgp->cmdstart->tv_sec;
  501. stp->tv_usec -= scgp->cmdstart->tv_usec;
  502. while (stp->tv_usec < 0) {
  503. stp->tv_sec -= 1;
  504. stp->tv_usec += 1000000;
  505. }
  506. }
  507. LOCAL BOOL
  508. scsierr(scgp)
  509. SCSI *scgp;
  510. {
  511. register struct scg_cmd *cp = scgp->scmd;
  512. if(cp->error != SCG_NO_ERROR ||
  513. cp->ux_errno != 0 ||
  514. *(u_char *)&cp->scb != 0 ||
  515. cp->u_sense.cmd_sense[0] != 0) /* Paranioa */
  516. return (TRUE);
  517. return (FALSE);
  518. }
  519. LOCAL int
  520. scsicheckerr(scgp)
  521. SCSI *scgp;
  522. {
  523. register int ret;
  524. ret = 0;
  525. if(scsierr(scgp)) {
  526. if (!scgp->silent || scgp->verbose)
  527. scsiprinterr(scgp);
  528. ret = -1;
  529. }
  530. if ((!scgp->silent || scgp->verbose) && scgp->scmd->resid) {
  531. printf("resid: %dn", scgp->scmd->resid);
  532. flush();
  533. }
  534. return (ret);
  535. }
  536. EXPORT void
  537. scsiprinterr(scgp)
  538. SCSI *scgp;
  539. {
  540. register struct scg_cmd *cp = scgp->scmd;
  541. register char *err;
  542. char errbuf[64];
  543. switch (cp->error) {
  544. case SCG_NO_ERROR : err = "no error"; break;
  545. case SCG_RETRYABLE: err = "retryable error"; break;
  546. case SCG_FATAL    : err = "fatal error"; break;
  547. /*
  548.  * We need to cast timeval->* to long because
  549.  * of the broken sys/time.h in Linux.
  550.  */
  551. case SCG_TIMEOUT  : sprintf(errbuf,
  552. "cmd timeout after %ld.%03ld (%d) s",
  553. (long)scgp->cmdstop->tv_sec,
  554. (long)scgp->cmdstop->tv_usec/1000,
  555. cp->timeout);
  556. err = errbuf;
  557. break;
  558. default: sprintf(errbuf, "error: %d", cp->error);
  559. err = errbuf;
  560. }
  561. errmsgno(cp->ux_errno, "%s: scsi sendcmd: %sn", scgp->cmdname, err);
  562. scsiprintcdb(scgp);
  563. if (cp->error <= SCG_RETRYABLE)
  564. scsiprintstatus(scgp);
  565. if (cp->scb.chk) {
  566. scsiprsense((u_char *)&cp->sense, cp->sense_count);
  567. scsierrmsg(scgp, &cp->sense, &cp->scb, -1, scgp->nonstderrs);
  568. }
  569. flush();
  570. }
  571. EXPORT void
  572. scsiprintcdb(scgp)
  573. SCSI *scgp;
  574. {
  575. scsiprbytes("CDB: ", scgp->scmd->cdb.cmd_cdb, scgp->scmd->cdb_len);
  576. }
  577. EXPORT void
  578. scsiprintwdata(scgp)
  579. SCSI *scgp;
  580. {
  581. register struct scg_cmd *scmd = scgp->scmd;
  582. if (scmd->size > 0 && (scmd->flags & SCG_RECV_DATA) == 0) {
  583. printf("Sending %d (0x%X) bytes of data.n",
  584. scmd->size, scmd->size);
  585. scsiprbytes("Write Data: ",
  586. (Uchar *)scmd->addr,
  587. scmd->size > 100 ? 100 : scmd->size);
  588. }
  589. }
  590. EXPORT void
  591. scsiprintrdata(scgp)
  592. SCSI *scgp;
  593. {
  594. register struct scg_cmd *scmd = scgp->scmd;
  595. if (scmd->size > 0 && (scmd->flags & SCG_RECV_DATA) != 0) {
  596. printf("Got %d (0x%X), expecting %d (0x%X) bytes of data.n",
  597. scmd->size-scmd->resid, scmd->size-scmd->resid,
  598. scmd->size, scmd->size);
  599. scsiprbytes("Received Data: ",
  600. (Uchar *)scmd->addr,
  601. (scmd->size-scmd->resid) > 100 ?
  602. 100 : (scmd->size-scmd->resid));
  603. }
  604. }
  605. EXPORT void
  606. scsiprintresult(scgp)
  607. SCSI *scgp;
  608. {
  609. printf("cmd finished after %ld.%03lds timeout %dsn",
  610. (long)scgp->cmdstop->tv_sec,
  611. (long)scgp->cmdstop->tv_usec/1000,
  612. scgp->scmd->timeout);
  613. if (scgp->verbose > 1)
  614. scsiprintrdata(scgp);
  615. flush();
  616. }
  617. EXPORT
  618. void scsiprintstatus(scgp)
  619. SCSI *scgp;
  620. {
  621. register struct scg_cmd *cp = scgp->scmd;
  622. error("status: 0x%x ", *(u_char *)&cp->scb);
  623. #ifdef SCSI_EXTENDED_STATUS
  624. if (cp->scb.ext_st1)
  625. error("0x%x ", ((u_char *)&cp->scb)[1]);
  626. if (cp->scb.ext_st2)
  627. error("0x%x ", ((u_char *)&cp->scb)[2]);
  628. #endif
  629. error("(");
  630. switch (*(u_char *)&cp->scb & 036) {
  631. case 0  : error("GOOD STATUS"); break;
  632. case 02 : error("CHECK CONDITION"); break;
  633. case 04 : error("CONDITION MET/GOOD"); break;
  634. case 010: error("BUSY"); break;
  635. case 020: error("INTERMEDIATE GOOD STATUS"); break;
  636. case 024: error("INTERMEDIATE CONDITION MET/GOOD"); break;
  637. case 030: error("RESERVATION CONFLICT"); break;
  638. default : error("Reserved"); break;
  639. }
  640. #ifdef SCSI_EXTENDED_STATUS
  641. if (cp->scb.ext_st1 && cp->scb.ha_er)
  642. error(" host adapter detected error");
  643. #endif
  644. error(")n");
  645. }
  646. EXPORT void
  647. scsiprbytes(s, cp, n)
  648. char *s;
  649. register u_char *cp;
  650. register int n;
  651. {
  652. printf(s);
  653. while (--n >= 0)
  654. printf(" %02X", *cp++);
  655. printf("n");
  656. }
  657. EXPORT void
  658. scsiprsense(cp, n)
  659. u_char *cp;
  660. int n;
  661. {
  662. scsiprbytes("Sense Bytes:", cp, n);
  663. }
  664. EXPORT int
  665. scsi_sense_key(scgp)
  666. SCSI *scgp;
  667. {
  668. register struct scg_cmd *cp = scgp->scmd;
  669. int key = -1;
  670. if(!scsierr(scgp))
  671. return (0);
  672. if (cp->sense.code >= 0x70)
  673. key = ((struct scsi_ext_sense*)&(cp->sense))->key;
  674. return(key);
  675. }
  676. EXPORT int
  677. scsi_sense_code(scgp)
  678. SCSI *scgp;
  679. {
  680. register struct scg_cmd *cp = scgp->scmd;
  681. int code = -1;
  682. if(!scsierr(scgp))
  683. return (0);
  684. if (cp->sense.code >= 0x70)
  685. code = ((struct scsi_ext_sense*)&(cp->sense))->sense_code;
  686. else
  687. code = cp->sense.code;
  688. return(code);
  689. }
  690. EXPORT int
  691. scsi_sense_qual(scgp)
  692. SCSI *scgp;
  693. {
  694. register struct scg_cmd *cp = scgp->scmd;
  695. if(!scsierr(scgp))
  696. return (0);
  697. if (cp->sense.code >= 0x70)
  698. return (((struct scsi_ext_sense*)&(cp->sense))->qual_code);
  699. else
  700. return (0);
  701. }
  702. EXPORT
  703. void scsiprintdev(ip)
  704. struct scsi_inquiry *ip;
  705. {
  706. if (ip->removable)
  707. printf("Removable ");
  708. if (ip->data_format >= 2) {
  709. switch (ip->qualifier) {
  710. case INQ_DEV_PRESENT: break;
  711. case INQ_DEV_NOTPR:
  712. printf("not present "); break;
  713. case INQ_DEV_RES:
  714. printf("reserved "); break;
  715. case INQ_DEV_NOTSUP:
  716. if (ip->type == INQ_NODEV) {
  717. printf("unsupportedn"); return;
  718. }
  719. printf("unsupported "); break;
  720. default:
  721. printf("vendor specific %d ", ip->qualifier);
  722. }
  723. }
  724. switch (ip->type) {
  725. case INQ_DASD:
  726. printf("Disk"); break;
  727. case INQ_SEQD:
  728. printf("Tape"); break;
  729. case INQ_PRTD:
  730. printf("Printer"); break;
  731. case INQ_PROCD:
  732. printf("Processor"); break;
  733. case INQ_WORM:
  734. printf("WORM"); break;
  735. case INQ_ROMD:
  736. printf("CD-ROM"); break;
  737. case INQ_SCAN:
  738. printf("Scanner"); break;
  739. case INQ_OMEM:
  740. printf("Optical Storage"); break;
  741. case INQ_JUKE:
  742. printf("Juke Box"); break;
  743. case INQ_COMM:
  744. printf("Communication"); break;
  745. case INQ_IT8_1:
  746. printf("IT8 1"); break;
  747. case INQ_IT8_2:
  748. printf("IT8 2"); break;
  749. case INQ_STARR:
  750. printf("Storage array"); break;
  751. case INQ_ENCL:
  752. printf("Enclosure services"); break;
  753. case INQ_NODEV:
  754. if (ip->data_format >= 2) {
  755. printf("unknown/no device");
  756. break;
  757. } else if (ip->qualifier == INQ_DEV_NOTSUP) {
  758. printf("unit not present");
  759. break;
  760. }
  761. default:
  762. printf("unknown device type 0x%x", ip->type);
  763. }
  764. printf("n");
  765. }