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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-linux-pg.c 1.21 99/11/30 Copyright 1997 J. Schilling */
  2. #ifndef lint
  3. static char ___sccsid[] =
  4. "@(#)scsi-linux-pg.c 1.21 99/11/30 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.  * Warning: you may change this source, but if you do that
  12.  * you need to change the _scg_version and _scg_auth* string below.
  13.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  14.  * Choose your name instead of "schily" and make clear that the version
  15.  * string is related to a modified source.
  16.  *
  17.  * Copyright (c) 1997  J. Schilling
  18.  * Copyright (c) 1998  Grant R. Guenther <grant@torque.net>
  19.  *     Under the terms of the GNU public license.
  20.  */
  21. /*
  22.  * This program is free software; you can redistribute it and/or modify
  23.  * it under the terms of the GNU General Public License as published by
  24.  * the Free Software Foundation; either version 2, or (at your option)
  25.  * any later version.
  26.  *
  27.  * This program is distributed in the hope that it will be useful,
  28.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30.  * GNU General Public License for more details.
  31.  *
  32.  * You should have received a copy of the GNU General Public License
  33.  * along with this program; see the file COPYING.  If not, write to
  34.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  35.  */
  36. #ifdef HAVE_LINUX_PG_H
  37. #include <linux/pg.h>
  38. #else
  39. #include "pg.h" /* Use local version as Linux sometimes doesn't have */
  40. #endif /* installed. Now libscg always supports PP SCSI     */
  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_pg[] = "scsi-linux-pg.c-1.21"; /* The version for this transport*/
  49. #ifdef USE_PG_ONLY
  50. #define MAX_SCG 1 /* Max # of SCSI controllers */
  51. #define MAX_TGT 8
  52. #define MAX_LUN 8
  53. struct scg_local {
  54. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  55. short buscookies[MAX_SCG];
  56. int pgbus;
  57. char *SCSIbuf;
  58. };
  59. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  60. #else
  61. #define scg__version pg_version
  62. #define scsi_open pg_open
  63. #define scsi_close pg_close
  64. #define scsi_send pg_send
  65. #define scsi_maxdma pg_maxdma
  66. #define scsi_initiator_id pg_initiator_id
  67. #define scsi_isatapi pg_isatapi
  68. #define scsireset pg_reset
  69. EXPORT char *pg_version __PR((SCSI *scgp, int what));
  70. LOCAL int pg_open __PR((SCSI *scgp, char *device, int busno, int tgt, int tlun));
  71. LOCAL int pg_close __PR((SCSI *scgp));
  72. LOCAL long pg_maxdma __PR((SCSI *scgp));
  73. LOCAL int  pg_initiator_id __PR((SCSI *scgp));
  74. LOCAL int  pg_isatapi __PR((SCSI *scgp));
  75. LOCAL int pg_reset __PR((SCSI *scgp));
  76. LOCAL int pg_send __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  77. #endif
  78. LOCAL int do_scsi_cmd __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  79. LOCAL int do_scsi_sense __PR((SCSI *scgp, int f, struct scg_cmd *sp));
  80. /*
  81.  * Return version information for the low level SCSI transport code.
  82.  * This has been introduced to make it easier to trace down problems
  83.  * in applications.
  84.  */
  85. EXPORT char *
  86. scg__version(scgp, what)
  87. SCSI *scgp;
  88. int what;
  89. {
  90. if (scgp != (SCSI *)0) {
  91. switch (what) {
  92. case SCG_VERSION:
  93. return (_scg_trans_version_pg);
  94. /*
  95.  * If you changed this source, you are not allowed to
  96.  * return "schily" for the SCG_AUTHOR request.
  97.  */
  98. case SCG_AUTHOR:
  99. return (_scg_auth_schily);
  100. case SCG_SCCS_ID:
  101. return (___sccsid);
  102. }
  103. }
  104. return ((char *)0);
  105. }
  106. EXPORT int
  107. scsi_open(scgp, device, busno, tgt, tlun)
  108. SCSI *scgp;
  109. char *device;
  110. int busno;
  111. int tgt;
  112. int tlun;
  113. {
  114. register int f;
  115. register int b;
  116. #ifdef USE_PG_ONLY
  117. register int t;
  118. register int l;
  119. #endif
  120. register int nopen = 0;
  121. char devname[32];
  122. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  123. errno = EINVAL;
  124. if (scgp->errstr)
  125. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  126. "Illegal value for busno, target or lun '%d,%d,%d'",
  127. busno, tgt, tlun);
  128. return (-1);
  129. }
  130. #ifndef USE_PG_ONLY
  131. /*
  132.  * We need to find a fake bus number for the parallel port interface.
  133.  * Unfortunatly, the buscookie array may contain holes if
  134.  * SCSI_IOCTL_GET_BUS_NUMBER works, so we are searching backwards
  135.  * for some place for us.
  136.  * XXX Should add extra space in buscookies for a "PP bus".
  137.  */
  138. if (scglocal(scgp)->buscookies[MAX_SCG-1] != (short)-1)
  139. return (0); /* No space for pgbus */
  140. for (b=MAX_SCG-1; b >= 0; b--) {
  141. if (scglocal(scgp)->buscookies[b] != (short)-1) {
  142. scglocal(scgp)->pgbus = ++b;
  143. break;
  144. }
  145. }
  146. if (scgp->debug)
  147. printf("PP Bus: %dn", scglocal(scgp)->pgbus);
  148. #else
  149. if (scgp->local == NULL) {
  150. scgp->local = malloc(sizeof(struct scg_local));
  151. if (scgp->local == NULL)
  152. return (0);
  153. scglocal(scgp)->pgbus = -2;
  154. scglocal(scgp)->SCSIbuf = (char *)-1;
  155. for (b=0; b < MAX_SCG; b++) {
  156. for (t=0; t < MAX_TGT; t++) {
  157. for (l=0; l < MAX_LUN ; l++)
  158. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  159. }
  160. }
  161. }
  162. #endif
  163. if (scglocal(scgp)->pgbus < 0)
  164. scglocal(scgp)->pgbus = 0;
  165. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2))
  166. goto openbydev;
  167. if (busno >= 0 && tgt >= 0 && tlun >= 0) {
  168. #ifndef USE_PG_ONLY
  169. if (scglocal(scgp)->pgbus != busno)
  170. return (0);
  171. #endif
  172. sprintf(devname, "/dev/pg%d", tgt);
  173. f = open(devname, 2);
  174. if (f < 0) {
  175. if (scgp->errstr)
  176. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  177. "Cannot open '%s'", devname);
  178. return (0);
  179. }
  180. scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
  181. return 1;
  182. } else {
  183. /* scgp->scsibus = 0; scgp->lun = 0;*/
  184. tlun = 0;
  185. for(tgt=0;tgt<MAX_TGT;tgt++) {
  186. sprintf(devname, "/dev/pg%d", tgt);
  187. f = open(devname, 2);
  188. if (f >= 0) {
  189. scglocal(scgp)->scgfiles[scglocal(scgp)->pgbus][tgt][tlun] = f;
  190. nopen++;
  191. }
  192. }
  193. }
  194. openbydev:
  195. if (device != NULL && *device != '') {
  196. char *p;
  197. if (tlun < 0)
  198. return (0);
  199. f = open(device, 2);
  200. if (f < 0 && errno == ENOENT)
  201. return (0);
  202. p = device + strlen(device) -1;
  203. tgt = *p - '0';
  204. if (tgt < 0 || tgt > 9)
  205. return (0);
  206. scgp->scsibus = scglocal(scgp)->pgbus;
  207. scgp->target = tgt;
  208. scgp->lun = tlun;
  209. scglocal(scgp)->scgfiles[scglocal(scgp)->pgbus][tgt][tlun] = f;
  210. return (++nopen);
  211. }
  212. return (nopen);
  213. }
  214. EXPORT int
  215. scsi_close(scgp)
  216. SCSI *scgp;
  217. {
  218. register int f;
  219. register int b;
  220. register int t;
  221. register int l;
  222. if (scgp->local == NULL)
  223. return (-1);
  224. if (scglocal(scgp)->pgbus < 0)
  225. return (0);
  226. b = scglocal(scgp)->pgbus;
  227. scglocal(scgp)->buscookies[b] = (short)-1;
  228. for (t=0; t < MAX_TGT; t++) {
  229. for (l=0; l < MAX_LUN ; l++)
  230. f = scglocal(scgp)->scgfiles[b][t][l];
  231. if (f >= 0)
  232. close(f);
  233. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  234. }
  235. return (0);
  236. }
  237. LOCAL long
  238. scsi_maxdma(scgp)
  239. SCSI *scgp;
  240. {
  241. return (PG_MAX_DATA);
  242. }
  243. #ifdef USE_PG_ONLY
  244. EXPORT void *
  245. scsi_getbuf(scgp, amt)
  246. SCSI *scgp;
  247. long amt;
  248. {
  249.         char    *ret;
  250. if (amt <= 0 || amt > scsi_maxdma(scgp))
  251.                 return ((void *)0);
  252.         if (scgp->debug)
  253.                 printf("scsi_getbuf: %ld bytesn", amt);
  254.         ret = valloc((size_t)(amt+getpagesize()));
  255.         if (ret == NULL)
  256.                 return (ret);
  257. scgp->bufbase = ret;
  258.         ret += getpagesize();
  259.         scglocal(scgp)->SCSIbuf = ret;
  260.         return ((void *)ret);
  261. }
  262. EXPORT void
  263. scsi_freebuf(scgp)
  264. SCSI *scgp;
  265. {
  266. if (scgp->bufbase)
  267. free(scgp->bufbase);
  268. scgp->bufbase = NULL;
  269. }
  270. EXPORT
  271. BOOL scsi_havebus(scgp, busno)
  272. SCSI *scgp;
  273. int busno;
  274. {
  275. register int t;
  276. register int l;
  277. if (busno < 0 || busno >= MAX_SCG)
  278. return (FALSE);
  279. if (scgp->local == NULL)
  280. return (FALSE);
  281. for (t=0; t < MAX_TGT; t++) {
  282. for (l=0; l < MAX_LUN ; l++)
  283. if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
  284. return (TRUE);
  285. }
  286. return (FALSE);
  287. }
  288. EXPORT
  289. int scsi_fileno(scgp, busno, tgt, tlun)
  290. SCSI *scgp;
  291. int busno;
  292. int tgt;
  293. int tlun;
  294. {
  295. if (busno < 0 || busno >= MAX_SCG ||
  296.     tgt < 0 || tgt >= MAX_TGT ||
  297.     tlun < 0 || tlun >= MAX_LUN)
  298. return (-1);
  299. if (scgp->local == NULL)
  300. return (-1);
  301. return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
  302. }
  303. #endif /* USE_PG_ONLY */
  304. EXPORT int
  305. scsi_initiator_id(scgp)
  306. SCSI *scgp;
  307. {
  308. return (-1);
  309. }
  310. EXPORT
  311. int scsi_isatapi(scgp)
  312. SCSI *scgp;
  313. {
  314. return (TRUE);
  315. }
  316. EXPORT
  317. int scsireset(scgp)
  318. SCSI *scgp;
  319. {
  320. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  321. struct pg_write_hdr hdr = {PG_MAGIC, PG_RESET, 0};
  322. return (write(f, (char *)&hdr, sizeof(hdr)));
  323. }
  324. #ifndef MAX
  325. #define MAX(a,b) ((a)>(b)?(a):(b))
  326. #endif
  327. #define RHSIZE sizeof(struct pg_read_hdr)
  328. #define WHSIZE  sizeof(struct pg_write_hdr)
  329. #define LEAD MAX(RHSIZE,WHSIZE)
  330. LOCAL int
  331. do_scsi_cmd(scgp, f, sp)
  332. SCSI *scgp;
  333. int f;
  334. struct scg_cmd *sp;
  335. {
  336. char local[LEAD+PG_MAX_DATA];
  337. int use_local, i, r;
  338. int inward = (sp->flags & SCG_RECV_DATA);
  339. struct pg_write_hdr *whp;
  340. struct pg_read_hdr  *rhp;
  341. char     *dbp;
  342. if (sp->cdb_len > 12)
  343. comerrno(EX_BAD, "Can't do %d byte command.n", sp->cdb_len);
  344. if (sp->addr == scglocal(scgp)->SCSIbuf) {
  345. use_local = 0; 
  346. dbp = sp->addr;
  347. } else {
  348. use_local = 1;
  349. dbp = &local[LEAD];
  350. if (!inward) 
  351. movebytes(sp->addr, dbp, sp->size);
  352. }
  353. whp = (struct pg_write_hdr *)(dbp - WHSIZE);
  354. rhp = (struct pg_read_hdr *)(dbp - RHSIZE);
  355. whp->magic   = PG_MAGIC;
  356. whp->func    = PG_COMMAND;
  357. whp->dlen    = sp->size;
  358. whp->timeout = sp->timeout;
  359. for(i=0; i<12; i++) {
  360. if (i < sp->cdb_len)
  361. whp->packet[i] = sp->cdb.cmd_cdb[i];
  362. else
  363. whp->packet[i] = 0;
  364. }
  365. i = WHSIZE;
  366. if (!inward) 
  367. i += sp->size;
  368. r = write(f, (char *)whp, i);
  369. if (r < 0) { /* command was not sent */
  370. sp->ux_errno = geterrno();
  371. if (sp->ux_errno == ETIME) {
  372. /*
  373.  * If the previous command timed out, we cannot send
  374.  * any further command until the command in the drive
  375.  * is ready. So we behave as if the drive did not
  376.  * respond to the command.
  377.  */
  378. sp->error = SCG_FATAL;
  379. return 0;
  380. }
  381. return -1;
  382. }
  383. if (r != i)
  384. errmsg("scsi_send(%s) wrote %d bytes (expected %d).n",
  385. scgp->cmdname, r, i);
  386. sp->ux_errno = 0;
  387. sp->sense_count = 0;
  388. r = read(f, (char *)rhp, RHSIZE+sp->size);
  389. if (r < 0) {
  390. sp->ux_errno = geterrno();
  391. if (sp->ux_errno == ETIME) {
  392. sp->error = SCG_TIMEOUT;
  393. return 0;
  394. }
  395. sp->error = SCG_FATAL;
  396. return -1;
  397. }
  398. i = rhp->dlen;
  399. if (i > sp->size) {
  400. /*
  401.  * "DMA overrun" should be handled in the kernel.
  402.  * However this may happen with flaky PP adapters.
  403.  */
  404. errmsgno(EX_BAD,
  405. "DMA (read) overrun by %d bytes (requested %d bytes).n",
  406. i - sp->size, sp->size);
  407. i = sp->size;
  408. }
  409. if (use_local && inward)
  410. movebytes(dbp, sp->addr, i);
  411. sp->resid = sp->size - i;
  412. fillbytes(&sp->scb, sizeof(sp->scb), '');
  413.         fillbytes(&sp->u_sense.cmd_sense, sizeof(sp->u_sense.cmd_sense), '');
  414. sp->error = SCG_NO_ERROR;
  415. i = rhp->scsi?2:0;
  416. sp->u_scb.cmd_scb[0] = i;
  417. if (i) {
  418. if (sp->ux_errno == 0)
  419. sp->ux_errno = EIO;
  420. sp->error = SCG_RETRYABLE;
  421. }
  422. return 0;
  423. }
  424. LOCAL int
  425. do_scsi_sense(scgp, f, sp)
  426. SCSI *scgp;
  427. int f;
  428. struct scg_cmd *sp;
  429. {
  430.         int             ret;
  431.         struct scg_cmd  s_cmd;
  432.         if (sp->sense_len > SCG_MAX_SENSE)
  433.                 sp->sense_len = SCG_MAX_SENSE;
  434.         fillbytes((caddr_t)&s_cmd, sizeof(s_cmd), '');
  435.         s_cmd.addr = sp->u_sense.cmd_sense;
  436.         s_cmd.size = sp->sense_len;
  437.         s_cmd.flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  438.         s_cmd.cdb_len = SC_G0_CDBLEN;
  439.         s_cmd.sense_len = CCS_SENSE_LEN;
  440.         s_cmd.target = scgp->target;
  441.         s_cmd.cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
  442.         s_cmd.cdb.g0_cdb.lun = sp->cdb.g0_cdb.lun;
  443.         s_cmd.cdb.g0_cdb.count = sp->sense_len;
  444.         ret = do_scsi_cmd(scgp, f, &s_cmd);
  445.         if (ret < 0)
  446.                 return (ret);
  447.         sp->sense_count = sp->sense_len - s_cmd.resid;
  448.         return (ret);
  449. }
  450. LOCAL int
  451. scsi_send(scgp, f, sp)
  452. SCSI *scgp;
  453. int f;
  454. struct scg_cmd *sp;
  455. {
  456. int ret;
  457. if (f < 0) {
  458. sp->error = SCG_FATAL;
  459. return (0);
  460. }
  461. ret = do_scsi_cmd(scgp, f, sp);
  462. if (ret < 0)
  463. return (ret);
  464. if (sp->u_scb.cmd_scb[0])
  465. ret = do_scsi_sense(scgp, f, sp);
  466. return (ret);
  467. }
  468. /* end of scsi-linux-pg.c */
  469. #ifndef USE_PG_ONLY
  470. #undef scg__version
  471. #undef scsi_open
  472. #undef scsi_close
  473. #undef scsi_send
  474. #undef scsi_maxdma
  475. #undef scsi_initiator_id
  476. #undef scsi_isatapi
  477. #undef scsireset
  478. #endif