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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-vms.c 1.15 99/09/17 Copyright 1997 J. Schilling */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-vms.c 1.15 99/09/17 Copyright 1997 J. Schilling";
  5. #endif
  6. /*
  7.  * Interface for the VMS 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 <iodef.h>
  36. #include <ssdef.h>
  37. #include <descrip.h>
  38. #include <starlet.h>
  39. #include <string.h>
  40. #include <LIB$ROUTINES.H>
  41. /*
  42.  * Warning: you may change this source, but if you do that
  43.  * you need to change the _scg_version and _scg_auth* string below.
  44.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  45.  * Choose your name instead of "schily" and make clear that the version
  46.  * string is related to a modified source.
  47.  */
  48. LOCAL char _scg_trans_version[] = "scsi-vms.c-1.15"; /* The version for this transport*/
  49. #define MAX_SCG  16 /* Max # of SCSI controllers */
  50. #define MAX_TGT  16
  51. #define MAX_LUN  8
  52. #define MAX_DMA_VMS (96*512)/* Check if this is not too big */
  53. #define MAX_PHSTMO_VMS 300
  54. #define MAX_DSCTMO_VMS 65535 /* max value for OpenVMS/AXP 7.1 ehh*/
  55. LOCAL int do_scsi_cmd __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  56. LOCAL int do_scsi_sense __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  57. #define DEVICE_NAMELEN 7
  58. struct SCSI$DESC {
  59. Uint SCSI$L_OPCODE; /* SCSI Operation Code */
  60. Uint SCSI$L_FLAGS; /* SCSI Flags Bit Map */
  61. char *SCSI$A_CMD_ADDR; /* ->SCSI command buffer */
  62. Uint SCSI$L_CMD_LEN;  /* SCSI command length, bytes */
  63. char *SCSI$A_DATA_ADDR; /* ->SCSI data buffer */
  64. Uint SCSI$L_DATA_LEN; /* SCSI data length, bytes */
  65. Uint SCSI$L_PAD_LEN;  /* SCSI pad length, bytes */
  66. Uint SCSI$L_PH_CH_TMOUT; /* SCSI phase change timeout */
  67. Uint SCSI$L_DISCON_TMOUT; /* SCSI disconnect timeout */
  68. Uint SCSI$L_RES_1; /* Reserved */
  69. Uint SCSI$L_RES_2; /* Reserved */
  70. Uint SCSI$L_RES_3; /* Reserved */
  71. Uint SCSI$L_RES_4; /* Reserved */
  72. Uint SCSI$L_RES_5; /* Reserved */
  73. Uint SCSI$L_RES_6; /* Reserved */
  74. };
  75. #ifdef __ALPHA
  76. #pragma member_alignment save
  77. #pragma nomember_alignment
  78. #endif
  79. struct SCSI$IOSB {
  80. Ushort SCSI$W_VMS_STAT; /* VMS status code */
  81. Ulong SCSI$L_IOSB_TFR_CNT; /* Actual #bytes transferred */
  82. char SCSI$B_IOSB_FILL_1;
  83. Uchar SCSI$B_IOSB_STS; /* SCSI device status */
  84. };
  85. #ifdef __ALPHA
  86. #pragma member_alignment restore
  87. #endif
  88. #define SCSI$K_GOOD_STATUS 0
  89. #define SCSI$K_CHECK_CONDITION 0x2
  90. #define SCSI$K_CONDITION_MET 0x4
  91. #define SCSI$K_BUSY 0x8
  92. #define SCSI$K_INTERMEDIATE 0x10
  93. #define SCSI$K_INTERMEDIATE_C_MET 0x14
  94. #define SCSI$K_RESERVATION_CONFLICT 0x18
  95. #define SCSI$K_COMMAND_TERMINATED 0x22
  96. #define SCSI$K_QUEUE_FULL 0x28
  97. #define SCSI$K_WRITE 0X0 /* direction of transfer=write */
  98. #define SCSI$K_READ 0X1 /* direction of transfer=read */
  99. #define SCSI$K_FL_ENAB_DIS 0X2 /* enable disconnects */
  100. #define SCSI$K_FL_ENAB_SYNC 0X4 /* enable sync */
  101. #define GK_EFN 0 /* Event flag number */
  102. static char gk_device[8]; /* XXX JS hoffentlich gibt es keinen Ueberlauf */
  103. static Ushort gk_chan;
  104. static Ushort transfer_length;
  105. static int i;
  106. static int status;
  107. static $DESCRIPTOR(gk_device_desc, gk_device);
  108. static struct SCSI$IOSB gk_iosb ;
  109. static struct SCSI$DESC gk_desc;
  110. static FILE *fp;
  111. struct scg_local {
  112. Ushort gk_chan;
  113. };
  114. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  115. /*
  116.  * Return version information for the low level SCSI transport code.
  117.  * This has been introduced to make it easier to trace down problems
  118.  * in applications.
  119.  */
  120. EXPORT char *
  121. scg__version(scgp, what)
  122. SCSI *scgp;
  123. int what;
  124. {
  125. if (scgp != (SCSI *)0) {
  126. switch (what) {
  127. case SCG_VERSION:
  128. return (_scg_trans_version);
  129. /*
  130.  * If you changed this source, you are not allowed to
  131.  * return "schily" for the SCG_AUTHOR request.
  132.  */
  133. case SCG_AUTHOR:
  134. return (_scg_auth_schily);
  135. case SCG_SCCS_ID:
  136. return (__sccsid);
  137. }
  138. }
  139. return ((char *)0);
  140. }
  141. EXPORT int
  142. scsi_open(scgp, device, busno, tgt, tlun)
  143. SCSI *scgp;
  144. char *device;
  145. int busno;
  146. int tgt;
  147. int tlun;
  148. {
  149. char devname[DEVICE_NAMELEN];
  150. char buschar;
  151. char buschar1;
  152. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  153. errno = EINVAL;
  154. if (scgp->errstr)
  155. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  156. "Illegal value for busno, target or lun '%d,%d,%d'",
  157. busno, tgt, tlun);
  158. return (-1);
  159. }
  160. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2)) {
  161. errno = EINVAL;
  162. if (scgp->errstr)
  163. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  164. "Open by 'devname' not supported on this OS");
  165. return (-1);
  166. }
  167. if (scgp->local == NULL) {
  168. scgp->local = malloc(sizeof(struct scg_local));
  169. if (scgp->local == NULL)
  170. return (0);
  171. }
  172. switch (busno) {
  173. case 0: buschar = 'd';
  174. buschar1 = 'a';
  175. break;
  176. case 1: buschar = 'd';
  177. buschar1 = 'b';
  178. break;
  179. case 2: buschar = 'd';
  180. buschar1 = 'c';
  181. break;
  182. case 3: buschar = 'd';
  183. buschar1 = 'd';
  184. break;
  185. case 4: buschar = 'g';
  186. buschar1 = 'a';
  187. break;
  188. case 5: buschar = 'g';
  189. buschar1 = 'b';
  190. break;
  191. case 6: buschar = 'g';
  192. buschar1 = 'c';
  193. break;
  194. case 7: buschar = 'g';
  195. buschar1 = 'd';
  196. break;
  197. default :
  198. if (scgp->errstr)
  199. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  200. "Wrong scsibus-# (%d)", busno);
  201. return (-1);
  202. }
  203. /* XXX JS XXX devname length snprintf ??? */
  204. sprintf(devname, "%ck%c%d0%d:", buschar, buschar1, tgt, tlun);
  205. strcpy (gk_device, devname);
  206. status = sys$assign(&gk_device_desc, &gk_chan, 0, 0);
  207. if (!(status & 1)) {
  208. printf("Unable to access scsi-device "%s"n", &gk_device[0]);
  209. return (-1);
  210. }
  211. if (scgp->debug) {
  212. fp = fopen("cdrecord_io.log","w","rfm=stmlf","rat=cr");
  213. if (fp == NULL) {
  214. perror("Failing opening i/o-logfile");
  215. exit(SS$_NORMAL);
  216. }
  217. }
  218. return (status);
  219. }
  220. EXPORT int
  221. scsi_close(scgp)
  222. SCSI *scgp;
  223. {
  224. /*
  225.  * XXX close gk_chan ???
  226.  */
  227. return (0);
  228. }
  229. LOCAL long
  230. scsi_maxdma(scgp)
  231. SCSI *scgp;
  232. {
  233. return (MAX_DMA_VMS);
  234. }
  235. EXPORT
  236. BOOL scsi_havebus(scgp, busno)
  237. SCSI *scgp;
  238. int busno;
  239. {
  240. if (gk_chan <= 0)
  241. return (FALSE);
  242. return (TRUE);
  243. }
  244. EXPORT
  245. int scsi_fileno(scgp, busno, tgt, tlun)
  246. SCSI *scgp;
  247. int busno;
  248. int tgt;
  249. int tlun;
  250. {
  251. if (gk_chan <= 0)
  252. return (-1);
  253. return (gk_chan);
  254. }
  255. EXPORT int
  256. scsi_initiator_id(scgp)
  257. SCSI *scgp;
  258. {
  259. return (-1);
  260. }
  261. EXPORT
  262. int scsi_isatapi(scgp)
  263. SCSI *scgp;
  264. {
  265. return (FALSE);
  266. }
  267. EXPORT
  268. int scsireset(scgp)
  269. SCSI *scgp;
  270. {
  271. return (-1);
  272. }
  273. EXPORT void *
  274. scsi_getbuf(scgp, amt)
  275. SCSI *scgp;
  276. long amt;
  277. {
  278. if (amt <= 0 || amt > scsi_maxdma(scgp))
  279. return ((void *)0);
  280. if (scgp->debug)
  281. printf("scsi_getbuf: %ld bytesn", amt);
  282. scgp->bufbase = malloc((size_t)(amt)); /* XXX JS XXX valloc() ??? */
  283. return (scgp->bufbase);
  284. }
  285. EXPORT void
  286. scsi_freebuf(scgp)
  287. SCSI *scgp;
  288. {
  289. if (scgp->bufbase)
  290. free(scgp->bufbase);
  291. scgp->bufbase = NULL;
  292. }
  293. LOCAL int
  294. do_scsi_cmd(scgp, f, sp)
  295. SCSI *scgp;
  296. int f;
  297. struct scg_cmd *sp;
  298. {
  299. char *cmdadr;
  300. int notcmdretry;
  301. int len;
  302. int severity;
  303. /* XXX JS XXX This cannot be OK */
  304. notcmdretry = (sp->flags & SCG_CMD_RETRY)^SCG_CMD_RETRY;
  305. /* error corrected ehh */
  306. /* XXX JS Wenn das notcmdretry Flag bei VMS auch 0x08 ist und Du darauf hoffst,
  307.    XXX Dasz ich den Wert nie aendere, dann ist das richtig.
  308.    XXX Siehe unten: Das gleiche gilt fuer SCG_RECV_DATA und SCG_DISRE_ENA !!!
  309. */
  310. cmdadr = (char *)sp->cdb.cmd_cdb;
  311. /* XXX JS XXX This cannot be OK */
  312. gk_desc.SCSI$L_FLAGS = ((sp->flags & SCG_RECV_DATA) |
  313. (sp->flags & SCG_DISRE_ENA)|
  314. notcmdretry);
  315. /* XXX siehe oben, das ist ein bitweises oder!!! */
  316. gk_desc.SCSI$A_DATA_ADDR = sp->addr;
  317. gk_desc.SCSI$L_DATA_LEN = sp->size;
  318. gk_desc.SCSI$A_CMD_ADDR = cmdadr;
  319. gk_desc.SCSI$L_CMD_LEN = sp->cdb_len;
  320. gk_desc.SCSI$L_PH_CH_TMOUT = sp->timeout;
  321. gk_desc.SCSI$L_DISCON_TMOUT = sp->timeout;
  322.         if (gk_desc.SCSI$L_PH_CH_TMOUT > MAX_PHSTMO_VMS)
  323.             gk_desc.SCSI$L_PH_CH_TMOUT = MAX_PHSTMO_VMS;
  324.         if (gk_desc.SCSI$L_DISCON_TMOUT > MAX_DSCTMO_VMS)
  325.             gk_desc.SCSI$L_DISCON_TMOUT = MAX_DSCTMO_VMS;
  326. gk_desc.SCSI$L_OPCODE = 1; /* SCSI Operation Code */
  327. gk_desc.SCSI$L_PAD_LEN = 0; /* SCSI pad length, bytes */
  328. gk_desc.SCSI$L_RES_1 = 0; /* Reserved */
  329. gk_desc.SCSI$L_RES_2 = 0; /* Reserved */
  330. gk_desc.SCSI$L_RES_3 = 0; /* Reserved */
  331. gk_desc.SCSI$L_RES_4 = 0; /* Reserved */
  332. gk_desc.SCSI$L_RES_5 = 0; /* Reserved */
  333. gk_desc.SCSI$L_RES_6 = 0; /* Reserved */
  334. if (scgp->debug) {
  335. fprintf(fp, "***********************************************************n");
  336. fprintf(fp, "SCSI VMS-I/O parametersn");
  337. fprintf(fp, "OPCODE: %d", gk_desc.SCSI$L_OPCODE);
  338. fprintf(fp, " FLAGS: %dn", gk_desc.SCSI$L_FLAGS);
  339. fprintf(fp, "CMD:");
  340. for (i = 0; i < gk_desc.SCSI$L_CMD_LEN; i++) {
  341. fprintf(fp, "%x ", sp->cdb.cmd_cdb[i]);
  342. }
  343. fprintf(fp, "n");
  344. fprintf(fp, "DATA_LEN: %dn", gk_desc.SCSI$L_DATA_LEN);
  345. fprintf(fp, "PH_CH_TMOUT: %d", gk_desc.SCSI$L_PH_CH_TMOUT);
  346. fprintf(fp, " DISCON_TMOUT: %dn", gk_desc.SCSI$L_DISCON_TMOUT);
  347. }
  348. status = sys$qiow(GK_EFN, gk_chan, IO$_DIAGNOSE, &gk_iosb, 0, 0,
  349. &gk_desc, sizeof(gk_desc), 0, 0, 0, 0);
  350. if (scgp->debug) {
  351. fprintf(fp, "qiow-status: %in", status);
  352. fprintf(fp, "VMS status code %in",gk_iosb.SCSI$W_VMS_STAT);
  353. fprintf(fp, "Actual #bytes transferred %in",gk_iosb.SCSI$L_IOSB_TFR_CNT);
  354. fprintf(fp, "SCSI device status %in",gk_iosb.SCSI$B_IOSB_STS);
  355. if (gk_iosb.SCSI$L_IOSB_TFR_CNT != gk_desc.SCSI$L_DATA_LEN) {
  356. fprintf(fp,"#bytes transferred != DATA_LENn");
  357. }
  358. }
  359. if (!(status & 1)) { /* Fehlerindikation fuer sys$qiow() */
  360. sp->ux_errno = geterrno();
  361. /* schwerwiegender nicht SCSI bedingter Fehler => return(-1) */
  362. if (sp->ux_errno == ENOTTY || sp->ux_errno == ENXIO ||
  363.     sp->ux_errno == EINVAL || sp->ux_errno == EACCES) {
  364. return (-1);
  365. }
  366. } else {
  367. sp->ux_errno = 0;
  368. }
  369. sp->resid = gk_desc.SCSI$L_DATA_LEN - gk_iosb.SCSI$L_IOSB_TFR_CNT;
  370. if (gk_iosb.SCSI$W_VMS_STAT == SS$_NORMAL &&
  371.     gk_iosb.SCSI$B_IOSB_STS == 0) {
  372. sp->error = SCG_NO_ERROR;
  373. if (scgp->debug) {
  374. fprintf(fp,"gk_iosb.SCSI$B_IOSB_STS == 0n");
  375. fprintf(fp,"sp->error %in",sp->error);
  376. fprintf(fp,"sp->resid %in",sp->resid);
  377. }
  378. return(0);
  379. }
  380. severity = gk_iosb.SCSI$W_VMS_STAT & 0x7;
  381. if (severity == 4) {
  382. sp->error = SCG_FATAL;
  383. if (scgp->debug) {
  384. fprintf(fp,"gk_iosb.SCSI$B_IOSB_STS & 2n");
  385. fprintf(fp,"gk_iosb.SCSI$W_VMS_STAT & 0x7 == SS$_FATALn");
  386. fprintf(fp,"sp->error %in",sp->error);
  387. }
  388. return (0);
  389. }
  390. if (gk_iosb.SCSI$W_VMS_STAT == SS$_TIMEOUT) {
  391. sp->error = SCG_TIMEOUT;
  392. if (scgp->debug) {
  393. fprintf(fp,"gk_iosb.SCSI$B_IOSB_STS & 2n");
  394. fprintf(fp,"gk_iosb.SCSI$W_VMS_STAT == SS$_TIMEOUTn");
  395. fprintf(fp,"sp->error %in",sp->error);
  396. }
  397. return (0);
  398. }
  399. sp->error = SCG_RETRYABLE;
  400. sp->ux_errno = EIO;
  401. sp->u_scb.cmd_scb[0] = gk_iosb.SCSI$B_IOSB_STS;
  402. if (scgp->debug) {
  403. fprintf(fp,"gk_iosb.SCSI$B_IOSB_STS & 2n");
  404. fprintf(fp,"gk_iosb.SCSI$W_VMS_STAT != 0n");
  405. fprintf(fp,"sp->error %in",sp->error);
  406. }
  407. return(0);
  408. }
  409. LOCAL int
  410. do_scsi_sense(scgp, f, sp)
  411. SCSI *scgp;
  412. int f;
  413. struct scg_cmd *sp;
  414. {
  415. int ret;
  416. struct scg_cmd s_cmd;
  417. if (sp->sense_len > SCG_MAX_SENSE)
  418. sp->sense_len = SCG_MAX_SENSE;
  419. fillbytes((caddr_t)&s_cmd, sizeof(s_cmd), '');
  420. s_cmd.addr = (char *)sp->u_sense.cmd_sense;
  421. s_cmd.size = sp->sense_len;
  422. s_cmd.flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  423. s_cmd.cdb_len = SC_G0_CDBLEN;
  424. s_cmd.sense_len = CCS_SENSE_LEN;
  425. s_cmd.target = scgp->target;
  426. s_cmd.cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
  427. s_cmd.cdb.g0_cdb.lun = sp->cdb.g0_cdb.lun;
  428. s_cmd.cdb.g0_cdb.count = sp->sense_len;
  429. ret = do_scsi_cmd(scgp, f, &s_cmd);
  430. if (ret < 0)
  431. return (ret);
  432. if (s_cmd.u_scb.cmd_scb[0] & 02) {
  433. /* XXX ??? Check condition on request Sense ??? */
  434. }
  435. sp->sense_count = sp->sense_len - s_cmd.resid;
  436. return (ret);
  437. }
  438. LOCAL int
  439. scsi_send(scgp, f, sp)
  440. SCSI *scgp;
  441. int f;
  442. struct scg_cmd *sp;
  443. {
  444. int ret;
  445. if (f < 0) {
  446. sp->error = SCG_FATAL;
  447. return (0);
  448. }
  449. ret = do_scsi_cmd(scgp, f, sp);
  450. if (ret < 0)
  451. return (ret);
  452. if (sp->u_scb.cmd_scb[0] & 02)
  453. ret = do_scsi_sense(scgp, f, sp);
  454. return (ret);
  455. }