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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-linux-pg.c 1.18 99/09/07 Copyright 1997 J. Schilling */
  2. #ifndef lint
  3. static char ___sccsid[] =
  4. "@(#)scsi-linux-pg.c 1.18 99/09/07 Copyright 1997 J. Schilling";
  5. #endif
  6. /*
  7.  * Interface for the Linux PARIDE implementation.
  8.  *
  9.  * We emulate the functionality of the scg driver, via the pg driver.
  10.  *
  11.  * Copyright (c) 1997  J. Schilling
  12.  * Copyright (c) 1998  Grant R. Guenther <grant@torque.net>
  13.  *     Under the terms of the GNU public license.
  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 <linux/pg.h>
  31. #ifdef USE_PG_ONLY
  32. #define MAX_SCG 1 /* Max # of SCSI controllers */
  33. #define MAX_TGT 8
  34. #define MAX_LUN 8
  35. struct scg_local {
  36. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  37. short buscookies[MAX_SCG];
  38. int pgbus;
  39. char *SCSIbuf;
  40. };
  41. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  42. #else
  43. #define scsi_open pg_open
  44. #define scsi_close pg_close
  45. #define scsi_send pg_send
  46. #define scsi_maxdma pg_maxdma
  47. #define scsi_initiator_id pg_initiator_id
  48. #define scsi_isatapi pg_isatapi
  49. #define scsireset pg_reset
  50. LOCAL int pg_open __PR((SCSI *scgp, char *device, int busno, int tgt, int tlun));
  51. LOCAL int pg_close __PR((SCSI *scgp));
  52. LOCAL long pg_maxdma __PR((SCSI *scgp));
  53. LOCAL int  pg_initiator_id __PR((SCSI *scgp));
  54. LOCAL int  pg_isatapi __PR((SCSI *scgp));
  55. LOCAL int pg_reset __PR((SCSI *scgp));
  56. LOCAL int pg_send __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  57. #endif
  58. LOCAL int do_scsi_cmd __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  59. LOCAL int do_scsi_sense __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  60. EXPORT int
  61. scsi_open(scgp, device, busno, tgt, tlun)
  62. SCSI *scgp;
  63. char *device;
  64. int busno;
  65. int tgt;
  66. int tlun;
  67. {
  68. register int f;
  69. register int b;
  70. #ifdef USE_PG_ONLY
  71. register int t;
  72. register int l;
  73. #endif
  74. register int nopen = 0;
  75. char devname[32];
  76. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  77. errno = EINVAL;
  78. if (scgp->errstr)
  79. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  80. "Illegal value for busno, target or lun '%d,%d,%d'",
  81. busno, tgt, tlun);
  82. return (-1);
  83. }
  84. #ifndef USE_PG_ONLY
  85. /*
  86.  * We need to find a fake bus number for the parallel port interface.
  87.  * Unfortunatly, the buscookie array may contain holes if
  88.  * SCSI_IOCTL_GET_BUS_NUMBER works, so we are searching backwards
  89.  * for some place for us.
  90.  * XXX Should add extra space in buscookies for a "PP bus".
  91.  */
  92. if (scglocal(scgp)->buscookies[MAX_SCG-1] != (short)-1)
  93. return (0); /* No space for pgbus */
  94. for (b=MAX_SCG-1; b >= 0; b--) {
  95. if (scglocal(scgp)->buscookies[b] != (short)-1) {
  96. scglocal(scgp)->pgbus = ++b;
  97. break;
  98. }
  99. }
  100. if (scgp->debug)
  101. printf("PP Bus: %dn", scglocal(scgp)->pgbus);
  102. #else
  103. if (scgp->local == NULL) {
  104. scgp->local = malloc(sizeof(struct scg_local));
  105. if (scgp->local == NULL)
  106. return (0);
  107. scglocal(scgp)->pgbus = -2;
  108. scglocal(scgp)->SCSIbuf = (char *)-1;
  109. for (b=0; b < MAX_SCG; b++) {
  110. for (t=0; t < MAX_TGT; t++) {
  111. for (l=0; l < MAX_LUN ; l++)
  112. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  113. }
  114. }
  115. }
  116. #endif
  117. if (scglocal(scgp)->pgbus < 0)
  118. scglocal(scgp)->pgbus = 0;
  119. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2))
  120. goto openbydev;
  121. if (busno >= 0 && tgt >= 0 && tlun >= 0) {
  122. #ifndef USE_PG_ONLY
  123. if (scglocal(scgp)->pgbus != busno)
  124. return (0);
  125. #endif
  126. sprintf(devname, "/dev/pg%d", tgt);
  127. f = open(devname, 2);
  128. if (f < 0) {
  129. if (scgp->errstr)
  130. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  131. "Cannot open '%s'", devname);
  132. return (0);
  133. }
  134. scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
  135. return 1;
  136. } else {
  137. /* scgp->scsibus = 0; scgp->lun = 0;*/
  138. tlun = 0;
  139. for(tgt=0;tgt<MAX_TGT;tgt++) {
  140. sprintf(devname, "/dev/pg%d", tgt);
  141. f = open(devname, 2);
  142. if (f >= 0) {
  143. scglocal(scgp)->scgfiles[scglocal(scgp)->pgbus][tgt][tlun] = f;
  144. nopen++;
  145. }
  146. }
  147. }
  148. openbydev:
  149. if (device != NULL && *device != '') {
  150. char *p;
  151. if (tlun < 0)
  152. return (0);
  153. f = open(device, 2);
  154. if (f < 0 && errno == ENOENT)
  155. return (0);
  156. p = device + strlen(device) -1;
  157. tgt = *p - '0';
  158. if (tgt < 0 || tgt > 9)
  159. return (0);
  160. scgp->scsibus = scglocal(scgp)->pgbus;
  161. scgp->target = tgt;
  162. scgp->lun = tlun;
  163. scglocal(scgp)->scgfiles[scglocal(scgp)->pgbus][tgt][tlun] = f;
  164. return (++nopen);
  165. }
  166. return (nopen);
  167. }
  168. EXPORT int
  169. scsi_close(scgp)
  170. SCSI *scgp;
  171. {
  172. register int f;
  173. register int b;
  174. register int t;
  175. register int l;
  176. if (scgp->local == NULL)
  177. return (-1);
  178. if (scglocal(scgp)->pgbus < 0)
  179. return (0);
  180. b = scglocal(scgp)->pgbus;
  181. scglocal(scgp)->buscookies[b] = (short)-1;
  182. for (t=0; t < MAX_TGT; t++) {
  183. for (l=0; l < MAX_LUN ; l++) {
  184. f = scglocal(scgp)->scgfiles[b][t][l];
  185. if (f >= 0)
  186. close(f);
  187. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  188. }
  189. }
  190. return (0);
  191. }
  192. LOCAL long
  193. scsi_maxdma(scgp)
  194. SCSI *scgp;
  195. {
  196. return (PG_MAX_DATA);
  197. }
  198. #ifdef USE_PG_ONLY
  199. EXPORT void *
  200. scsi_getbuf(scgp, amt)
  201. SCSI *scgp;
  202. long amt;
  203. {
  204.         char    *ret;
  205. if (amt <= 0 || amt > scsi_maxdma(scgp))
  206.                 return ((void *)0);
  207.         if (scgp->debug)
  208.                 printf("scsi_getbuf: %ld bytesn", amt);
  209.         ret = valloc((size_t)(amt+getpagesize()));
  210.         if (ret == NULL)
  211.                 return (ret);
  212. scgp->bufbase = ret;
  213.         ret += getpagesize();
  214.         scglocal(scgp)->SCSIbuf = ret;
  215.         return ((void *)ret);
  216. }
  217. EXPORT void
  218. scsi_freebuf(scgp)
  219. SCSI *scgp;
  220. {
  221. if (scgp->bufbase)
  222. free(scgp->bufbase);
  223. scgp->bufbase = NULL;
  224. }
  225. EXPORT
  226. BOOL scsi_havebus(scgp, busno)
  227. SCSI *scgp;
  228. int busno;
  229. {
  230. register int t;
  231. register int l;
  232. if (busno < 0 || busno >= MAX_SCG)
  233. return (FALSE);
  234. if (scgp->local == NULL)
  235. return (FALSE);
  236. for (t=0; t < MAX_TGT; t++) {
  237. for (l=0; l < MAX_LUN ; l++)
  238. if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
  239. return (TRUE);
  240. }
  241. return (FALSE);
  242. }
  243. EXPORT
  244. int scsi_fileno(scgp, busno, tgt, tlun)
  245. SCSI *scgp;
  246. int busno;
  247. int tgt;
  248. int tlun;
  249. {
  250. if (busno < 0 || busno >= MAX_SCG ||
  251.     tgt < 0 || tgt >= MAX_TGT ||
  252.     tlun < 0 || tlun >= MAX_LUN)
  253. return (-1);
  254. if (scgp->local == NULL)
  255. return (-1);
  256. return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
  257. }
  258. #endif /* USE_PG_ONLY */
  259. EXPORT int
  260. scsi_initiator_id(scgp)
  261. SCSI *scgp;
  262. {
  263. return (-1);
  264. }
  265. EXPORT
  266. int scsi_isatapi(scgp)
  267. SCSI *scgp;
  268. {
  269. return (TRUE);
  270. }
  271. EXPORT
  272. int scsireset(scgp)
  273. SCSI *scgp;
  274. {
  275. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  276. struct pg_write_hdr hdr = {PG_MAGIC, PG_RESET, 0};
  277. return (write(f, (char *)&hdr, sizeof(hdr)));
  278. }
  279. #ifndef MAX
  280. #define MAX(a,b) ((a)>(b)?(a):(b))
  281. #endif
  282. #define RHSIZE sizeof(struct pg_read_hdr)
  283. #define WHSIZE  sizeof(struct pg_write_hdr)
  284. #define LEAD MAX(RHSIZE,WHSIZE)
  285. LOCAL int
  286. do_scsi_cmd(scgp, f, sp)
  287. SCSI *scgp;
  288. int f;
  289. struct scg_cmd *sp;
  290. {
  291. char local[LEAD+PG_MAX_DATA];
  292. int use_local, i, r;
  293. int inward = (sp->flags & SCG_RECV_DATA);
  294. struct pg_write_hdr *whp;
  295. struct pg_read_hdr  *rhp;
  296. char     *dbp;
  297. if (sp->cdb_len > 12)
  298. comerrno(EX_BAD, "Can't do %d byte command.n", sp->cdb_len);
  299. if (sp->addr == scglocal(scgp)->SCSIbuf) {
  300. use_local = 0; 
  301. dbp = sp->addr;
  302. } else {
  303. use_local = 1;
  304. dbp = &local[LEAD];
  305. if (!inward) 
  306. movebytes(sp->addr, dbp, sp->size);
  307. }
  308. whp = (struct pg_write_hdr *)(dbp - WHSIZE);
  309. rhp = (struct pg_read_hdr *)(dbp - RHSIZE);
  310. whp->magic   = PG_MAGIC;
  311. whp->func    = PG_COMMAND;
  312. whp->dlen    = sp->size;
  313. whp->timeout = sp->timeout;
  314. for(i=0; i<12; i++) {
  315. if (i < sp->cdb_len)
  316. whp->packet[i] = sp->cdb.cmd_cdb[i];
  317. else
  318. whp->packet[i] = 0;
  319. }
  320. i = WHSIZE;
  321. if (!inward) 
  322. i += sp->size;
  323. r = write(f, (char *)whp, i);
  324. if (r < 0) { /* command was not sent */
  325. sp->ux_errno = geterrno();
  326. if (sp->ux_errno == ETIME) {
  327. /*
  328.  * If the previous command timed out, we cannot send
  329.  * any further command until the command in the drive
  330.  * is ready. So we behave as if the drive did not
  331.  * respond to the command.
  332.  */
  333. sp->error = SCG_FATAL;
  334. return 0;
  335. }
  336. return -1;
  337. }
  338. if (r != i)
  339. errmsg("scsi_send(%s) wrote %d bytes (expected %d).n",
  340. scgp->cmdname, r, i);
  341. sp->ux_errno = 0;
  342. sp->sense_count = 0;
  343. r = read(f, (char *)rhp, RHSIZE+sp->size);
  344. if (r < 0) {
  345. sp->ux_errno = geterrno();
  346. if (sp->ux_errno == ETIME) {
  347. sp->error = SCG_TIMEOUT;
  348. return 0;
  349. }
  350. sp->error = SCG_FATAL;
  351. return -1;
  352. }
  353. i = rhp->dlen;
  354. if (i > sp->size) {
  355. /*
  356.  * "DMA overrun" should be handled in the kernel.
  357.  * However this may happen with flaky PP adapters.
  358.  */
  359. errmsgno(EX_BAD,
  360. "DMA (read) overrun by %d bytes (requested %d bytes).n",
  361. i - sp->size, sp->size);
  362. i = sp->size;
  363. }
  364. if (use_local && inward)
  365. movebytes(dbp, sp->addr, i);
  366. sp->resid = sp->size - i;
  367. fillbytes(&sp->scb, sizeof(sp->scb), '');
  368.         fillbytes(&sp->u_sense.cmd_sense, sizeof(sp->u_sense.cmd_sense), '');
  369. sp->error = SCG_NO_ERROR;
  370. i = rhp->scsi?2:0;
  371. sp->u_scb.cmd_scb[0] = i;
  372. if (i) {
  373. if (sp->ux_errno == 0)
  374. sp->ux_errno = EIO;
  375. sp->error = SCG_RETRYABLE;
  376. }
  377. return 0;
  378. }
  379. LOCAL int
  380. do_scsi_sense(scgp, f, sp)
  381. SCSI *scgp;
  382. int f;
  383. struct scg_cmd *sp;
  384. {
  385.         int             ret;
  386.         struct scg_cmd  s_cmd;
  387.         if (sp->sense_len > SCG_MAX_SENSE)
  388.                 sp->sense_len = SCG_MAX_SENSE;
  389.         fillbytes((caddr_t)&s_cmd, sizeof(s_cmd), '');
  390.         s_cmd.addr = sp->u_sense.cmd_sense;
  391.         s_cmd.size = sp->sense_len;
  392.         s_cmd.flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  393.         s_cmd.cdb_len = SC_G0_CDBLEN;
  394.         s_cmd.sense_len = CCS_SENSE_LEN;
  395.         s_cmd.target = scgp->target;
  396.         s_cmd.cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
  397.         s_cmd.cdb.g0_cdb.lun = sp->cdb.g0_cdb.lun;
  398.         s_cmd.cdb.g0_cdb.count = sp->sense_len;
  399.         ret = do_scsi_cmd(scgp, f, &s_cmd);
  400.         if (ret < 0)
  401.                 return (ret);
  402.         sp->sense_count = sp->sense_len - s_cmd.resid;
  403.         return (ret);
  404. }
  405. LOCAL int
  406. scsi_send(scgp, f, sp)
  407. SCSI *scgp;
  408. int f;
  409. struct scg_cmd *sp;
  410. {
  411. int ret;
  412. if (f < 0) {
  413. sp->error = SCG_FATAL;
  414. return (0);
  415. }
  416. ret = do_scsi_cmd(scgp, f, sp);
  417. if (ret < 0)
  418. return (ret);
  419. if (sp->u_scb.cmd_scb[0])
  420. ret = do_scsi_sense(scgp, f, sp);
  421. return (ret);
  422. }
  423. /* end of scsi-linux-pg.c */
  424. #ifndef USE_PG_ONLY
  425. #undef scsi_open
  426. #undef scsi_close
  427. #undef scsi_send
  428. #undef scsi_maxdma
  429. #undef scsi_initiator_id
  430. #undef scsi_isatapi
  431. #undef scsireset
  432. #endif