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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-sco.c 1.12 99/09/07 Copyright 1998 J. Schilling, Santa Cruz Operation */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-sco.c 1.12 99/09/07 Copyright 1998 J. Schilling, Santa Cruz Operation";
  5. #endif
  6. /*
  7.  * Interface for the SCO SCSI implementation.
  8.  *
  9.  * Copyright (c) 1998 J. Schilling, Santa Cruz Operation
  10.  */
  11. /*
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2, or (at your option)
  15.  * any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; see the file COPYING.  If not, write to
  24.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26. #undef sense
  27. #include <sys/scsicmd.h>
  28. #define MAX_SCG 16 /* Max # of cdrom devices */
  29. #define MAX_TGT 16 /* Not really needed      */
  30. #define MAX_LUN 8 /* Not really needed      */
  31. #define MAX_DMA (32*1024) /* Maybe even more ???    */
  32. struct scg_local {
  33. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  34. };
  35. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  36. LOCAL void cp_scg2sco __PR((struct scsicmd2 *sco, struct scg_cmd *scg));
  37. LOCAL void cp_sco2scg __PR((struct scsicmd2 *sco, struct scg_cmd *scg));
  38. /* -------------------------------------------------------------------------
  39. ** SCO OpenServer does not have a generic scsi device driver, which can
  40. ** be used to access any configured scsi device. 
  41. **
  42. ** But we can use the "Srom" scsi peripherial driver (for CD-ROM devices) 
  43. ** to send SCSIUSERCMD's to any target device controlled by the Srom driver,
  44. ** as we only want to communicate with a CD(-Writer) device, not with disks
  45. ** tapes etc.
  46. **
  47. ** The Srom driver hides all info like scsibus, target id and lun from the
  48. ** user, so we really don't need the information about this, just the
  49. ** name of the special device node to open this device for sending
  50. ** all SCSIUSERCMD's.
  51. **
  52. ** Therefore we can use the scsibus as the index into the special device
  53. ** nodes of all CD-ROM devices, as all CD-ROM devices have "/dev/rcdX" as 
  54. ** their device node, with X being the number of the CD-ROM device.
  55. **
  56. ** By default, if you installed from a CD-ROM device, you will have 
  57. ** a "/dev/rcd0" device. If you installed the CD-Writer as an additional
  58. ** device, you will need to use the appropiate number to access it.
  59. **
  60. ** The scsibus variable is used as the number of the /dev/rcd device to be 
  61. ** used for sending the userland commands to the cdrecorder device, as the 
  62. ** scsibus itself is hidden by the Srom driver (same as with target and lun).
  63. **
  64. ** Actually we would not need target and lun at all, as it is all hidden by 
  65. ** the Srom driver, but for God's sake we will take it to set the according
  66. ** scgfiles element.
  67. **
  68. ** For example: 
  69. ** 
  70. **   busno = 0  means
  71. **
  72. **   /dev/rcd0 is opened for sending cmds via the SCSIUSERCMD2 ioctl.
  73. **
  74. **
  75. ** The alternative method to specify the target device is to use the
  76. ** the full device name instead of the scsibus.
  77. **
  78. ** For example:
  79. **
  80. **  cdrecord dev=/dev/rcd0:5,0 
  81. **
  82. **  will also open /dev/rcd0 to access the CD-Writer.
  83. **
  84. **
  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. int f, b, t, l;
  95. int nopen = 0;
  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. for (b = 0; b < MAX_SCG; b++) {
  117. for (t = 0; t < MAX_TGT; t++) {
  118. for (l = 0; l < MAX_LUN ; l++)
  119. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  120. }
  121. }
  122. }
  123. sprintf(devname, "/dev/rcd%d", busno);
  124. device = devname;
  125. if (busno >= 0 && tgt >= 0 && tlun >= 0) {
  126. f = open(device, O_RDONLY);
  127. if (f < 0) {
  128. switch (errno) {
  129. case ENXIO:
  130. if (scgp->errstr)
  131. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  132. "No media in %s !n", device);
  133.             break;
  134. default   :
  135. if (scgp->errstr)
  136. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  137. "Cannot open '%s'.n", device);
  138. }
  139. return(-1);
  140. }
  141. scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
  142. nopen++;
  143. return(1);
  144. }
  145. return (nopen);
  146. }
  147. EXPORT int
  148. scsi_close(scgp)
  149. SCSI *scgp;
  150. {
  151. register int f;
  152. register int b;
  153. register int t;
  154. register int l;
  155. if (scgp->local == NULL)
  156. return (-1);
  157. for (b=0; b < MAX_SCG; b++) {
  158. for (t=0; t < MAX_TGT; t++) {
  159. for (l=0; l < MAX_LUN ; l++)
  160. f = scglocal(scgp)->scgfiles[b][t][l];
  161. if (f >= 0)
  162. close(f);
  163. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  164. }
  165. }
  166. return (0);
  167. }
  168. LOCAL long
  169. scsi_maxdma(scgp)
  170. SCSI *scgp;
  171. {
  172. return (MAX_DMA);
  173. }
  174. EXPORT void *
  175. scsi_getbuf(scgp, amt)
  176. SCSI *scgp;
  177. long amt;
  178. {
  179. if (amt <= 0 || amt > scsi_maxdma(scgp))
  180. return ((void *)0);
  181. if (scgp->debug)
  182. printf("scsi_getbuf: %ld bytesn", amt);
  183. scgp->bufbase = valloc((size_t)(amt));
  184. return (scgp->bufbase);
  185. }
  186. EXPORT void
  187. scsi_freebuf(scgp)
  188. SCSI *scgp;
  189. {
  190. if (scgp->bufbase)
  191. free(scgp->bufbase);
  192. scgp->bufbase = NULL;
  193. }
  194. EXPORT
  195. BOOL scsi_havebus(scgp, busno)
  196. SCSI *scgp;
  197. int busno;
  198. {
  199. register int t;
  200. register int l;
  201. if (busno < 0 || busno >= MAX_SCG)
  202. return (FALSE);
  203. if (scgp->local == NULL)
  204. return (FALSE);
  205. for (t=0; t < MAX_TGT; t++) {
  206. for (l=0; l < MAX_LUN ; l++)
  207. if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
  208. return (TRUE);
  209. }
  210. return (FALSE);
  211. }
  212. EXPORT
  213. int scsi_fileno(scgp, busno, tgt, tlun)
  214. SCSI *scgp;
  215. int busno;
  216. int tgt;
  217. int tlun;
  218. {
  219. if (busno < 0 || busno >= MAX_SCG ||
  220.     tgt < 0 || tgt >= MAX_TGT ||
  221.     tlun < 0 || tlun >= MAX_LUN)
  222. return (-1);
  223. if (scgp->local == NULL)
  224. return (-1);
  225. return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
  226. }
  227. EXPORT int
  228. scsi_initiator_id(scgp)
  229. SCSI *scgp;
  230. {
  231. return (-1);
  232. }
  233. EXPORT
  234. int scsi_isatapi(scgp)
  235. SCSI *scgp;
  236. {
  237. return (-1); /* There may be ATAPI support */
  238. }
  239. EXPORT
  240. int scsireset(scgp)
  241. SCSI *scgp;
  242. {
  243. return(-1); /* no scsi reset available */
  244. }
  245. LOCAL void
  246. cp_scg2sco(sco, scg)
  247. struct scsicmd2 *sco;
  248. struct scg_cmd *scg;
  249. {
  250. sco->cmd.data_ptr = (char *) scg->addr;
  251. sco->cmd.data_len = scg->size;
  252. sco->cmd.cdb_len  = scg->cdb_len;
  253. sco->sense_len    = scg->sense_len;
  254. sco->sense_ptr    = scg->u_sense.cmd_sense;
  255.     
  256. if (!(scg->flags & SCG_RECV_DATA) && (scg->size > 0))
  257. sco->cmd.is_write = 1;
  258. if (scg->cdb_len == SC_G0_CDBLEN )
  259. memcpy(sco->cmd.cdb, &scg->cdb.g0_cdb, scg->cdb_len);
  260. if (scg->cdb_len == SC_G1_CDBLEN )
  261. memcpy(sco->cmd.cdb, &scg->cdb.g1_cdb, scg->cdb_len);
  262. if (scg->cdb_len == SC_G5_CDBLEN )
  263. memcpy(sco->cmd.cdb, &scg->cdb.g5_cdb, scg->cdb_len);
  264. }
  265. LOCAL void
  266. cp_sco2scg(sco, scg)
  267. struct scsicmd2 *sco;
  268. struct scg_cmd *scg;
  269. {
  270. scg->size      = sco->cmd.data_len;
  271. memset(&scg->scb,               0, sizeof(scg->scb));
  272. if (sco->sense_len > SCG_MAX_SENSE)
  273. scg->sense_count = SCG_MAX_SENSE;
  274. else
  275. scg->sense_count = sco->sense_len;
  276. scg->resid = 0;
  277. scg->u_scb.cmd_scb[0] = sco->cmd.target_sts;
  278. }
  279. LOCAL int
  280. scsi_send(scgp, fd, sp)
  281. SCSI *scgp;
  282. int fd;
  283. struct scg_cmd *sp;
  284. {
  285. struct scsicmd2 scsi_cmd;
  286. int i;
  287. u_char sense_buf[SCG_MAX_SENSE];
  288. memset(&scsi_cmd, 0, sizeof(scsi_cmd));
  289. memset(sense_buf,  0, sizeof(sense_buf));
  290. scsi_cmd.sense_ptr = sense_buf;
  291. scsi_cmd.sense_len = sizeof(sense_buf);
  292. cp_scg2sco(&scsi_cmd, sp);
  293. errno = 0;
  294. for (;;) {
  295. int ioctlStatus;
  296. if ((ioctlStatus = ioctl(fd, SCSIUSERCMD2, &scsi_cmd)) < 0) {
  297. if (errno == EINTR)
  298. continue;
  299. cp_sco2scg(&scsi_cmd, sp);
  300. sp->ux_errno = errno;
  301. if (errno == 0)
  302. sp->ux_errno = EIO;
  303. sp->error    = SCG_RETRYABLE;
  304. return (0);
  305. }
  306. break;
  307. }
  308. cp_sco2scg(&scsi_cmd, sp);
  309. sp->ux_errno = errno;
  310. if (scsi_cmd.cmd.target_sts & 0x02) {
  311. if (errno == 0)
  312. sp->ux_errno = EIO;
  313. sp->error    = SCG_RETRYABLE;
  314. } else {
  315. sp->error    = SCG_NO_ERROR;
  316. }
  317. return 0;
  318. }
  319. #define sense u_sense.Sense