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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-bsd.c 1.26 99/09/17 Copyright 1997 J. Schilling */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-bsd.c 1.26 99/09/17 Copyright 1997 J. Schilling";
  5. #endif
  6. /*
  7.  * Interface for the NetBSD/FreeBSD/OpenBSD generic SCSI implementation.
  8.  *
  9.  * This is a hack, that tries to emulate the functionality
  10.  * of the scg driver.
  11.  * The SCSI tranport of the generic *BSD implementation is very
  12.  * similar to the SCSI command transport of the
  13.  * 6 years older scg driver.
  14.  *
  15.  * Warning: you may change this source, but if you do that
  16.  * you need to change the _scg_version and _scg_auth* string below.
  17.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  18.  * Choose your name instead of "schily" and make clear that the version
  19.  * string is related to a modified source.
  20.  *
  21.  * Copyright (c) 1997 J. Schilling
  22.  */
  23. /*
  24.  * This program is free software; you can redistribute it and/or modify
  25.  * it under the terms of the GNU General Public License as published by
  26.  * the Free Software Foundation; either version 2, or (at your option)
  27.  * any later version.
  28.  *
  29.  * This program is distributed in the hope that it will be useful,
  30.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  31.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  32.  * GNU General Public License for more details.
  33.  *
  34.  * You should have received a copy of the GNU General Public License
  35.  * along with this program; see the file COPYING.  If not, write to
  36.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  37.  */
  38. #ifndef HAVE_CAMLIB_H
  39. #undef sense
  40. #include <sys/scsiio.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-bsd.c-1.26"; /* 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. struct scg_local {
  53. short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
  54. };
  55. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  56. /*#define MAX_DMA_BSD (32*1024)*/
  57. #define MAX_DMA_BSD (60*1024) /* More seems to make problems */
  58. #if defined(__NetBSD__) && defined(TYPE_ATAPI)
  59. /*
  60.  * NetBSD 1.3 has a merged SCSI/ATAPI system, so this structure
  61.  * is slightly different.
  62.  */
  63. #define MAYBE_ATAPI
  64. #define SADDR_ISSCSI(a) ((a).type == TYPE_SCSI)
  65. #define SADDR_BUS(a) (SADDR_ISSCSI(a)?(a).addr.scsi.scbus:(MAX_SCG-1))
  66. #define SADDR_TARGET(a) (SADDR_ISSCSI(a)?(a).addr.scsi.target:(a).addr.atapi.atbus*2+(a).addr.atapi.drive)
  67. #define SADDR_LUN(a) (SADDR_ISSCSI(a)?(a).addr.scsi.lun:0)
  68. #else
  69. #define SADDR_ISSCSI(a) (1)
  70. #define SADDR_BUS(a) (a).scbus
  71. #define SADDR_TARGET(a) (a).target
  72. #define SADDR_LUN(a) (a).lun
  73. #endif /* __NetBSD__ && TYPE_ATAPI */
  74. LOCAL BOOL scsi_setup __PR((SCSI *scgp, int f, int busno, int tgt, int tlun));
  75. /*
  76.  * Return version information for the low level SCSI transport code.
  77.  * This has been introduced to make it easier to trace down problems
  78.  * in applications.
  79.  */
  80. EXPORT char *
  81. scg__version(scgp, what)
  82. SCSI *scgp;
  83. int what;
  84. {
  85. if (scgp != (SCSI *)0) {
  86. switch (what) {
  87. case SCG_VERSION:
  88. return (_scg_trans_version);
  89. /*
  90.  * If you changed this source, you are not allowed to
  91.  * return "schily" for the SCG_AUTHOR request.
  92.  */
  93. case SCG_AUTHOR:
  94. return (_scg_auth_schily);
  95. case SCG_SCCS_ID:
  96. return (__sccsid);
  97. }
  98. }
  99. return ((char *)0);
  100. }
  101. EXPORT int
  102. scsi_open(scgp, device, busno, tgt, tlun)
  103. SCSI *scgp;
  104. char *device;
  105. int busno;
  106. int tgt;
  107. int tlun;
  108. {
  109. register int f;
  110. register int b;
  111. register int t;
  112. register int l;
  113. register int nopen = 0;
  114. char devname[64];
  115. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  116. errno = EINVAL;
  117. if (scgp->errstr)
  118. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  119. "Illegal value for busno, target or lun '%d,%d,%d'",
  120. busno, tgt, tlun);
  121. return (-1);
  122. }
  123. if (scgp->local == NULL) {
  124. scgp->local = malloc(sizeof(struct scg_local));
  125. if (scgp->local == NULL)
  126. return (0);
  127. for (b=0; b < MAX_SCG; b++) {
  128. for (t=0; t < MAX_TGT; t++) {
  129. for (l=0; l < MAX_LUN ; l++)
  130. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  131. }
  132. }
  133. }
  134. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2))
  135. goto openbydev;
  136. if (busno >= 0 && tgt >= 0 && tlun >= 0) {
  137. sprintf(devname, "/dev/su%d-%d-%d", busno, tgt, tlun);
  138. f = open(devname, O_RDWR);
  139. if (f < 0) {
  140. goto openbydev;
  141. }
  142. scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
  143. return(1);
  144. } else for (b=0; b < MAX_SCG; b++) {
  145. for (t=0; t < MAX_TGT; t++) {
  146. for (l=0; l < MAX_LUN ; l++) {
  147. sprintf(devname, "/dev/su%d-%d-%d", b, t, l);
  148. f = open(devname, O_RDWR);
  149. /* error("open (%s) = %dn", devname, f);*/
  150. if (f < 0) {
  151. if (errno != ENOENT &&
  152.     errno != ENXIO &&
  153.     errno != ENODEV) {
  154. if (scgp->errstr)
  155. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  156. "Cannot open '%s'",
  157. devname);
  158. return (0);
  159. }
  160. } else {
  161. if (scsi_setup(scgp, f, b, t, l))
  162. nopen++;
  163. }
  164. }
  165. }
  166. }
  167. /*
  168.  * Could not open /dev/su-* or got dev=devname:b,l,l / dev=devname:@,l
  169.  * We do the apropriate tests and try our best.
  170.  */
  171. openbydev:
  172. if (nopen == 0) {
  173. struct scsi_addr saddr;
  174. if (device == NULL || device[0] == '')
  175. return (0);
  176. f = open(device, O_RDWR);
  177. if (f < 0)
  178. return (0);
  179. if (tgt == -2) {
  180. if (ioctl(f, SCIOCIDENTIFY, &saddr) < 0) {
  181. close(f);
  182. errno = EINVAL;
  183. return (0);
  184. }
  185. scgp->scsibus = busno = SADDR_BUS(saddr);
  186. scgp->target  = tgt = SADDR_TARGET(saddr);
  187. if ((tlun >= 0) && (tlun != SADDR_LUN(saddr))) {
  188. close(f);
  189. errno = EINVAL;
  190. return (0);
  191. }
  192. scgp->lun     = tlun = SADDR_LUN(saddr);
  193. }
  194. if (scsi_setup(scgp, f, busno, tgt, tlun))
  195. nopen++;
  196. }
  197. return (nopen);
  198. }
  199. EXPORT int
  200. scsi_close(scgp)
  201. SCSI *scgp;
  202. {
  203. register int f;
  204. register int b;
  205. register int t;
  206. register int l;
  207. if (scgp->local == NULL)
  208. return (-1);
  209. for (b=0; b < MAX_SCG; b++) {
  210. for (t=0; t < MAX_TGT; t++) {
  211. for (l=0; l < MAX_LUN ; l++)
  212. f = scglocal(scgp)->scgfiles[b][t][l];
  213. if (f >= 0)
  214. close(f);
  215. scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
  216. }
  217. }
  218. return (0);
  219. }
  220. LOCAL BOOL
  221. scsi_setup(scgp, f, busno, tgt, tlun)
  222. SCSI *scgp;
  223. int f;
  224. int busno;
  225. int tgt;
  226. int tlun;
  227. {
  228. struct scsi_addr saddr;
  229. int Bus;
  230. int Target;
  231. int Lun;
  232. BOOL onetarget = FALSE;
  233. if (scgp->scsibus >= 0 && scgp->target >= 0 && scgp->lun >= 0)
  234. onetarget = TRUE;
  235. if (ioctl(f, SCIOCIDENTIFY, &saddr) < 0) {
  236. errmsg("Cannot get SCSI addr.n");
  237. close(f);
  238. return (FALSE);
  239. }
  240. Bus = SADDR_BUS(saddr);
  241. Target = SADDR_TARGET(saddr);
  242. Lun = SADDR_LUN(saddr);
  243. if (scgp->debug)
  244. printf("Bus: %d Target: %d Lun: %dn", Bus, Target, Lun);
  245. if (Bus >= MAX_SCG || Target >= MAX_TGT || Lun >= MAX_LUN) {
  246. close(f);
  247. return (FALSE);
  248. }
  249. if (scglocal(scgp)->scgfiles[Bus][Target][Lun] == (short)-1)
  250. scglocal(scgp)->scgfiles[Bus][Target][Lun] = (short)f;
  251. if (onetarget) {
  252. if (Bus == busno && Target == tgt && Lun == tlun) {
  253. return (TRUE);
  254. } else {
  255. scglocal(scgp)->scgfiles[Bus][Target][Lun] = (short)-1;
  256. close(f);
  257. }
  258. }
  259. return (FALSE);
  260. }
  261. LOCAL long
  262. scsi_maxdma(scgp)
  263. SCSI *scgp;
  264. {
  265. long maxdma = MAX_DMA_BSD;
  266. return (maxdma);
  267. }
  268. EXPORT void *
  269. scsi_getbuf(scgp, amt)
  270. SCSI *scgp;
  271. long amt;
  272. {
  273. if (amt <= 0 || amt > scsi_maxdma(scgp))
  274. return ((void *)0);
  275. if (scgp->debug)
  276. printf("scsi_getbuf: %ld bytesn", amt);
  277. scgp->bufbase = valloc((size_t)(amt));
  278. return (scgp->bufbase);
  279. }
  280. EXPORT void
  281. scsi_freebuf(scgp)
  282. SCSI *scgp;
  283. {
  284. if (scgp->bufbase)
  285. free(scgp->bufbase);
  286. scgp->bufbase = NULL;
  287. }
  288. EXPORT
  289. BOOL scsi_havebus(scgp, busno)
  290. SCSI *scgp;
  291. int busno;
  292. {
  293. register int t;
  294. register int l;
  295. if (busno < 0 || busno >= MAX_SCG)
  296. return (FALSE);
  297. if (scgp->local == NULL)
  298. return (FALSE);
  299. for (t=0; t < MAX_TGT; t++) {
  300. for (l=0; l < MAX_LUN ; l++)
  301. if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
  302. return (TRUE);
  303. }
  304. return (FALSE);
  305. }
  306. EXPORT
  307. int scsi_fileno(scgp, busno, tgt, tlun)
  308. SCSI *scgp;
  309. int busno;
  310. int tgt;
  311. int tlun;
  312. {
  313. if (busno < 0 || busno >= MAX_SCG ||
  314.     tgt < 0 || tgt >= MAX_TGT ||
  315.     tlun < 0 || tlun >= MAX_LUN)
  316. return (-1);
  317. if (scgp->local == NULL)
  318. return (-1);
  319. return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
  320. }
  321. EXPORT int
  322. scsi_initiator_id(scgp)
  323. SCSI *scgp;
  324. {
  325. return (-1);
  326. }
  327. EXPORT
  328. int scsi_isatapi(scgp)
  329. SCSI *scgp;
  330. {
  331. #ifdef MAYBE_ATAPI
  332. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  333. struct scsi_addr saddr;
  334. if (ioctl(f, SCIOCIDENTIFY, &saddr) < 0)
  335. return (-1);
  336. if (!SADDR_ISSCSI(saddr))
  337. return (TRUE);
  338. #endif
  339. return (FALSE);
  340. }
  341. EXPORT
  342. int scsireset(scgp)
  343. SCSI *scgp;
  344. {
  345. int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
  346. return (ioctl(f, SCIOCRESET, 0));
  347. }
  348. LOCAL int
  349. scsi_send(scgp, f, sp)
  350. SCSI *scgp;
  351. int f;
  352. struct scg_cmd *sp;
  353. {
  354. scsireq_t req;
  355. register long *lp1;
  356. register long *lp2;
  357. int ret = 0;
  358. /* printf("f: %dn", f);*/
  359. if (f < 0) {
  360. sp->error = SCG_FATAL;
  361. return (0);
  362. }
  363. req.flags = SCCMD_ESCAPE; /* We set the SCSI cmd len */
  364. if (sp->flags & SCG_RECV_DATA)
  365. req.flags |= SCCMD_READ;
  366. else if (sp->size > 0)
  367. req.flags |= SCCMD_WRITE;
  368. req.timeout = sp->timeout * 1000;
  369. lp1 = (long *)sp->cdb.cmd_cdb;
  370. lp2 = (long *)req.cmd;
  371. *lp2++ = *lp1++;
  372. *lp2++ = *lp1++;
  373. *lp2++ = *lp1++;
  374. *lp2++ = *lp1++;
  375. req.cmdlen = sp->cdb_len;
  376. req.databuf = sp->addr;
  377. req.datalen = sp->size;
  378. req.datalen_used = 0;
  379. fillbytes(req.sense, sizeof(req.sense), '');
  380. if (sp->sense_len > sizeof(req.sense))
  381. req.senselen = sizeof(req.sense);
  382. else if (sp->sense_len < 0)
  383. req.senselen = 0;
  384. else
  385. req.senselen = sp->sense_len;
  386. req.senselen_used = 0;
  387. req.status = 0;
  388. req.retsts = 0;
  389. req.error = 0;
  390. if (ioctl(f, SCIOCCOMMAND, (void *)&req) < 0) {
  391. ret  = -1;
  392. sp->ux_errno = geterrno();
  393. if (sp->ux_errno != ENOTTY)
  394. ret = 0;
  395. } else {
  396. sp->ux_errno = 0;
  397. if (req.retsts != SCCMD_OK)
  398. sp->ux_errno = EIO;
  399. }
  400. fillbytes(&sp->scb, sizeof(sp->scb), '');
  401. fillbytes(&sp->u_sense.cmd_sense, sizeof(sp->u_sense.cmd_sense), '');
  402. sp->resid = req.datalen - req.datalen_used;
  403. sp->sense_count = req.senselen_used;
  404. if (sp->sense_count > SCG_MAX_SENSE)
  405. sp->sense_count = SCG_MAX_SENSE;
  406. movebytes(req.sense, sp->u_sense.cmd_sense, sp->sense_count);
  407. sp->u_scb.cmd_scb[0] = req.status;
  408. switch (req.retsts) {
  409. case SCCMD_OK:
  410. #ifdef BSD_SCSI_SENSE_BUG
  411. sp->u_scb.cmd_scb[0] = 0;
  412. sp->ux_errno = 0;
  413. #endif
  414. sp->error = SCG_NO_ERROR; break;
  415. case SCCMD_TIMEOUT: sp->error = SCG_TIMEOUT; break;
  416. default:
  417. case SCCMD_BUSY: sp->error = SCG_RETRYABLE; break;
  418. case SCCMD_SENSE: sp->error = SCG_RETRYABLE; break;
  419. case SCCMD_UNKNOWN: sp->error = SCG_FATAL; break;
  420. }
  421. return (ret);
  422. }
  423. #define sense u_sense.Sense
  424. #else /* BSD_CAM */
  425. /*
  426.  * Interface for the FreeBSD CAM passthrough device.
  427.  *
  428.  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
  429.  * Copyright (c) 1998 Kenneth D. Merry <ken@kdm.org>
  430.  * Copyright (c) 1998 Joerg Schilling <schilling@fokus.gmd.de>
  431.  * All rights reserved.
  432.  *
  433.  * Redistribution and use in source and binary forms, with or without
  434.  * modification, are permitted provided that the following conditions
  435.  * are met:
  436.  * 1. Redistributions of source code must retain the above copyright
  437.  *    notice, this list of conditions and the following disclaimer.
  438.  * 2. Redistributions in binary form must reproduce the above copyright
  439.  *    notice, this list of conditions and the following disclaimer in the
  440.  *    documentation and/or other materials provided with the distribution.
  441.  *
  442.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  443.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  444.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  445.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  446.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  447.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  448.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  449.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  450.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  451.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  452.  * SUCH DAMAGE.
  453.  *
  454.  */
  455. #undef sense
  456. #define scsi_sense CAM_scsi_sense
  457. #define scsi_inquiry CAM_scsi_inquiry
  458. #include <sys/param.h>
  459. #include <cam/cam.h>
  460. #include <cam/cam_ccb.h>
  461. #include <cam/scsi/scsi_message.h>
  462. #include <cam/scsi/scsi_pass.h>
  463. #include <camlib.h>
  464. /*
  465.  * Warning: you may change this source, but if you do that
  466.  * you need to change the _scg_version and _scg_auth* string below.
  467.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  468.  * Choose your name instead of "schily" and make clear that the version
  469.  * string is related to a modified source.
  470.  */
  471. LOCAL char _scg_trans_version[] = "scsi-bsd.c-1.26"; /* The version for this transport*/
  472. #define CAM_MAXDEVS 128
  473. struct scg_local {
  474. struct cam_device *cam_devices[CAM_MAXDEVS + 1];
  475. };
  476. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  477. /*
  478.  * Return version information for the low level SCSI transport code.
  479.  * This has been introduced to make it easier to trace down problems
  480.  * in applications.
  481.  */
  482. EXPORT char *
  483. scg__version(scgp, what)
  484. SCSI *scgp;
  485. int what;
  486. {
  487. if (scgp != (SCSI *)0) {
  488. switch (what) {
  489. case SCG_VERSION:
  490. return (_scg_trans_version);
  491. /*
  492.  * If you changed this source, you are not allowed to
  493.  * return "schily" for the SCG_AUTHOR request.
  494.  */
  495. case SCG_AUTHOR:
  496. return (_scg_auth_schily);
  497. case SCG_SCCS_ID:
  498. return (__sccsid);
  499. }
  500. }
  501. return ((char *)0);
  502. }
  503. /*
  504.  * Build a list of everything we can find.
  505.  */
  506. EXPORT int
  507. scsi_open(scgp, device, busno, tgt, tlun)
  508. SCSI *scgp;
  509. char *device;
  510. int busno;
  511. int tgt;
  512. int tlun;
  513. {
  514. char name[16];
  515. int unit;
  516. int nopen = 0;
  517. union ccb ccb;
  518. int bufsize;
  519. struct periph_match_pattern *match_pat;
  520. int fd;
  521. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2)) {
  522. errno = EINVAL;
  523. if (scgp->errstr)
  524. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  525. "Open by 'devname' not supported on this OS");
  526. return (-1);
  527. }
  528. if (scgp->local == NULL) {
  529. scgp->local = malloc(sizeof(struct scg_local));
  530. if (scgp->local == NULL)
  531. return (0);
  532. for (unit = 0; unit <= CAM_MAXDEVS; unit++) {
  533. scglocal(scgp)->cam_devices[unit] = (struct cam_device *)-1;
  534. }
  535. }
  536. /*
  537.  * If we're not scanning the bus, just open one device.
  538.  */
  539. if (busno >= 0 && tgt >= 0 && tlun >= 0) {
  540. scglocal(scgp)->cam_devices[0] = cam_open_btl(busno, tgt, tlun, O_RDWR, NULL);
  541. if (scglocal(scgp)->cam_devices[0] == NULL)
  542. return(-1);
  543. nopen++;
  544. return(nopen);
  545. }
  546. /*
  547.  * First open the transport layer device.  There's no point in the
  548.  * rest of this if we can't open it.
  549.  */
  550. if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
  551. if (scgp->errstr)
  552. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  553. "Open of %s failed", XPT_DEVICE);
  554. return(-1);
  555. }
  556. fillbytes(&ccb, sizeof(union ccb), '');
  557. /*
  558.  * Get a list of up to CAM_MAXDEVS passthrough devices in the
  559.  * system.
  560.  */
  561. ccb.ccb_h.func_code = XPT_DEV_MATCH;
  562. /*
  563.  * Setup the result buffer.
  564.  */
  565. bufsize = sizeof(struct dev_match_result) * CAM_MAXDEVS;
  566. ccb.cdm.match_buf_len = bufsize;
  567. ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
  568. if (ccb.cdm.matches == NULL) {
  569. if (scgp->errstr)
  570. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  571. "Couldn't malloc match buffer");
  572. close(fd);
  573. return(-1);
  574. }
  575. ccb.cdm.num_matches = 0;
  576. /*
  577.  * Setup the pattern buffer.  We're matching against all
  578.  * peripherals named "pass".
  579.  */
  580. ccb.cdm.num_patterns = 1;
  581. ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
  582. ccb.cdm.patterns = (struct dev_match_pattern *)malloc(
  583. sizeof(struct dev_match_pattern));
  584. if (ccb.cdm.patterns == NULL) {
  585. if (scgp->errstr)
  586. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  587. "Couldn't malloc pattern buffer");
  588. close(fd);
  589. free(ccb.cdm.matches);
  590. return(-1);
  591. }
  592. ccb.cdm.patterns[0].type = DEV_MATCH_PERIPH;
  593. match_pat = &ccb.cdm.patterns[0].pattern.periph_pattern;
  594. sprintf(match_pat->periph_name, "pass");
  595. match_pat->flags = PERIPH_MATCH_NAME;
  596. if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
  597. if (scgp->errstr)
  598. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  599. "CAMIOCOMMAND ioctl failed");
  600. close(fd);
  601. free(ccb.cdm.matches);
  602. free(ccb.cdm.patterns);
  603. return(-1);
  604. }
  605. if ((ccb.ccb_h.status != CAM_REQ_CMP)
  606.  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
  607.     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
  608. /* errmsgno(EX_BAD, "Got CAM error 0x%X, CDM error %d.n",*/
  609. if (scgp->errstr)
  610. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  611. "Got CAM error 0x%X, CDM error %d",
  612. ccb.ccb_h.status, ccb.cdm.status);
  613. close(fd);
  614. free(ccb.cdm.matches);
  615. free(ccb.cdm.patterns);
  616. return(-1);
  617. }
  618. free(ccb.cdm.patterns);
  619. close(fd);
  620. for (unit = 0; unit < MIN(CAM_MAXDEVS, ccb.cdm.num_matches); unit++) {
  621. struct periph_match_result *periph_result;
  622. /*
  623.  * We shouldn't have anything other than peripheral
  624.  * matches in here.  If we do, it means an error in the
  625.  * device matching code in the transport layer.
  626.  */
  627. if (ccb.cdm.matches[unit].type != DEV_MATCH_PERIPH) {
  628. /* errmsgno(EX_BAD, "Kernel error! got periph match type %d!!n",*/
  629. if (scgp->errstr)
  630. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  631. "Kernel error! got periph match type %d!!",
  632. ccb.cdm.matches[unit].type);
  633. free(ccb.cdm.matches);
  634. return(-1);
  635. }
  636. periph_result = &ccb.cdm.matches[unit].result.periph_result;
  637. sprintf(name, "/dev/%s%d", periph_result->periph_name,
  638. periph_result->unit_number);
  639. /*
  640.  * cam_open_pass() avoids all lookup and translation from
  641.  * "regular device name" to passthrough unit number and
  642.  * just opens the device in question as a passthrough device.
  643.  */
  644. scglocal(scgp)->cam_devices[unit] = cam_open_pass(name, O_RDWR, NULL);
  645. /*
  646.  * If we get back NULL from the open routine, it wasn't
  647.  * able to open the given passthrough device for one reason
  648.  * or another.
  649.  */
  650. if (scglocal(scgp)->cam_devices[unit] == NULL) {
  651. #ifdef OLD
  652. errmsgno(EX_BAD, "Error opening /dev/%s%dn",
  653. periph_result->periph_name,
  654. periph_result->unit_number);
  655. errmsgno(EX_BAD, "%sn", cam_errbuf);
  656. #endif
  657. if (scgp->errstr)
  658. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  659. "Error opening /dev/%s%d Cam error '%s'",
  660. periph_result->periph_name,
  661. periph_result->unit_number,
  662. cam_errbuf);
  663. break;
  664. }
  665. nopen++;
  666. }
  667. free(ccb.cdm.matches);
  668. return (nopen);
  669. }
  670. EXPORT int
  671. scsi_close(scgp)
  672. SCSI *scgp;
  673. {
  674. register int i;
  675. if (scgp->local == NULL)
  676. return (-1);
  677. for (i = 0; i <= CAM_MAXDEVS; i++) {
  678. if (scglocal(scgp)->cam_devices[i] != (struct cam_device *)-1)
  679. cam_close_device(scglocal(scgp)->cam_devices[i]);
  680. scglocal(scgp)->cam_devices[i] = (struct cam_device *)-1;
  681.         }
  682. return (0);
  683. }
  684. LOCAL
  685. long scsi_maxdma(scgp)
  686. SCSI *scgp;
  687. {
  688. #ifdef DFLTPHYS
  689. return (DFLTPHYS);
  690. #else
  691. return (MAXPHYS);
  692. #endif
  693. }
  694. EXPORT void *
  695. scsi_getbuf(scgp, amt)
  696. SCSI *scgp;
  697. long amt;
  698. {
  699. if (amt <= 0 || amt > scsi_maxdma(scgp))
  700. return ((void *)0);
  701. if (scgp->debug)
  702. printf("scsi_getbuf: %ld bytesn", amt);
  703. scgp->bufbase = valloc((size_t)(amt));
  704. return (scgp->bufbase);
  705. }
  706. EXPORT void
  707. scsi_freebuf(scgp)
  708. SCSI *scgp;
  709. {
  710. if (scgp->bufbase)
  711. free(scgp->bufbase);
  712. scgp->bufbase = NULL;
  713. }
  714. EXPORT
  715. BOOL scsi_havebus(scgp, busno)
  716. SCSI *scgp;
  717. int busno;
  718. {
  719. int unit;
  720. if (scgp->local == NULL)
  721. return (FALSE);
  722. /*
  723.  * There's a "cleaner" way to do this, using the matching code, but
  724.  * it would involve more code than this solution...
  725.  */
  726. for (unit = 0; scglocal(scgp)->cam_devices[unit] != (struct cam_device *)-1; unit++) {
  727. if (scglocal(scgp)->cam_devices[unit] == NULL)
  728. continue;
  729. if (scglocal(scgp)->cam_devices[unit]->path_id == busno)
  730. return (TRUE);
  731. }
  732. return (FALSE);
  733. }
  734. EXPORT
  735. int scsi_fileno(scgp, busno, unit, tlun)
  736. SCSI *scgp;
  737. int busno;
  738. int unit;
  739. int tlun;
  740. {
  741. int i;
  742. if (scgp->local == NULL)
  743. return (-1);
  744. for (i = 0; scglocal(scgp)->cam_devices[i] != (struct cam_device *)-1; i++) {
  745. if (scglocal(scgp)->cam_devices[i] == NULL)
  746. continue;
  747. if ((scglocal(scgp)->cam_devices[i]->path_id == busno) &&
  748.     (scglocal(scgp)->cam_devices[i]->target_id == unit) &&
  749.     (scglocal(scgp)->cam_devices[i]->target_lun == tlun))
  750. return (i);
  751. }
  752. return (-1);
  753. }
  754. EXPORT int
  755. scsi_initiator_id(scgp)
  756. SCSI *scgp;
  757. {
  758. return (-1);
  759. }
  760. EXPORT
  761. int scsi_isatapi(scgp)
  762. SCSI *scgp;
  763. {
  764. return (FALSE);
  765. }
  766. EXPORT
  767. int scsireset(scgp)
  768. SCSI *scgp;
  769. {
  770. /* XXX synchronous reset command - is this wise? */
  771. return (-1);
  772. }
  773. LOCAL int
  774. scsi_send(scgp, unit, sp)
  775. SCSI *scgp;
  776. int unit;
  777. struct scg_cmd *sp;
  778. {
  779. struct cam_device *dev;
  780. union ccb ccb_space;
  781. union ccb *ccb = &ccb_space;
  782. int rv, result;
  783. u_int32_t ccb_flags;
  784. if (unit < 0) {
  785. #if 0
  786. fprintf(stderr, "attempt to reference invalid unit %dn", unit);
  787. #endif
  788. sp->error = SCG_FATAL;
  789. return (0);
  790. }
  791. dev = scglocal(scgp)->cam_devices[unit];
  792. fillbytes(&ccb->ccb_h, sizeof(struct ccb_hdr), '');
  793. ccb->ccb_h.path_id = dev->path_id;
  794. ccb->ccb_h.target_id = dev->target_id;
  795. ccb->ccb_h.target_lun = dev->target_lun;
  796. /* Build the CCB */
  797. fillbytes(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio), '');
  798. movebytes(sp->cdb.cmd_cdb, &ccb->csio.cdb_io.cdb_bytes, sp->cdb_len);
  799. /*
  800.  * Set the data direction flags.
  801.  */
  802. if (sp->size != 0) {
  803. ccb_flags = (sp->flags & SCG_RECV_DATA) ? CAM_DIR_IN :
  804.    CAM_DIR_OUT;
  805. } else {
  806. ccb_flags = CAM_DIR_NONE;
  807. }
  808. ccb_flags |= CAM_DEV_QFRZDIS;
  809. /*
  810.  * If you don't want to bother with sending tagged commands under CAM,
  811.  * we don't need to do anything to cdrecord.  If you want to send
  812.  * tagged commands to those devices that support it, we'll need to set
  813.  * the tag action valid field like this in scsi_send():
  814.    *         
  815.  *        ccb_flags |= CAM_DEV_QFRZDIS | CAM_TAG_ACTION_VALID;
  816.  */
  817. cam_fill_csio(&ccb->csio,
  818.       /* retries */ 1,
  819.       /* cbfncp */ NULL,
  820.       /* flags */ ccb_flags,
  821.       /* tag_action */ MSG_SIMPLE_Q_TAG,
  822.       /* data_ptr */ (u_int8_t *)sp->addr,
  823.       /* dxfer_len */ sp->size,
  824.       /* sense_len */ SSD_FULL_SIZE,
  825.       /* cdb_len */ sp->cdb_len,
  826.       /* timeout */ sp->timeout * 1000);
  827. /* Run the command */
  828. errno = 0;
  829. if ((rv = cam_send_ccb(dev, ccb)) == -1) {
  830. return (rv);
  831. } else {
  832. /*
  833.  * Check for command status.  Selection timeouts are fatal.
  834.  * For command timeouts, we pass back the appropriate
  835.  * error.  If we completed successfully, there's (obviously)
  836.  * no error.  We declare anything else "retryable".
  837.  */
  838. switch(ccb->ccb_h.status & CAM_STATUS_MASK) {
  839. case CAM_SEL_TIMEOUT:
  840. result = SCG_FATAL;
  841. break;
  842. case CAM_CMD_TIMEOUT:
  843. result = SCG_TIMEOUT;
  844. break;
  845. case CAM_REQ_CMP:
  846. result = SCG_NO_ERROR;
  847. break;
  848. default:
  849. result = SCG_RETRYABLE;
  850. break;
  851. }
  852. }
  853. sp->error = result;
  854. if (result != SCG_NO_ERROR)
  855. sp->ux_errno = EIO;
  856. /* Pass the result back up */
  857. fillbytes(&sp->scb, sizeof(sp->scb), '');
  858. fillbytes(&sp->u_sense.cmd_sense, sizeof(sp->u_sense.cmd_sense), '');
  859. sp->resid = ccb->csio.resid;
  860. sp->sense_count = SSD_FULL_SIZE - ccb->csio.sense_resid;
  861. /*
  862.  * Determine how much room we have for sense data.
  863.  */
  864. if (sp->sense_count > SCG_MAX_SENSE)
  865. sp->sense_count = SCG_MAX_SENSE;
  866. /* Copy the sense data out */
  867. movebytes(&ccb->csio.sense_data, &sp->u_sense.cmd_sense, sp->sense_count);
  868. sp->u_scb.cmd_scb[0] = ccb->csio.scsi_status;
  869. return (0);
  870. }
  871. #undef scsi_sense
  872. #undef scsi_inquiry
  873. #define sense u_sense.Sense
  874. #endif /* BSD_CAM */