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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsiopen.c 1.80 99/10/15 Copyright 1995 J. Schilling */
  2. #ifndef lint
  3. static char sccsid[] =
  4. "@(#)scsiopen.c 1.80 99/10/15 Copyright 1995 J. Schilling";
  5. #endif
  6. /*
  7.  * SCSI command functions for cdrecord
  8.  *
  9.  * Copyright (c) 1995 J. Schilling
  10.  */
  11. /*
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2, or (at your option)
  15.  * any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; see the file COPYING.  If not, write to
  24.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26. /*
  27.  * NOTICE: The Philips CDD 521 has several firmware bugs.
  28.  * One of them is not to respond to a SCSI selection
  29.  * within 200ms if the general load on the
  30.  * SCSI bus is high. To deal with this problem
  31.  * most of the SCSI commands are send with the
  32.  * SCG_CMD_RETRY flag enabled.
  33.  */
  34. #include <mconfig.h>
  35. #include <stdio.h>
  36. #include <standard.h>
  37. #include <stdxlib.h>
  38. #include <unixstd.h>
  39. #include <fctldefs.h>
  40. #include <errno.h>
  41. #include <strdefs.h>
  42. #include <timedefs.h>
  43. #include <utypes.h>
  44. #include <btorder.h>
  45. #include <scg/scgcmd.h>
  46. #include <scg/scsidefs.h>
  47. #include <scg/scsireg.h>
  48. #include <scg/scsitransp.h>
  49. #define strbeg(s1,s2) (strstr((s2), (s1)) == (s2))
  50. extern int lverbose;
  51. EXPORT SCSI *open_scsi __PR((char *scsidev, char *errs, int slen, int debug,
  52. int be_verbose));
  53. LOCAL int scsi_scandev __PR((char *devp, char *errs, int slen, 
  54. int *busp, int *tgtp, int *lunp));
  55. EXPORT int close_scsi __PR((SCSI * scgp));
  56. EXPORT void scsi_settimeout __PR((SCSI * scgp, int timeout));
  57. EXPORT SCSI *scsi_smalloc __PR((void));
  58. EXPORT void scsi_sfree __PR((SCSI *scgp));
  59. /*
  60.  * Open a SCSI device.
  61.  *
  62.  * Possible syntax is:
  63.  *
  64.  * Preferred:
  65.  * dev=target,lun / dev=scsibus,target,lun
  66.  *
  67.  * Needed on some systems:
  68.  * dev=devicename:target,lun / dev=devicename:scsibus,target,lun
  69.  *
  70.  * On systems that don't support SCSI Bus scanning this syntax helps:
  71.  * dev=devicename:@ / dev=devicename:@,lun
  72.  * or dev=devicename (undocumented)
  73.  *
  74.  * NOTE: As the 'lun' is part of the SCSI command descriptor block, it
  75.  *   must always be known. If the OS cannot map it, it must be
  76.  *  specified on command line.
  77.  */
  78. EXPORT SCSI *
  79. open_scsi(scsidev, errs, slen, debug, be_verbose)
  80. char *scsidev;
  81. char *errs;
  82. int slen;
  83. int debug;
  84. int be_verbose;
  85. {
  86. char devname[256];
  87. char *devp = NULL;
  88. int x1, x2, x3;
  89. int n = 0;
  90. SCSI *scgp;
  91. if (errs)
  92. errs[0] = '';
  93. scgp = scsi_smalloc();
  94. if (scgp == NULL) {
  95. if (errs)
  96. js_snprintf(errs, slen, "No memory for SCSI structure");
  97. return ((SCSI *)0);
  98. }
  99. scgp->debug = debug;
  100. devname[0] = '';
  101. if (scsidev != NULL) {
  102. if ((devp = strchr(scsidev, ':')) == NULL) {
  103. if (strchr(scsidev, ',') == NULL) {
  104. /* Notation form: 'devname' (undocumented)   */
  105. /* Fetch bus/tgt/lun values from OS      */
  106. n = -1;
  107. scgp->lun = -2; /* Lun must be known      */
  108. strncpy(devname, scsidev, sizeof(devname)-1);
  109. devname[sizeof(devname)-1] = '';
  110. } else {
  111. /* Basic notation form: 'bus,tgt,lun'      */
  112. devp = scsidev;
  113. }
  114. } else {
  115. /* Notation form: 'devname:bus,tgt,lun'/'devname:@'  */
  116. x1 = devp - scsidev;
  117. if (x1 >= (int)sizeof(devname))
  118. x1 = sizeof(devname)-1;
  119. strncpy(devname, scsidev, x1);
  120. devname[x1] = '';
  121. devp++;
  122. /* Check for a notation in the form 'devname:@'      */
  123. if (devp[0] == '@') {
  124. if (devp[1] == '') {
  125. scgp->lun = -2;
  126. } else if (devp[1] == ',') {
  127. if (*astoi(&devp[2], &scgp->lun) != '') {
  128. errno = EINVAL;
  129. if (errs)
  130. js_snprintf(errs, slen,
  131. "Invalid lun specifier '%s'",
  132. &devp[2]);
  133. return ((SCSI *)0);
  134. }
  135. }
  136. n = -1;
  137. devp = NULL;
  138. }
  139. }
  140. }
  141. if (devp != NULL) {
  142. n = scsi_scandev(devp, errs, slen, &x1, &x2, &x3);
  143. if (n < 0) {
  144. errno = EINVAL;
  145. return ((SCSI *)0);
  146. }
  147. }
  148. if (n == 3 || n == 2) { /* Got bus,target,lun or target,lun */
  149. scgp->scsibus = x1;
  150. scgp->target = x2;
  151. scgp->lun = x3;
  152. } else if (n == -1) { /* Got device:@, fetch bus/lun from OS */
  153. scgp->scsibus = scgp->target = -2;
  154. } else if (devp != NULL) {
  155. printf("WARNING: device not valid, trying to use default target...n");
  156. scgp->scsibus = 0;
  157. scgp->target = 6;
  158. scgp->lun = 0;
  159. }
  160. if (be_verbose && scsidev != NULL) {
  161. printf("scsidev: '%s'n", scsidev);
  162. if (devname[0] != '')
  163. printf("devname: '%s'n", devname);
  164. printf("scsibus: %d target: %d lun: %dn",
  165. scgp->scsibus, scgp->target, scgp->lun);
  166. }
  167. if (scsi_open(scgp, devname, scgp->scsibus, scgp->target, scgp->lun) <= 0) {
  168. if (errs && scgp->errstr)
  169. js_snprintf(errs, slen, scgp->errstr);
  170. scsi_sfree(scgp);
  171. return ((SCSI *)0);
  172. }
  173. return (scgp);
  174. }
  175. /*
  176.  * Convert scgp->target,lun or scsibus,target,lun syntax.
  177.  * Check for bad syntax and invalid values.
  178.  * This is definitely better than using scanf() as it checks for syntax errors.
  179.  */
  180. LOCAL int
  181. scsi_scandev(devp, errs, slen, busp, tgtp, lunp)
  182. char *devp;
  183. char *errs;
  184. int slen;
  185. int *busp;
  186. int *tgtp;
  187. int *lunp;
  188. {
  189. int x1, x2, x3;
  190. int n = 0;
  191. char *p = devp;
  192. x1 = x2 = x3 = 0;
  193. *busp = *tgtp = *lunp = 0;
  194. if (*p != '') {
  195. p = astoi(p, &x1);
  196. if (*p == ',') {
  197. p++;
  198. n++;
  199. } else {
  200. if (errs)
  201. js_snprintf(errs, slen, "Invalid bus or target specifier in '%s'", devp);
  202. return (-1);
  203. }
  204. }
  205. if (*p != '') {
  206. p = astoi(p, &x2);
  207. if (*p == ',' || *p == '') {
  208. if (*p != '')
  209. p++;
  210. n++;
  211. } else {
  212. if (errs)
  213. js_snprintf(errs, slen, "Invalid target or lun specifier in '%s'", devp);
  214. return (-1);
  215. }
  216. }
  217. if (*p != '') {
  218. p = astoi(p, &x3);
  219. if (*p == '') {
  220. n++;
  221. } else {
  222. if (errs)
  223. js_snprintf(errs, slen, "Invalid lun specifier in '%s'", devp);
  224. return (-1);
  225. }
  226. }
  227. if (n == 3) {
  228. *busp = x1;
  229. *tgtp = x2;
  230. *lunp = x3;
  231. }
  232. if (n == 2) {
  233. *tgtp = x1;
  234. *lunp = x2;
  235. }
  236. if (n == 1) {
  237. *tgtp = x1;
  238. }
  239. if (x1 < 0 || x2 < 0 || x3 < 0) {
  240. if (errs)
  241. js_snprintf(errs, slen, "Invalid value for bus, target or lun (%d,%d,%d)",
  242. *busp, *tgtp, *lunp);
  243. return (-1);
  244. }
  245. return (n);
  246. }
  247. EXPORT int
  248. close_scsi(scgp)
  249. SCSI *scgp;
  250. {
  251. scsi_close(scgp);
  252. scsi_sfree(scgp);
  253. return (0);
  254. }
  255. EXPORT void
  256. scsi_settimeout(scgp, timeout)
  257. SCSI *scgp;
  258. int timeout;
  259. {
  260. #ifdef nonono
  261. if (timeout >= 0)
  262. scgp->deftimeout = timeout;
  263. #else
  264. scgp->deftimeout = timeout;
  265. #endif
  266. }
  267. EXPORT SCSI *
  268. scsi_smalloc()
  269. {
  270. SCSI *scgp;
  271. scgp = (SCSI *)malloc(sizeof(*scgp));
  272. if (scgp == NULL)
  273. return ((SCSI *)0);
  274. fillbytes(scgp, sizeof(*scgp), 0);
  275. scgp->scsibus = -1;
  276. scgp->target = -1;
  277. scgp->lun = -1;
  278. scgp->deftimeout = 20;
  279. scgp->running = FALSE;
  280. scgp->cmdstart = (struct timeval *)malloc(sizeof(struct timeval));
  281. if (scgp->cmdstart == NULL)
  282. goto err;
  283. scgp->cmdstop = (struct timeval *)malloc(sizeof(struct timeval));
  284. if (scgp->cmdstop == NULL)
  285. goto err;
  286. scgp->scmd = (struct scg_cmd *)malloc(sizeof(struct scg_cmd));
  287. if (scgp->scmd == NULL)
  288. goto err;
  289. scgp->errstr = malloc(SCSI_ERRSTR_SIZE);
  290. if (scgp->errstr == NULL)
  291. goto err;
  292. scgp->errptr = scgp->errstr;
  293. scgp->errstr[0] = '';
  294. scgp->inq = (struct scsi_inquiry *)malloc(sizeof(struct scsi_inquiry));
  295. if (scgp->inq == NULL)
  296. goto err;
  297. scgp->cap = (struct scsi_capacity *)malloc(sizeof(struct scsi_capacity));
  298. if (scgp->cap == NULL)
  299. goto err;
  300. return (scgp);
  301. err:
  302. scsi_sfree(scgp);
  303. return ((SCSI *)0);
  304. }
  305. EXPORT void
  306. scsi_sfree(scgp)
  307. SCSI *scgp;
  308. {
  309. if (scgp->cmdstart)
  310. free(scgp->cmdstart);
  311. if (scgp->cmdstop)
  312. free(scgp->cmdstop);
  313. if (scgp->scmd)
  314. free(scgp->scmd);
  315. if (scgp->inq)
  316. free(scgp->inq);
  317. if (scgp->cap)
  318. free(scgp->cap);
  319. if (scgp->local)
  320. free(scgp->local);
  321. scsi_freebuf(scgp);
  322. if (scgp->errstr)
  323. free(scgp->errstr);
  324. free(scgp);
  325. }