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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-next.c 1.16 99/09/17 Copyright 1997 J. Schilling */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-next.c 1.16 99/09/17 Copyright 1997 J. Schilling";
  5. #endif
  6. /*
  7.  * Interface for the NeXT Step generic 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. #include <bsd/dev/scsireg.h>
  36. /*
  37.  * Warning: you may change this source, but if you do that
  38.  * you need to change the _scg_version and _scg_auth* string below.
  39.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  40.  * Choose your name instead of "schily" and make clear that the version
  41.  * string is related to a modified source.
  42.  */
  43. LOCAL char _scg_trans_version[] = "scsi-next.c-1.16"; /* The version for this transport*/
  44. #define MAX_SCG 16 /* Max # of SCSI controllers */
  45. #define MAX_TGT 16
  46. #define MAX_LUN 8
  47. struct scg_local {
  48. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  49. int scgfile;
  50. int max_scsibus;
  51. int cur_scsibus;
  52. int cur_target;
  53. int cur_lun;
  54. };
  55. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  56. /*#define MAX_DMA_NEXT (32*1024)*/
  57. #define MAX_DMA_NEXT (64*1024) /* Check if this is not too big */
  58. LOCAL BOOL scsi_setup __PR((SCSI *scgp, int busno, int tgt, int tlun,
  59. BOOL ex));
  60. /*
  61.  * Return version information for the low level SCSI transport code.
  62.  * This has been introduced to make it easier to trace down problems
  63.  * in applications.
  64.  */
  65. EXPORT char *
  66. scg__version(scgp, what)
  67. SCSI *scgp;
  68. int what;
  69. {
  70. if (scgp != (SCSI *)0) {
  71. switch (what) {
  72. case SCG_VERSION:
  73. return (_scg_trans_version);
  74. /*
  75.  * If you changed this source, you are not allowed to
  76.  * return "schily" for the SCG_AUTHOR request.
  77.  */
  78. case SCG_AUTHOR:
  79. return (_scg_auth_schily);
  80. case SCG_SCCS_ID:
  81. return (__sccsid);
  82. }
  83. }
  84. return ((char *)0);
  85. }
  86. EXPORT int
  87. scsi_open(scgp, device, busno, tgt, tlun)
  88. SCSI *scgp;
  89. char *device;
  90. int busno;
  91. int tgt;
  92. int tlun;
  93. {
  94. register int f;
  95. register int i;
  96. char devname[64];
  97. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  98. errno = EINVAL;
  99. if (scgp->errstr)
  100. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  101. "Illegal value for busno, target or lun '%d,%d,%d'",
  102. busno, tgt, tlun);
  103. return (-1);
  104. }
  105. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2)) {
  106. errno = EINVAL;
  107. if (scgp->errstr)
  108. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  109. "Open by 'devname' not supported on this OS");
  110. return (-1);
  111. }
  112. if (scgp->local == NULL) {
  113. scgp->local = malloc(sizeof(struct scg_local));
  114. if (scgp->local == NULL)
  115. return (0);
  116. scglocal(scgp)->scgfile = -1;
  117. scglocal(scgp)->max_scsibus = -1;
  118. scglocal(scgp)->cur_scsibus = -1;
  119. scglocal(scgp)->cur_target = -1;
  120. scglocal(scgp)->cur_lun = -1;
  121. }
  122. for (i=0; i < 4; i++) {
  123. sprintf(devname, "/dev/sg%d", i);
  124. f = open(devname, O_RDWR);
  125. if (scgp->debug)
  126. errmsg("open(devname: '%s') : %dn", devname, f);
  127. if (f < 0)
  128. continue;
  129. scglocal(scgp)->scgfile = f;
  130. break;
  131. }
  132. if (f >= 0) {
  133. if (scglocal(scgp)->max_scsibus < 0) {
  134. for (i=0; i < MAX_SCG; i++) {
  135. if (!scsi_havebus(scgp, i))
  136. break;
  137. }
  138. scglocal(scgp)->max_scsibus = i;
  139. }
  140. if (scgp->debug)
  141. printf("maxbus: %dn", scglocal(scgp)->max_scsibus);
  142. if (max_scsibus <= 0) {
  143. scglocal(scgp)->max_scsibus = 1;
  144. scglocal(scgp)->cur_scsibus = 0;
  145. }
  146.                 ioctl(f, SGIOCENAS);
  147. if (busno > 0 && tgt > 0 && tlun > 0)
  148. scsi_setup(scgp, busno, tgt, tlun, TRUE);
  149. return(1);
  150. }
  151. return (0);
  152. }
  153. EXPORT int
  154. scsi_close(scgp)
  155. SCSI *scgp;
  156. {
  157. if (scgp->local == NULL)
  158. return (-1);
  159. if (scglocal(scgp)->scgfile >= 0)
  160. close(scglocal(scgp)->scgfile);
  161. scglocal(scgp)->scgfile = -1;
  162. return (0);
  163. }
  164. LOCAL BOOL
  165. scsi_setup(scgp, busno, tgt, tlun, ex)
  166. SCSI *scgp;
  167. int busno;
  168. int tgt;
  169. int tlun;
  170. BOOL ex;
  171. {
  172. scsi_adr_t sadr;
  173. sadr.sa_target = tgt;
  174. sadr.sa_lun = tlun;
  175. if (scgp->debug)
  176. printf("scsi_setup curbus %d -> %dn", scglocal(scgp)->cur_scsibus, busno);
  177. if (scgp->debug && ((scglocal(scgp)->cur_scsibus < 0 || scglocal(scgp)->cur_scsibus != busno)))
  178. printf("setting SCSI bus to: %dn", busno); 
  179. if ((scglocal(scgp)->cur_scsibus < 0 || scglocal(scgp)->cur_scsibus != busno) &&
  180. ioctl(scglocal(scgp)->scgfile, SGIOCCNTR, &busno) < 0) {
  181. scglocal(scgp)->cur_scsibus = -1; /* Driver is in undefined state */
  182. if (ex)
  183. /* comerr("Cannot set SCSI busn");*/
  184. errmsg("Cannot set SCSI busn");
  185. return (FALSE);
  186. }
  187. scglocal(scgp)->cur_scsibus = busno;
  188. if (scgp->debug)
  189. printf("setting target/lun to: %d/%dn", tgt, tlun);
  190. if (ioctl(scglocal(scgp)->scgfile, SGIOCSTL, &sadr) < 0) {
  191. if (ex)
  192. comerr("Cannot set SCSI addressn");
  193. return (FALSE);
  194. }
  195. scglocal(scgp)->cur_scsibus = busno;
  196. scglocal(scgp)->cur_target = tgt;
  197. scglocal(scgp)->cur_lun = tlun;
  198. return (TRUE);
  199. }
  200. LOCAL long
  201. scsi_maxdma(scgp)
  202. SCSI *scgp;
  203. {
  204. long maxdma = MAX_DMA_NEXT;
  205. #ifdef SGIOCMAXDMA
  206. int  m;
  207. if (ioctl(scglocal(scgp)->scgfile, SGIOCMAXDMA, &m) >= 0)
  208. maxdma = m;
  209. if (scgp->debug)
  210. printf("maxdma: %dn", maxdma);
  211. #endif
  212. return (maxdma);
  213. }
  214. #ifdef XXX
  215. #define SGIOCENAS _IO(  's', 2)   /* enable autosense */
  216. #define SGIOCDAS _IO(  's', 3) /* disable autosense */
  217. #define SGIOCRST _IO(  's', 4) /* reset SCSI bus */
  218. #define SGIOCCNTR       _IOW( 's', 6, int)              /* select controller */
  219. #define SGIOCGAS _IOR( 's', 7, int) /* get autosense */
  220. #define SGIOCMAXDMA _IOR( 's', 8, int) /* max DMA size */
  221. #define SGIOCNUMTARGS _IOR( 's', 9, int) /* # of targets/bus */
  222. #endif
  223. EXPORT void *
  224. scsi_getbuf(scgp, amt)
  225. SCSI *scgp;
  226. long amt;
  227. {
  228. if (amt <= 0 || amt > scsi_maxdma(scgp))
  229. return ((void *)0);
  230. if (scgp->debug)
  231. printf("scsi_getbuf: %ld bytesn", amt);
  232. scgp->bufbase = valloc((size_t)(amt));
  233. return (scgp->bufbase);
  234. }
  235. EXPORT void
  236. scsi_freebuf(scgp)
  237. SCSI *scgp;
  238. {
  239. if (scgp->bufbase)
  240. free(scgp->bufbase);
  241. scgp->bufbase = NULL;
  242. }
  243. EXPORT
  244. BOOL scsi_havebus(scgp, busno)
  245. SCSI *scgp;
  246. int busno;
  247. {
  248. if (busno < 0 || busno >= MAX_SCG)
  249. return (FALSE);
  250. if (scglocal(scgp)->max_scsibus > 0 && busno >= scglocal(scgp)->max_scsibus)
  251. return (FALSE);
  252. if (scgp->local == NULL)
  253. return (FALSE);
  254. return (scsi_setup(scgp, busno, 0, 0, FALSE));
  255. }
  256. EXPORT
  257. int scsi_fileno(scgp, busno, tgt, tlun)
  258. SCSI *scgp;
  259. int busno;
  260. int tgt;
  261. int tlun;
  262. {
  263. if (busno < 0 || busno >= MAX_SCG ||
  264.     tgt < 0 || tgt >= MAX_TGT ||
  265.     tlun < 0 || tlun >= MAX_LUN)
  266. return (-1);
  267. if (scglocal(scgp)->max_scsibus > 0 && busno >= scglocal(scgp)->max_scsibus)
  268. return (-1);
  269. if (scgp->local == NULL)
  270. return (-1);
  271. if ((busno != scglocal(scgp)->cur_scsibus) || (tgt != scglocal(scgp)->cur_target) || (tlun != scglocal(scgp)->cur_lun)) {
  272. if (!scsi_setup(scgp, busno, tgt, tlun, FALSE))
  273. return (-1);
  274. }
  275. return (scglocal(scgp)->scgfile);
  276. }
  277. EXPORT int
  278. scsi_initiator_id(scgp)
  279. SCSI *scgp;
  280. {
  281. return (-1);
  282. }
  283. EXPORT
  284. int scsi_isatapi(scgp)
  285. SCSI *scgp;
  286. {
  287. return (FALSE);
  288. }
  289. EXPORT
  290. int scsireset(scgp)
  291. SCSI *scgp;
  292. {
  293. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  294. return (ioctl(f, SGIOCRST, 0));
  295. }
  296. LOCAL int
  297. scsi_send(scgp, f, sp)
  298. SCSI *scgp;
  299. int f;
  300. struct scg_cmd *sp;
  301. {
  302. struct scsi_req req;
  303. register long *lp1;
  304. register long *lp2;
  305. int ret = 0;
  306. if (f < 0 || (sp->cdb_len > sizeof(req.sr_cdb))) {
  307. sp->error = SCG_FATAL;
  308. sp->ux_errno = EIO;
  309. return (0);
  310. }
  311. fillbytes(&req, sizeof(req), '');
  312. movebytes(sp->cdb.cmd_cdb, &req.sr_cdb, sp->cdb_len);
  313. if (sp->size) {
  314. req.sr_dma_dir = SR_DMA_WR;
  315. if (sp->flags & SCG_RECV_DATA)
  316. req.sr_dma_dir = SR_DMA_RD;
  317. }
  318. req.sr_addr = sp->addr;
  319. req.sr_dma_max = sp->size;
  320. req.sr_ioto = sp->timeout;
  321. if (ioctl(f, SGIOCREQ, (void *)&req) < 0) {
  322. ret  = -1;
  323. sp->ux_errno = geterrno();
  324. if (sp->ux_errno != ENOTTY)
  325. ret = 0;
  326. } else {
  327. sp->ux_errno = 0;
  328. }
  329. if (scgp->debug) {
  330. printf("dma_dir:     %Xn", req.sr_dma_dir);
  331. printf("dma_addr:    %Xn", req.sr_addr);
  332. printf("io_time:     %dn", req.sr_ioto);
  333. printf("io_status:   %dn", req.sr_io_status);
  334. printf("scsi_status: %Xn", req.sr_scsi_status);
  335. printf("dma_xfer:    %dn", req.sr_dma_xfr);
  336. }
  337. sp->u_scb.cmd_scb[0] = req.sr_scsi_status;
  338. sp->sense_count = sizeof(esense_reply_t);
  339. if (sp->sense_count > sp->sense_len)
  340. sp->sense_count = sp->sense_len;
  341. if (sp->sense_count > SCG_MAX_SENSE)
  342. sp->sense_count = SCG_MAX_SENSE;
  343. if (sp->sense_count < 0)
  344. sp->sense_count = 0;
  345. movebytes(&req.sr_esense, sp->u_sense.cmd_sense, sp->sense_count);
  346. sp->resid = sp->size - req.sr_dma_xfr;
  347. switch (req.sr_io_status) {
  348. case SR_IOST_GOOD: sp->error = SCG_NO_ERROR; break;
  349. case SR_IOST_CHKSNV: sp->sense_count = 0;
  350. case SR_IOST_CHKSV: sp->error = SCG_RETRYABLE;
  351. break;
  352. case SR_IOST_SELTO:
  353. case SR_IOST_DMAOR:
  354. sp->error = SCG_FATAL; break;
  355. case SR_IOST_IOTO: sp->error = SCG_TIMEOUT; break;
  356. case SR_IOST_PERM:
  357. case SR_IOST_NOPEN:
  358. sp->error = SCG_FATAL;
  359. ret = (-1);
  360. break;
  361. default: sp->error = SCG_RETRYABLE; break;
  362. }
  363. return (ret);
  364. }