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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-osf.c 1.12 99/10/15 Copyright 1998 J. Schilling */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-osf.c 1.12 99/10/15 Copyright 1998 J. Schilling";
  5. #endif
  6. /*
  7.  * Interface for Digital UNIX (OSF/1 generic SCSI implementation (/dev/cam).
  8.  *
  9.  * Created out of the hacks from:
  10.  * Stefan Traby <stefan@sime.com> and
  11.  * Bruno Achauer <bruno@tk.uni-linz.ac.at>
  12.  *
  13.  * Warning: you may change this source, but if you do that
  14.  * you need to change the _scg_version and _scg_auth* string below.
  15.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  16.  * Choose your name instead of "schily" and make clear that the version
  17.  * string is related to a modified source.
  18.  *
  19.  * Copyright (c) 1998 J. Schilling
  20.  */
  21. /*
  22.  * This program is free software; you can redistribute it and/or modify
  23.  * it under the terms of the GNU General Public License as published by
  24.  * the Free Software Foundation; either version 2, or (at your option)
  25.  * any later version.
  26.  *
  27.  * This program is distributed in the hope that it will be useful,
  28.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30.  * GNU General Public License for more details.
  31.  *
  32.  * You should have received a copy of the GNU General Public License
  33.  * along with this program; see the file COPYING.  If not, write to
  34.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  35.  */
  36. #include <sys/types.h>
  37. #include <io/common/iotypes.h>
  38. #include <io/cam/cam.h>
  39. #include <io/cam/uagt.h> 
  40. /*
  41.  * Warning: you may change this source, but if you do that
  42.  * you need to change the _scg_version and _scg_auth* string below.
  43.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  44.  * Choose your name instead of "schily" and make clear that the version
  45.  * string is related to a modified source.
  46.  */
  47. LOCAL char _scg_trans_version[] = "scsi-osf.c-1.12"; /* The version for this transport*/
  48. #define MAX_SCG 16 /* Max # of SCSI controllers */
  49. #define MAX_TGT 16
  50. #define MAX_LUN 8
  51. struct scg_local {
  52. int scgfile; /* Used for ioctl() */
  53. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  54. };
  55. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  56. LOCAL BOOL scsi_checktgt __PR((SCSI *scgp, int f, int busno, int tgt, int tlun));
  57. /*
  58.  * I don't have any documentation about CAM
  59.  */
  60. #define MAX_DMA_OSF_CAM (64*1024)
  61. #ifndef AUTO_SENSE_LEN
  62. # define AUTO_SENSE_LEN 32 /* SCG_MAX_SENSE */
  63. #endif
  64. /*
  65.  * Return version information for the low level SCSI transport code.
  66.  * This has been introduced to make it easier to trace down problems
  67.  * in applications.
  68.  */
  69. EXPORT char *
  70. scg__version(scgp, what)
  71. SCSI *scgp;
  72. int what;
  73. {
  74. if (scgp != (SCSI *)0) {
  75. switch (what) {
  76. case SCG_VERSION:
  77. return (_scg_trans_version);
  78. /*
  79.  * If you changed this source, you are not allowed to
  80.  * return "schily" for the SCG_AUTHOR request.
  81.  */
  82. case SCG_AUTHOR:
  83. return (_scg_auth_schily);
  84. case SCG_SCCS_ID:
  85. return (__sccsid);
  86. }
  87. }
  88. return ((char *)0);
  89. }
  90. EXPORT int
  91. scsi_open(scgp, device, busno, tgt, tlun)
  92. SCSI *scgp;
  93. char *device;
  94. int busno;
  95. int tgt;
  96. int tlun;
  97. {
  98. register int b;
  99. register int t;
  100. register int l;
  101. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  102. errno = EINVAL;
  103. if (scgp->errstr)
  104. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  105. "Illegal value for busno, target or lun '%d,%d,%d'",
  106. busno, tgt, tlun);
  107. return (-1);
  108. }
  109. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2)) {
  110. errno = EINVAL;
  111. if (scgp->errstr)
  112. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  113. "Open by 'devname' not supported on this OS");
  114. return (-1);
  115. }
  116. if (scgp->local == NULL) {
  117. scgp->local = malloc(sizeof(struct scg_local));
  118. if (scgp->local == NULL)
  119. return (0);
  120. scglocal(scgp)->scgfile = -1;
  121. for (b=0; b < MAX_SCG; b++) {
  122. for (t=0; t < MAX_TGT; t++) {
  123. for (l=0; l < MAX_LUN ; l++)
  124. scglocal(scgp)->scgfiles[b][t][l] = 0;
  125. }
  126. }
  127. }
  128. if (scglocal(scgp)->scgfile != -1) /* multiple opens ??? */
  129. return (1); /* not yet ready .... */
  130. if ((scglocal(scgp)->scgfile = open("/dev/cam", O_RDWR, 0)) < 0) {
  131. if (scgp->errstr)
  132. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  133. "Cannot open '/dev/cam'");
  134. return (-1);
  135. }
  136. if (busno >= 0 && tgt >= 0 && tlun >= 0) {
  137. /* scsi_checktgt() ??? */
  138. for (l=0; l < MAX_LUN ; l++)
  139. scglocal(scgp)->scgfiles[b][t][l] = 1;
  140. return (1);
  141. }
  142. /*
  143.  * There seems to be no clean way to check whether
  144.  * a SCSI bus is present in the current system.
  145.  * scsi_checktgt() is used as a workaround for this problem.
  146.  */
  147. for (b=0; b < MAX_SCG; b++) {
  148. for (t=0; t < MAX_TGT; t++) {
  149. if (scsi_checktgt(scgp, scglocal(scgp)->scgfile, b, t, 0)) {
  150. for (l=0; l < MAX_LUN ; l++)
  151. scglocal(scgp)->scgfiles[b][t][l] = 1;
  152. /*
  153.  * Found a target on this bus.
  154.  * Comment the 'break' for a complete scan.
  155.  */
  156. break;
  157. }
  158. }
  159. }
  160. return (1);
  161. }
  162. EXPORT int
  163. scsi_close(scgp)
  164. SCSI *scgp;
  165. {
  166. if (scgp->local == NULL)
  167. return (-1);
  168. if (scglocal(scgp)->scgfile >= 0)
  169. close(scglocal(scgp)->scgfile);
  170. scglocal(scgp)->scgfile = -1;
  171. return (0);
  172. }
  173. /*
  174.  * We send a test unit ready command to the target to check whether the
  175.  * OS is considering this target to be valid.
  176.  */
  177. LOCAL BOOL
  178. scsi_checktgt(scgp, f, busno, tgt, tlun)
  179. SCSI *scgp;
  180. int f;
  181. int busno;
  182. int tgt;
  183. int tlun;
  184. {
  185. struct scg_cmd sc;
  186. int obus = scgp->scsibus;
  187. int otgt = scgp->target;
  188. int olun = scgp->lun;
  189. scgp->scsibus = busno;
  190. scgp->target  = tgt;
  191. scgp->lun     = tlun;
  192. fillbytes((caddr_t)&sc, sizeof(sc), '');
  193. sc.addr = (caddr_t)0;
  194. sc.size = 0;
  195. sc.flags = SCG_DISRE_ENA | SCG_SILENT;
  196. sc.cdb_len = SC_G0_CDBLEN;
  197. sc.sense_len = CCS_SENSE_LEN;
  198. sc.target = scgp->target;
  199. sc.cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
  200. sc.cdb.g0_cdb.lun = scgp->lun;
  201. scsi_send(scgp, f, &sc);
  202. scgp->scsibus = obus;
  203. scgp->target  = otgt;
  204. scgp->lun     = olun;
  205. if (sc.error != SCG_FATAL)
  206. return (TRUE);
  207. return (sc.ux_errno != EINVAL);
  208. }
  209. LOCAL long
  210. scsi_maxdma(scgp)
  211. SCSI *scgp;
  212. {
  213. long maxdma = MAX_DMA_OSF_CAM;
  214. return (maxdma);
  215. }
  216. EXPORT void *
  217. scsi_getbuf(scgp, amt)
  218. SCSI *scgp;
  219. long amt;
  220. {
  221. if (amt <= 0 || amt > scsi_maxdma(scgp))
  222. return ((void *)0);
  223. if (scgp->debug)
  224. printf("scsi_getbuf: %ld bytesn", amt);
  225. scgp->bufbase = valloc((size_t)(amt));
  226. return (scgp->bufbase);
  227. }
  228. EXPORT void
  229. scsi_freebuf(scgp)
  230. SCSI *scgp;
  231. {
  232. if (scgp->bufbase)
  233. free(scgp->bufbase);
  234. scgp->bufbase = NULL;
  235. }
  236. EXPORT
  237. BOOL scsi_havebus(scgp, busno)
  238. SCSI *scgp;
  239. int busno;
  240. {
  241. register int t;
  242. if (busno < 0 || busno >= MAX_SCG)
  243. return (FALSE);
  244. if (scgp->local == NULL)
  245. return (FALSE);
  246. for (t=0; t < MAX_TGT; t++) {
  247. if (scglocal(scgp)->scgfiles[busno][t][0] != 0)
  248. return (TRUE);
  249. }
  250. return (FALSE);
  251. }
  252. EXPORT
  253. int scsi_fileno(scgp, busno, tgt, tlun)
  254. SCSI *scgp;
  255. int busno;
  256. int tgt;
  257. int tlun;
  258. {
  259. if (scgp->local == NULL)
  260. return (-1);
  261. return (busno < 0 || busno >= MAX_SCG) ? -1 : scglocal(scgp)->scgfile;
  262. }
  263. EXPORT int
  264. scsi_initiator_id(scgp)
  265. SCSI *scgp;
  266. {
  267. return (-1);
  268. }
  269. EXPORT
  270. int scsi_isatapi(scgp)
  271. SCSI *scgp;
  272. {
  273. return (FALSE);
  274. }
  275. EXPORT
  276. int scsireset(scgp)
  277. SCSI *scgp;
  278. {
  279. #ifdef XXX
  280. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  281. return (ioctl(f, SCGIORESET, 0));
  282. #else
  283. return (-1);
  284. #endif
  285. }
  286. LOCAL int
  287. scsi_send(scgp, f, sp)
  288. SCSI *scgp;
  289. int f;
  290. struct scg_cmd *sp;
  291. {
  292. CCB_SCSIIO ccb;
  293. UAGT_CAM_CCB ua;
  294. unsigned char  *cdb;
  295. CCB_RELSIM relsim;
  296. UAGT_CAM_CCB relua;
  297. int             i;
  298. if (f < 0) {
  299. sp->error = SCG_FATAL;
  300. return (0);
  301. }
  302. fillbytes(&ua, sizeof(UAGT_CAM_CCB), 0);
  303. fillbytes(&ccb, sizeof(CCB_SCSIIO), 0);
  304. ua.uagt_ccb = (CCB_HEADER *) &ccb;
  305. ua.uagt_ccblen = sizeof(CCB_SCSIIO);
  306. ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb;
  307. ccb.cam_ch.cam_ccb_len = sizeof(CCB_SCSIIO);
  308. ua.uagt_snsbuf = ccb.cam_sense_ptr = sp->u_sense.cmd_sense;
  309. ua.uagt_snslen = ccb.cam_sense_len = AUTO_SENSE_LEN;
  310. cdb = (unsigned char *) ccb.cam_cdb_io.cam_cdb_bytes;
  311. ccb.cam_timeout = sp->timeout;
  312. ccb.cam_data_ptr = ua.uagt_buffer = (u_char *) sp->addr;
  313. ccb.cam_dxfer_len = ua.uagt_buflen = sp->size;
  314. ccb.cam_ch.cam_func_code = XPT_SCSI_IO;
  315. ccb.cam_ch.cam_flags = 0; /* CAM_DIS_CALLBACK; */
  316. if (sp->size == 0) {
  317. ccb.cam_data_ptr = ua.uagt_buffer = (u_char *) NULL;
  318. ccb.cam_ch.cam_flags |= CAM_DIR_NONE;
  319. } else {
  320. if (sp->flags & SCG_RECV_DATA) {
  321. ccb.cam_ch.cam_flags |= CAM_DIR_IN;
  322. } else {
  323. ccb.cam_ch.cam_flags |= CAM_DIR_OUT;
  324. }
  325. }
  326. ccb.cam_cdb_len = sp->cdb_len;
  327. for (i = 0; i < sp->cdb_len; i++)
  328. cdb[i] = sp->cdb.cmd_cdb[i];
  329. ccb.cam_ch.cam_path_id   = scgp->scsibus;
  330. ccb.cam_ch.cam_target_id  = scgp->target;
  331. ccb.cam_ch.cam_target_lun = scgp->lun;
  332. sp->sense_count = 0;
  333. sp->ux_errno = 0;
  334. sp->error = SCG_NO_ERROR;
  335. if (ioctl(f, UAGT_CAM_IO, (caddr_t) &ua) < 0) {
  336. sp->ux_errno = geterrno();
  337. sp->error = SCG_FATAL;
  338. if (scgp->debug) {
  339. errmsg("ioctl(f, UAGT_CAM_IO, dev=%d,%d,%d) failed.n",
  340. scgp->scsibus, scgp->target, scgp->lun);
  341. }
  342. return (0);
  343. }
  344. if (scgp->debug) {
  345. errmsgno(EX_BAD, "cam_status = 0x%.2X dev=%d,%d,%dn",
  346. ccb.cam_ch.cam_status,
  347. scgp->scsibus, scgp->target, scgp->lun);
  348. fflush(stderr);
  349. }
  350. switch (ccb.cam_ch.cam_status & CAM_STATUS_MASK) {
  351. case CAM_REQ_CMP: break;
  352. case CAM_SEL_TIMEOUT: sp->error = SCG_FATAL;
  353. sp->ux_errno = EIO;
  354. break;
  355. case CAM_CMD_TIMEOUT: sp->error = SCG_TIMEOUT;
  356. sp->ux_errno = EIO;
  357. break;
  358. default: sp->error = SCG_RETRYABLE;
  359. sp->ux_errno = EIO;
  360. break;
  361. }
  362. sp->u_scb.cmd_scb[0] = ccb.cam_scsi_status;
  363. if (ccb.cam_ch.cam_status & CAM_AUTOSNS_VALID) {
  364. sp->sense_count = MIN(ccb.cam_sense_len - ccb.cam_sense_resid,
  365. SCG_MAX_SENSE);
  366. sp->sense_count = MIN(sp->sense_count, sp->sense_len);
  367. if (sp->sense_len < 0)
  368. sp->sense_count = 0;
  369. }
  370. sp->resid = ccb.cam_resid;
  371. /*
  372.  * this is perfectly wrong.
  373.  * But without this, we hang...
  374.  */
  375. if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN) {
  376. fillbytes(&relsim, sizeof(CCB_RELSIM), 0);
  377. relsim.cam_ch.cam_ccb_len = sizeof(CCB_SCSIIO);
  378. relsim.cam_ch.cam_func_code = XPT_REL_SIMQ;
  379. relsim.cam_ch.cam_flags = CAM_DIR_IN | CAM_DIS_CALLBACK;
  380. relsim.cam_ch.cam_path_id = scgp->scsibus;
  381. relsim.cam_ch.cam_target_id = scgp->target;
  382. relsim.cam_ch.cam_target_lun = scgp->lun;
  383. relua.uagt_ccb = (struct ccb_header *) & relsim; /* wrong cast */
  384. relua.uagt_ccblen = sizeof(relsim);
  385. relua.uagt_buffer = NULL;
  386. relua.uagt_buflen = 0;
  387. if (ioctl(f, UAGT_CAM_IO, (caddr_t) & relua) < 0)
  388. errmsg("DEC CAM -> LMAn");
  389. }
  390. return 0;
  391. }