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

SCSI/ASPI

开发平台:

MultiPlatform

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