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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-bsd-os.c 1.13 99/10/07 Copyright 1997 J. Schilling */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-bsd-os.c 1.13 99/10/07 Copyright 1997 J. Schilling";
  5. #endif
  6. /*
  7.  * Interface for the BSD/OS user-land raw SCSI implementation.
  8.  *
  9.  * This is a hack, that tries to emulate the functionality
  10.  * of the scg driver.
  11.  *
  12.  * Warning: you may change this source, but if you do that
  13.  * you need to change the _scg_version and _scg_auth* string below.
  14.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  15.  * Choose your name instead of "schily" and make clear that the version
  16.  * string is related to a modified source.
  17.  *
  18.  * Copyright (c) 1997 J. Schilling
  19.  */
  20. /*
  21.  * This program is free software; you can redistribute it and/or modify
  22.  * it under the terms of the GNU General Public License as published by
  23.  * the Free Software Foundation; either version 2, or (at your option)
  24.  * any later version.
  25.  *
  26.  * This program is distributed in the hope that it will be useful,
  27.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  29.  * GNU General Public License for more details.
  30.  *
  31.  * You should have received a copy of the GNU General Public License
  32.  * along with this program; see the file COPYING.  If not, write to
  33.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  34.  */
  35. #undef sense
  36. #define scsi_sense bsdi_scsi_sense
  37. #define scsi_inquiry bsdi_scsi_inquiry
  38. /*
  39.  * Must use -I/sys...
  40.  * The next two files are in /sys/dev/scsi
  41.  */
  42. #include <dev/scsi/scsi.h>
  43. #include <dev/scsi/scsi_ioctl.h>
  44. /*
  45.  * Warning: you may change this source, but if you do that
  46.  * you need to change the _scg_version and _scg_auth* string below.
  47.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  48.  * Choose your name instead of "schily" and make clear that the version
  49.  * string is related to a modified source.
  50.  */
  51. LOCAL char _scg_trans_version[] = "scsi-bsd-os.c-1.13"; /* The version for this transport*/
  52. #define MAX_SCG 16 /* Max # of SCSI controllers */
  53. #define MAX_TGT 16
  54. #define MAX_LUN 8
  55. struct scg_local {
  56. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  57. };
  58. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  59. #include <machine/param.h>
  60. #define MAX_DMA_BSDI MAXPHYS /* More makes problems */
  61. LOCAL BOOL scsi_setup __PR((SCSI *scgp, int f, int busno, int tgt, int tlun));
  62. /*
  63.  * Return version information for the low level SCSI transport code.
  64.  * This has been introduced to make it easier to trace down problems
  65.  * in applications.
  66.  */
  67. EXPORT char *
  68. scg__version(scgp, what)
  69. SCSI *scgp;
  70. int what;
  71. {
  72. if (scgp != (SCSI *)0) {
  73. switch (what) {
  74. case SCG_VERSION:
  75. return (_scg_trans_version);
  76. /*
  77.  * If you changed this source, you are not allowed to
  78.  * return "schily" for the SCG_AUTHOR request.
  79.  */
  80. case SCG_AUTHOR:
  81. return (_scg_auth_schily);
  82. case SCG_SCCS_ID:
  83. return (__sccsid);
  84. }
  85. }
  86. return ((char *)0);
  87. }
  88. EXPORT int
  89. scsi_open(scgp, device, busno, tgt, tlun)
  90. SCSI *scgp;
  91. char *device;
  92. int busno;
  93. int tgt;
  94. int tlun;
  95. {
  96. register int f;
  97. register int b;
  98. register int t;
  99. register int l;
  100. register int nopen = 0;
  101. char devname[64];
  102. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  103. errno = EINVAL;
  104. if (scgp->errstr)
  105. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  106. "Illegal value for busno, target or lun '%d,%d,%d'",
  107. busno, tgt, tlun);
  108. return (-1);
  109. }
  110. if (scgp->local == NULL) {
  111. scgp->local = malloc(sizeof(struct scg_local));
  112. if (scgp->local == NULL)
  113. return (0);
  114. for (b=0; b < MAX_SCG; b++) {
  115. for (t=0; t < MAX_TGT; t++) {
  116. for (l=0; l < MAX_LUN ; l++)
  117. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  118. }
  119. }
  120. }
  121. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2))
  122. goto openbydev;
  123. if (busno >= 0 && tgt >= 0 && tlun >= 0) {
  124. sprintf(devname, "/dev/su%d-%d-%d", busno, tgt, tlun);
  125. f = open(devname, O_RDWR|O_NONBLOCK);
  126. if (f < 0) {
  127. goto openbydev;
  128. }
  129. scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
  130. return(1);
  131. } else for (b=0; b < MAX_SCG; b++) {
  132. for (t=0; t < MAX_TGT; t++) {
  133. for (l=0; l < MAX_LUN ; l++) {
  134. sprintf(devname, "/dev/su%d-%d-%d", b, t, l);
  135. f = open(devname, O_RDWR|O_NONBLOCK);
  136. /* error("open (%s) = %dn", devname, f);*/
  137. if (f < 0) {
  138. if (errno != ENOENT &&
  139.     errno != ENXIO &&
  140.     errno != ENODEV) {
  141. if (scgp->errstr)
  142. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  143. "Cannot open '%s'",
  144. devname);
  145. return (0);
  146. }
  147. } else {
  148. if (scsi_setup(scgp, f, b, t, l))
  149. nopen++;
  150. }
  151. }
  152. }
  153. }
  154. /*
  155.  * Could not open /dev/su-* or got dev=devname:b,l,l / dev=devname:@,l
  156.  * We do the apropriate tests and try our best.
  157.  */
  158. openbydev:
  159. if (nopen == 0) {
  160. if (device == NULL || device[0] == '')
  161. return (0);
  162. f = open(device, O_RDWR|O_NONBLOCK);
  163. if (f < 0)
  164. return (0);
  165. if (tlun == -2) { /* If 'lun' is not known, we reject */
  166. close(f);
  167. errno = EINVAL;
  168. return (0);
  169. }
  170. scgp->scsibus = busno = 0; /* use fake number, we cannot get it */
  171. scgp->target  = tgt = 0; /* use fake number, we cannot get it */
  172. /* 'lun' has been specified on command line */
  173. if (scsi_setup(scgp, f, busno, tgt, tlun))
  174. nopen++;
  175. }
  176. return (nopen);
  177. }
  178. EXPORT int
  179. scsi_close(scgp)
  180. SCSI *scgp;
  181. {
  182. register int f;
  183. register int b;
  184. register int t;
  185. register int l;
  186. if (scgp->local == NULL)
  187. return (-1);
  188. for (b=0; b < MAX_SCG; b++) {
  189. for (t=0; t < MAX_TGT; t++) {
  190. for (l=0; l < MAX_LUN ; l++)
  191. f = scglocal(scgp)->scgfiles[b][t][l];
  192. if (f >= 0)
  193. close(f);
  194. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  195. }
  196. }
  197. return (0);
  198. }
  199. LOCAL BOOL
  200. scsi_setup(scgp, f, busno, tgt, tlun)
  201. SCSI *scgp;
  202. int f;
  203. int busno;
  204. int tgt;
  205. int tlun;
  206. {
  207. int Bus;
  208. int Target;
  209. int Lun;
  210. BOOL onetarget = FALSE;
  211. if (scgp->scsibus >= 0 && scgp->target >= 0 && scgp->lun >= 0)
  212. onetarget = TRUE;
  213. /*
  214.  * Unfortunately there is no way to get the right values from kernel.
  215.  */
  216. Bus = busno;
  217. Target = tgt;
  218. Lun = tlun;
  219. if (scgp->debug)
  220. printf("Bus: %d Target: %d Lun: %dn", Bus, Target, Lun);
  221. if (Bus >= MAX_SCG || Target >= 8 || Lun >= 8) {
  222. close(f);
  223. return (FALSE);
  224. }
  225. if (scglocal(scgp)->scgfiles[Bus][Target][Lun] == (short)-1)
  226. scglocal(scgp)->scgfiles[Bus][Target][Lun] = (short)f;
  227. if (onetarget) {
  228. if (Bus == busno && Target == tgt && Lun == tlun) {
  229. return (TRUE);
  230. } else {
  231. scglocal(scgp)->scgfiles[Bus][Target][Lun] = (short)-1;
  232. close(f);
  233. }
  234. }
  235. return (FALSE);
  236. }
  237. LOCAL long
  238. scsi_maxdma(scgp)
  239. SCSI *scgp;
  240. {
  241. long maxdma = MAX_DMA_BSDI;
  242. return (maxdma);
  243. }
  244. EXPORT void *
  245. scsi_getbuf(scgp, amt)
  246. SCSI *scgp;
  247. long amt;
  248. {
  249. if (amt <= 0 || amt > scsi_maxdma(scgp))
  250. return ((void *)0);
  251. if (scgp->debug)
  252. printf("scsi_getbuf: %ld bytesn", amt);
  253. scgp->bufbase = malloc((size_t)(amt));
  254. return (scgp->bufbase);
  255. }
  256. EXPORT void
  257. scsi_freebuf(scgp)
  258. SCSI *scgp;
  259. {
  260. if (scgp->bufbase)
  261. free(scgp->bufbase);
  262. scgp->bufbase = NULL;
  263. }
  264. EXPORT
  265. BOOL scsi_havebus(scgp, busno)
  266. SCSI *scgp;
  267. int busno;
  268. {
  269. register int t;
  270. register int l;
  271. if (busno < 0 || busno >= MAX_SCG)
  272. return (FALSE);
  273. if (scgp->local == NULL)
  274. return (-1);
  275. for (t=0; t < MAX_TGT; t++) {
  276. for (l=0; l < MAX_LUN ; l++)
  277. if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
  278. return (TRUE);
  279. }
  280. return (FALSE);
  281. }
  282. EXPORT
  283. int scsi_fileno(scgp, busno, tgt, tlun)
  284. SCSI *scgp;
  285. int busno;
  286. int tgt;
  287. int tlun;
  288. {
  289. if (busno < 0 || busno >= MAX_SCG ||
  290.     tgt < 0 || tgt >= MAX_TGT ||
  291.     tlun < 0 || tlun >= MAX_LUN)
  292. return (-1);
  293. if (scgp->local == NULL)
  294. return (-1);
  295. return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
  296. }
  297. EXPORT int
  298. scsi_initiator_id(scgp)
  299. SCSI *scgp;
  300. {
  301. return (-1);
  302. }
  303. EXPORT
  304. int scsi_isatapi(scgp)
  305. SCSI *scgp;
  306. {
  307. return (FALSE);
  308. }
  309. EXPORT
  310. int scsireset(scgp)
  311. SCSI *scgp;
  312. {
  313. /*
  314.  * Cannot reset on BSD/OS
  315.  */
  316. return (-1);
  317. }
  318. LOCAL int
  319. scsi_send(scgp, f, sp)
  320. SCSI *scgp;
  321. int f;
  322. struct scg_cmd *sp;
  323. {
  324. scsi_user_cdb_t suc;
  325. int ret = 0;
  326. /* printf("f: %dn", f);*/
  327. if (f < 0) {
  328. sp->error = SCG_FATAL;
  329. return (0);
  330. }
  331. /* Zero the structure... */
  332. fillbytes(&suc, sizeof(suc), '');
  333. /* Read or write? */
  334. if (sp->flags & SCG_RECV_DATA) {
  335. suc.suc_flags |= SUC_READ;
  336. } else if (sp->size > 0) {
  337. suc.suc_flags |= SUC_WRITE;
  338. }
  339. suc.suc_timeout = sp->timeout;
  340. suc.suc_cdblen = sp->cdb_len;
  341. movebytes(sp->cdb.cmd_cdb, suc.suc_cdb, suc.suc_cdblen);
  342. suc.suc_datalen = sp->size;
  343. suc.suc_data = sp->addr;
  344. if (ioctl(f, SCSIRAWCDB, &suc) < 0) {
  345. ret  = -1;
  346. sp->ux_errno = geterrno();
  347. if (sp->ux_errno != ENOTTY)
  348. ret = 0;
  349. } else {
  350. sp->ux_errno = 0;
  351. if (suc.suc_sus.sus_status != STS_GOOD)
  352. sp->ux_errno = EIO;
  353. }
  354. fillbytes(&sp->scb, sizeof(sp->scb), '');
  355. fillbytes(&sp->u_sense.cmd_sense, sizeof(sp->u_sense.cmd_sense), '');
  356. #if 0
  357. /*
  358.  * Unfortunalety, BSD/OS has no idea of DMA residual count.
  359.  */
  360. sp->resid = req.datalen - req.datalen_used;
  361. sp->sense_count = req.senselen_used;
  362. #else
  363. sp->resid = 0;
  364. sp->sense_count = sizeof(suc.suc_sus.sus_sense);
  365. #endif
  366. if (sp->sense_count > SCG_MAX_SENSE)
  367. sp->sense_count = SCG_MAX_SENSE;
  368. movebytes(suc.suc_sus.sus_sense, sp->u_sense.cmd_sense, sp->sense_count);
  369. sp->u_scb.cmd_scb[0] = suc.suc_sus.sus_status;
  370. switch (suc.suc_sus.sus_status) {
  371. case STS_GOOD:
  372. sp->error = SCG_NO_ERROR; break;
  373. case STS_CMD_TERMINATED:sp->error = SCG_TIMEOUT; break;
  374. case STS_BUSY: sp->error = SCG_RETRYABLE; break;
  375. case STS_CHECKCOND: sp->error = SCG_RETRYABLE; break;
  376. case STS_QUEUE_FULL: sp->error = SCG_RETRYABLE; break;
  377. default: sp->error = SCG_FATAL; break;
  378. }
  379. return (ret);
  380. }
  381. #define sense u_sense.Sense
  382. #undef scsi_sense
  383. #undef scsi_inquiry