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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-aix.c 1.17 99/09/07 Copyright 1997 J. Schilling */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-aix.c 1.17 99/09/07 Copyright 1997 J. Schilling";
  5. #endif
  6. /*
  7.  * Interface for the AIX generic SCSI implementation.
  8.  *
  9.  * This is a hack, that tries to emulate the functionality
  10.  * of the scg driver.
  11.  *
  12.  * Copyright (c) 1997 J. Schilling
  13.  */
  14. /*
  15.  * This program is free software; you can redistribute it and/or modify
  16.  * it under the terms of the GNU General Public License as published by
  17.  * the Free Software Foundation; either version 2, or (at your option)
  18.  * any later version.
  19.  *
  20.  * This program is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU General Public License for more details.
  24.  *
  25.  * You should have received a copy of the GNU General Public License
  26.  * along with this program; see the file COPYING.  If not, write to
  27.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  28.  */
  29. #include <sys/scdisk.h>
  30. #define MAX_SCG 16 /* Max # of SCSI controllers */
  31. #define MAX_TGT 16
  32. #define MAX_LUN 8
  33. struct scg_local {
  34. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  35. };
  36. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  37. #define MAX_DMA_AIX (64*1024)
  38. LOCAL int do_scsi_cmd __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  39. LOCAL int do_scsi_sense __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  40. EXPORT int
  41. scsi_open(scgp, device, busno, tgt, tlun)
  42. SCSI *scgp;
  43. char *device;
  44. int busno;
  45. int tgt;
  46. int tlun;
  47. {
  48. register int f;
  49. register int b;
  50. register int t;
  51. register int l;
  52. register int nopen = 0;
  53. char devname[32];
  54. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  55. errno = EINVAL;
  56. if (scgp->errstr)
  57. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  58. "Illegal value for busno, target or lun '%d,%d,%d'",
  59. busno, tgt, tlun);
  60. return (-1);
  61. }
  62. if (scgp->local == NULL) {
  63. scgp->local = malloc(sizeof(struct scg_local));
  64. if (scgp->local == NULL)
  65. return (0);
  66. for (b=0; b < MAX_SCG; b++) {
  67. for (t=0; t < MAX_TGT; t++) {
  68. for (l=0; l < MAX_LUN ; l++)
  69. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  70. }
  71. }
  72. }
  73. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2)) {
  74. goto openbydev;
  75. if (busno >= 0 && tgt >= 0 && tlun >= 0) {
  76. sprintf(devname, "/dev/rcd%d", tgt);
  77. f = openx(devname, 0, 0, SC_DIAGNOSTIC);
  78. if (f < 0) {
  79. if (scgp->errstr)
  80. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  81. "Cannot open '%s'. Specify device number (1 for cd1) as target (1,0)",
  82. devname);
  83. return (0);
  84. }
  85. scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
  86. return 1;
  87. } else {
  88. if (scgp->errstr)
  89. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  90. "Unable to scan on AIX");
  91. return (0);
  92. }
  93. openbydev:
  94. if (device != NULL && *device != '' && busno >= 0 && tgt >= 0 && tlun >= 0) {
  95. f = openx(device, 0, 0, SC_DIAGNOSTIC);
  96. if (f < 0) {
  97. if (scgp->errstr)
  98. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  99. "Cannot open '%s'",
  100. devname);
  101. return (0);
  102. }
  103. scgp->scsibus = busno;
  104. scgp->target = tgt;
  105. scgp->lun = tlun;
  106. scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
  107. return (++nopen);
  108. }
  109. return (nopen);
  110. }
  111. EXPORT int
  112. scsi_close(scgp)
  113. SCSI *scgp;
  114. {
  115. register int f;
  116. register int b;
  117. register int t;
  118. register int l;
  119. if (scgp->local == NULL)
  120. return (-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. f = scglocal(scgp)->scgfiles[b][t][l];
  125. if (f >= 0)
  126. close(f);
  127. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  128. }
  129. }
  130. return (0);
  131. }
  132. LOCAL long
  133. scsi_maxdma(scgp)
  134. SCSI *scgp;
  135. {
  136. return (MAX_DMA_AIX);
  137. }
  138. #define palign(x, a) (((char *)(x)) + ((a) - 1 - (((unsigned)((x)-1))%(a))))
  139. EXPORT void *
  140. scsi_getbuf(scgp, amt)
  141. SCSI *scgp;
  142. long amt;
  143. {
  144. void *ret;
  145. int pagesize;
  146. #ifdef _SC_PAGESIZE
  147. pagesize = sysconf(_SC_PAGESIZE);
  148. #else
  149. pagesize = getpagesize();
  150. #endif
  151. if (amt <= 0 || amt > scsi_maxdma(scgp))
  152. return ((void *)0);
  153. if (scgp->debug)
  154. printf("scsi_getbuf: %ld bytesn", amt);
  155. /*
  156.  * Damn AIX is a paged system but has no valloc()
  157.  */
  158. scgp->bufbase = ret = malloc((size_t)(amt+pagesize));
  159. if (ret == NULL)
  160. return (ret);
  161. ret = palign(ret, pagesize);
  162. return (ret);
  163. }
  164. EXPORT void
  165. scsi_freebuf(scgp)
  166. SCSI *scgp;
  167. {
  168. if (scgp->bufbase)
  169. free(scgp->bufbase);
  170. scgp->bufbase = NULL;
  171. }
  172. EXPORT
  173. BOOL scsi_havebus(scgp, busno)
  174. SCSI *scgp;
  175. int busno;
  176. {
  177. register int t;
  178. register int l;
  179. if (busno < 0 || busno >= MAX_SCG)
  180. return (FALSE);
  181. if (scgp->local == NULL)
  182. return (FALSE);
  183. for (t=0; t < MAX_TGT; t++) {
  184. for (l=0; l < MAX_LUN ; l++)
  185. if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
  186. return (TRUE);
  187. }
  188. return (FALSE);
  189. }
  190. EXPORT
  191. int scsi_fileno(scgp, busno, tgt, tlun)
  192. SCSI *scgp;
  193. int busno;
  194. int tgt;
  195. int tlun;
  196. {
  197. if (busno < 0 || busno >= MAX_SCG ||
  198.     tgt < 0 || tgt >= MAX_TGT ||
  199.     tlun < 0 || tlun >= MAX_LUN)
  200. return (-1);
  201. if (scgp->local == NULL)
  202. return (-1);
  203. return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
  204. }
  205. EXPORT int
  206. scsi_initiator_id(scgp)
  207. SCSI *scgp;
  208. {
  209. return (-1);
  210. }
  211. EXPORT
  212. int scsi_isatapi(scgp)
  213. SCSI *scgp;
  214. {
  215. return (FALSE);
  216. }
  217. EXPORT
  218. int scsireset(scgp)
  219. SCSI *scgp;
  220. {
  221. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  222. return (ioctl(f, SCIORESET, IDLUN(scgp->target, scgp->lun)));
  223. }
  224. LOCAL int
  225. do_scsi_cmd(scgp, f, sp)
  226. SCSI *scgp;
  227. int f;
  228. struct scg_cmd *sp;
  229. {
  230. struct sc_iocmd req;
  231. int ret;
  232. if (sp->cdb_len > 12)
  233. comerrno(EX_BAD, "Can't do %d byte command.n", sp->cdb_len);
  234. fillbytes(&req, sizeof(req), '');
  235. req.flags = SC_ASYNC;
  236. if (sp->flags & SCG_RECV_DATA) {
  237. req.flags |= B_READ;
  238. } else if (sp->size > 0) {
  239. req.flags |= B_WRITE;
  240. }
  241. req.data_length = sp->size;
  242. req.buffer = sp->addr;
  243. req.timeout_value = sp->timeout;
  244. req.command_length = sp->cdb_len;
  245. movebytes(&sp->cdb, req.scsi_cdb, 12);
  246. errno = 0;
  247. ret = ioctl(f, DKIOCMD, &req);
  248. if (scgp->debug) {
  249. printf("ret: %d errno: %d (%s)n", ret, errno, errmsgstr(errno));
  250. printf("data_length:     %dn", req.data_length);
  251. printf("buffer:          0x%Xn", req.buffer);
  252. printf("timeout_value:   %dn", req.timeout_value);
  253. printf("status_validity: %dn", req.status_validity);
  254. printf("scsi_bus_status: 0x%Xn", req.scsi_bus_status);
  255. printf("adapter_status:  0x%Xn", req.adapter_status);
  256. printf("adap_q_status:   0x%Xn", req.adap_q_status);
  257. printf("q_tag_msg:       0x%Xn", req.q_tag_msg);
  258. printf("flags:           0X%Xn", req.flags);
  259. }
  260. if (ret < 0) {
  261. sp->ux_errno = geterrno();
  262. /*
  263.  * Check if SCSI command cound not be send at all.
  264.  */
  265. if (sp->ux_errno == ENOTTY || sp->ux_errno == ENXIO ||
  266.     sp->ux_errno == EINVAL || sp->ux_errno == EACCES) {
  267. return (-1);
  268. }
  269. } else {
  270. sp->ux_errno = 0;
  271. }
  272. ret = 0;
  273. sp->sense_count = 0;
  274. sp->resid = 0; /* AIX is the same rubbish as Linux here */
  275. fillbytes(&sp->scb, sizeof(sp->scb), '');
  276. fillbytes(&sp->u_sense.cmd_sense, sizeof(sp->u_sense.cmd_sense), '');
  277. if (req.status_validity == 0) {
  278. sp->error = SCG_NO_ERROR;
  279. return (0);
  280. }
  281. if (req.status_validity & 1) {
  282. sp->u_scb.cmd_scb[0] = req.scsi_bus_status;
  283. sp->error = SCG_RETRYABLE;
  284. }
  285. if (req.status_validity & 2) {
  286. if (req.adapter_status & SC_NO_DEVICE_RESPONSE) {
  287. sp->error = SCG_FATAL;
  288. } else if (req.adapter_status & SC_CMD_TIMEOUT) {
  289. sp->error = SCG_TIMEOUT;
  290. } else if (req.adapter_status != 0) {
  291. sp->error = SCG_RETRYABLE;
  292. }
  293. }
  294. return (ret);
  295. }
  296. LOCAL int
  297. do_scsi_sense(scgp, f, sp)
  298. SCSI *scgp;
  299. int f;
  300. struct scg_cmd *sp;
  301. {
  302. int ret;
  303. struct scg_cmd s_cmd;
  304. if (sp->sense_len > SCG_MAX_SENSE)
  305. sp->sense_len = SCG_MAX_SENSE;
  306. fillbytes((caddr_t)&s_cmd, sizeof(s_cmd), '');
  307. s_cmd.addr = sp->u_sense.cmd_sense;
  308. s_cmd.size = sp->sense_len;
  309. s_cmd.flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  310. s_cmd.cdb_len = SC_G0_CDBLEN;
  311. s_cmd.sense_len = CCS_SENSE_LEN;
  312. s_cmd.target = scgp->target;
  313. s_cmd.cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
  314. s_cmd.cdb.g0_cdb.lun = sp->cdb.g0_cdb.lun;
  315. s_cmd.cdb.g0_cdb.count = sp->sense_len;
  316. ret = do_scsi_cmd(scgp, f, &s_cmd);
  317. if (ret < 0)
  318. return (ret);
  319. if (s_cmd.u_scb.cmd_scb[0] & 02) {
  320. /* XXX ??? Check condition on request Sense ??? */
  321. }
  322. sp->sense_count = sp->sense_len - s_cmd.resid;
  323. return (ret);
  324. }
  325. LOCAL int
  326. scsi_send(scgp, f, sp)
  327. SCSI *scgp;
  328. int f;
  329. struct scg_cmd *sp;
  330. {
  331. int ret;
  332. if (f < 0) {
  333. sp->error = SCG_FATAL;
  334. return (0);
  335. }
  336. ret = do_scsi_cmd(scgp, f, sp);
  337. if (ret < 0)
  338. return (ret);
  339. if (sp->u_scb.cmd_scb[0] & 02)
  340. ret = do_scsi_sense(scgp, f, sp);
  341. return (ret);
  342. }