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

SCSI/ASPI

开发平台:

MultiPlatform

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