vscsi.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /* $OpenBSD: vscsi.c,v 1.38 2015/03/14 03:38:46 jsg Exp $ */
  2. /*
  3. * Copyright (c) 2008 David Gwynne <dlg@openbsd.org>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <sys/param.h>
  18. #include <sys/systm.h>
  19. #include <sys/kernel.h>
  20. #include <sys/malloc.h>
  21. #include <sys/device.h>
  22. #include <sys/conf.h>
  23. #include <sys/queue.h>
  24. #include <sys/rwlock.h>
  25. #include <sys/pool.h>
  26. #include <sys/task.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/poll.h>
  29. #include <sys/selinfo.h>
  30. #include <scsi/scsi_all.h>
  31. #include <scsi/scsiconf.h>
  32. #include <dev/vscsivar.h>
  33. int vscsi_match(struct device *, void *, void *);
  34. void vscsi_attach(struct device *, struct device *, void *);
  35. void vscsi_shutdown(void *);
  36. struct vscsi_ccb {
  37. TAILQ_ENTRY(vscsi_ccb) ccb_entry;
  38. int ccb_tag;
  39. struct scsi_xfer *ccb_xs;
  40. size_t ccb_datalen;
  41. };
  42. TAILQ_HEAD(vscsi_ccb_list, vscsi_ccb);
  43. enum vscsi_state {
  44. VSCSI_S_CLOSED,
  45. VSCSI_S_CONFIG,
  46. VSCSI_S_RUNNING
  47. };
  48. struct vscsi_softc {
  49. struct device sc_dev;
  50. struct scsi_link sc_link;
  51. struct scsibus_softc *sc_scsibus;
  52. struct mutex sc_state_mtx;
  53. enum vscsi_state sc_state;
  54. u_int sc_ref_count;
  55. struct pool sc_ccb_pool;
  56. struct scsi_iopool sc_iopool;
  57. struct vscsi_ccb_list sc_ccb_i2t;
  58. struct vscsi_ccb_list sc_ccb_t2i;
  59. int sc_ccb_tag;
  60. struct mutex sc_poll_mtx;
  61. struct rwlock sc_ioc_lock;
  62. struct selinfo sc_sel;
  63. struct mutex sc_sel_mtx;
  64. };
  65. #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
  66. #define DEV2SC(_d) ((struct vscsi_softc *)device_lookup(&vscsi_cd, minor(_d)))
  67. struct cfattach vscsi_ca = {
  68. sizeof(struct vscsi_softc),
  69. vscsi_match,
  70. vscsi_attach
  71. };
  72. struct cfdriver vscsi_cd = {
  73. NULL,
  74. "vscsi",
  75. DV_DULL
  76. };
  77. void vscsi_cmd(struct scsi_xfer *);
  78. int vscsi_probe(struct scsi_link *);
  79. void vscsi_free(struct scsi_link *);
  80. struct scsi_adapter vscsi_switch = {
  81. vscsi_cmd,
  82. scsi_minphys,
  83. vscsi_probe,
  84. vscsi_free
  85. };
  86. int vscsi_i2t(struct vscsi_softc *, struct vscsi_ioc_i2t *);
  87. int vscsi_data(struct vscsi_softc *, struct vscsi_ioc_data *, int);
  88. int vscsi_t2i(struct vscsi_softc *, struct vscsi_ioc_t2i *);
  89. int vscsi_devevent(struct vscsi_softc *, u_long,
  90. struct vscsi_ioc_devevent *);
  91. void vscsi_devevent_task(void *);
  92. void vscsi_done(struct vscsi_softc *, struct vscsi_ccb *);
  93. void * vscsi_ccb_get(void *);
  94. void vscsi_ccb_put(void *, void *);
  95. void filt_vscsidetach(struct knote *);
  96. int filt_vscsiread(struct knote *, long);
  97. struct filterops vscsi_filtops = {
  98. 1,
  99. NULL,
  100. filt_vscsidetach,
  101. filt_vscsiread
  102. };
  103. int
  104. vscsi_match(struct device *parent, void *match, void *aux)
  105. {
  106. return (1);
  107. }
  108. void
  109. vscsi_attach(struct device *parent, struct device *self, void *aux)
  110. {
  111. struct vscsi_softc *sc = (struct vscsi_softc *)self;
  112. struct scsibus_attach_args saa;
  113. printf("\n");
  114. mtx_init(&sc->sc_state_mtx, IPL_BIO);
  115. sc->sc_state = VSCSI_S_CLOSED;
  116. TAILQ_INIT(&sc->sc_ccb_i2t);
  117. TAILQ_INIT(&sc->sc_ccb_t2i);
  118. mtx_init(&sc->sc_poll_mtx, IPL_BIO);
  119. mtx_init(&sc->sc_sel_mtx, IPL_BIO);
  120. rw_init(&sc->sc_ioc_lock, "vscsiioc");
  121. scsi_iopool_init(&sc->sc_iopool, sc, vscsi_ccb_get, vscsi_ccb_put);
  122. sc->sc_link.adapter = &vscsi_switch;
  123. sc->sc_link.adapter_softc = sc;
  124. sc->sc_link.adapter_target = 256;
  125. sc->sc_link.adapter_buswidth = 256;
  126. sc->sc_link.openings = 16;
  127. sc->sc_link.pool = &sc->sc_iopool;
  128. memset(&saa, 0, sizeof(saa));
  129. saa.saa_sc_link = &sc->sc_link;
  130. sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev,
  131. &saa, scsiprint);
  132. }
  133. void
  134. vscsi_cmd(struct scsi_xfer *xs)
  135. {
  136. struct scsi_link *link = xs->sc_link;
  137. struct vscsi_softc *sc = link->adapter_softc;
  138. struct vscsi_ccb *ccb = xs->io;
  139. int polled = ISSET(xs->flags, SCSI_POLL);
  140. int running = 0;
  141. if (ISSET(xs->flags, SCSI_POLL) && ISSET(xs->flags, SCSI_NOSLEEP)) {
  142. printf("%s: POLL && NOSLEEP for 0x%02x\n", DEVNAME(sc),
  143. xs->cmd->opcode);
  144. xs->error = XS_DRIVER_STUFFUP;
  145. scsi_done(xs);
  146. return;
  147. }
  148. ccb->ccb_xs = xs;
  149. mtx_enter(&sc->sc_state_mtx);
  150. if (sc->sc_state == VSCSI_S_RUNNING) {
  151. running = 1;
  152. TAILQ_INSERT_TAIL(&sc->sc_ccb_i2t, ccb, ccb_entry);
  153. }
  154. mtx_leave(&sc->sc_state_mtx);
  155. if (!running) {
  156. xs->error = XS_DRIVER_STUFFUP;
  157. scsi_done(xs);
  158. return;
  159. }
  160. selwakeup(&sc->sc_sel);
  161. if (polled) {
  162. mtx_enter(&sc->sc_poll_mtx);
  163. while (ccb->ccb_xs != NULL)
  164. msleep(ccb, &sc->sc_poll_mtx, PRIBIO, "vscsipoll", 0);
  165. mtx_leave(&sc->sc_poll_mtx);
  166. scsi_done(xs);
  167. }
  168. }
  169. void
  170. vscsi_done(struct vscsi_softc *sc, struct vscsi_ccb *ccb)
  171. {
  172. struct scsi_xfer *xs = ccb->ccb_xs;
  173. if (ISSET(xs->flags, SCSI_POLL)) {
  174. mtx_enter(&sc->sc_poll_mtx);
  175. ccb->ccb_xs = NULL;
  176. wakeup(ccb);
  177. mtx_leave(&sc->sc_poll_mtx);
  178. } else
  179. scsi_done(xs);
  180. }
  181. int
  182. vscsi_probe(struct scsi_link *link)
  183. {
  184. struct vscsi_softc *sc = link->adapter_softc;
  185. int rv = 0;
  186. mtx_enter(&sc->sc_state_mtx);
  187. if (sc->sc_state == VSCSI_S_RUNNING)
  188. sc->sc_ref_count++;
  189. else
  190. rv = ENXIO;
  191. mtx_leave(&sc->sc_state_mtx);
  192. return (rv);
  193. }
  194. void
  195. vscsi_free(struct scsi_link *link)
  196. {
  197. struct vscsi_softc *sc = link->adapter_softc;
  198. mtx_enter(&sc->sc_state_mtx);
  199. sc->sc_ref_count--;
  200. if (sc->sc_state != VSCSI_S_RUNNING && sc->sc_ref_count == 0)
  201. wakeup(&sc->sc_ref_count);
  202. mtx_leave(&sc->sc_state_mtx);
  203. }
  204. int
  205. vscsiopen(dev_t dev, int flags, int mode, struct proc *p)
  206. {
  207. struct vscsi_softc *sc = DEV2SC(dev);
  208. enum vscsi_state state = VSCSI_S_RUNNING;
  209. int rv = 0;
  210. if (sc == NULL)
  211. return (ENXIO);
  212. mtx_enter(&sc->sc_state_mtx);
  213. if (sc->sc_state != VSCSI_S_CLOSED)
  214. rv = EBUSY;
  215. else
  216. sc->sc_state = VSCSI_S_CONFIG;
  217. mtx_leave(&sc->sc_state_mtx);
  218. if (rv != 0) {
  219. device_unref(&sc->sc_dev);
  220. return (rv);
  221. }
  222. pool_init(&sc->sc_ccb_pool, sizeof(struct vscsi_ccb), 0, 0, 0,
  223. "vscsiccb", NULL);
  224. pool_setipl(&sc->sc_ccb_pool, IPL_BIO);
  225. /* we need to guarantee some ccbs will be available for the iopool */
  226. rv = pool_prime(&sc->sc_ccb_pool, 8);
  227. if (rv != 0) {
  228. pool_destroy(&sc->sc_ccb_pool);
  229. state = VSCSI_S_CLOSED;
  230. }
  231. /* commit changes */
  232. mtx_enter(&sc->sc_state_mtx);
  233. sc->sc_state = state;
  234. mtx_leave(&sc->sc_state_mtx);
  235. device_unref(&sc->sc_dev);
  236. return (rv);
  237. }
  238. int
  239. vscsiioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
  240. {
  241. struct vscsi_softc *sc = DEV2SC(dev);
  242. int read = 0;
  243. int err = 0;
  244. if (sc == NULL)
  245. return (ENXIO);
  246. rw_enter_write(&sc->sc_ioc_lock);
  247. switch (cmd) {
  248. case VSCSI_I2T:
  249. err = vscsi_i2t(sc, (struct vscsi_ioc_i2t *)addr);
  250. break;
  251. case VSCSI_DATA_READ:
  252. read = 1;
  253. case VSCSI_DATA_WRITE:
  254. err = vscsi_data(sc, (struct vscsi_ioc_data *)addr, read);
  255. break;
  256. case VSCSI_T2I:
  257. err = vscsi_t2i(sc, (struct vscsi_ioc_t2i *)addr);
  258. break;
  259. case VSCSI_REQPROBE:
  260. case VSCSI_REQDETACH:
  261. err = vscsi_devevent(sc, cmd,
  262. (struct vscsi_ioc_devevent *)addr);
  263. break;
  264. default:
  265. err = ENOTTY;
  266. break;
  267. }
  268. rw_exit_write(&sc->sc_ioc_lock);
  269. device_unref(&sc->sc_dev);
  270. return (err);
  271. }
  272. int
  273. vscsi_i2t(struct vscsi_softc *sc, struct vscsi_ioc_i2t *i2t)
  274. {
  275. struct vscsi_ccb *ccb;
  276. struct scsi_xfer *xs;
  277. struct scsi_link *link;
  278. mtx_enter(&sc->sc_state_mtx);
  279. ccb = TAILQ_FIRST(&sc->sc_ccb_i2t);
  280. if (ccb != NULL)
  281. TAILQ_REMOVE(&sc->sc_ccb_i2t, ccb, ccb_entry);
  282. mtx_leave(&sc->sc_state_mtx);
  283. if (ccb == NULL)
  284. return (EAGAIN);
  285. xs = ccb->ccb_xs;
  286. link = xs->sc_link;
  287. i2t->tag = ccb->ccb_tag;
  288. i2t->target = link->target;
  289. i2t->lun = link->lun;
  290. memcpy(&i2t->cmd, xs->cmd, xs->cmdlen);
  291. i2t->cmdlen = xs->cmdlen;
  292. i2t->datalen = xs->datalen;
  293. switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
  294. case SCSI_DATA_IN:
  295. i2t->direction = VSCSI_DIR_READ;
  296. break;
  297. case SCSI_DATA_OUT:
  298. i2t->direction = VSCSI_DIR_WRITE;
  299. break;
  300. default:
  301. i2t->direction = VSCSI_DIR_NONE;
  302. break;
  303. }
  304. TAILQ_INSERT_TAIL(&sc->sc_ccb_t2i, ccb, ccb_entry);
  305. return (0);
  306. }
  307. int
  308. vscsi_data(struct vscsi_softc *sc, struct vscsi_ioc_data *data, int read)
  309. {
  310. struct vscsi_ccb *ccb;
  311. struct scsi_xfer *xs;
  312. int xsread;
  313. u_int8_t *buf;
  314. int rv = EINVAL;
  315. TAILQ_FOREACH(ccb, &sc->sc_ccb_t2i, ccb_entry) {
  316. if (ccb->ccb_tag == data->tag)
  317. break;
  318. }
  319. if (ccb == NULL)
  320. return (EFAULT);
  321. xs = ccb->ccb_xs;
  322. if (data->datalen > xs->datalen - ccb->ccb_datalen)
  323. return (ENOMEM);
  324. switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
  325. case SCSI_DATA_IN:
  326. xsread = 1;
  327. break;
  328. case SCSI_DATA_OUT:
  329. xsread = 0;
  330. break;
  331. default:
  332. return (EINVAL);
  333. }
  334. if (read != xsread)
  335. return (EINVAL);
  336. buf = xs->data;
  337. buf += ccb->ccb_datalen;
  338. if (read)
  339. rv = copyin(data->data, buf, data->datalen);
  340. else
  341. rv = copyout(buf, data->data, data->datalen);
  342. if (rv == 0)
  343. ccb->ccb_datalen += data->datalen;
  344. return (rv);
  345. }
  346. int
  347. vscsi_t2i(struct vscsi_softc *sc, struct vscsi_ioc_t2i *t2i)
  348. {
  349. struct vscsi_ccb *ccb;
  350. struct scsi_xfer *xs;
  351. struct scsi_link *link;
  352. int rv = 0;
  353. TAILQ_FOREACH(ccb, &sc->sc_ccb_t2i, ccb_entry) {
  354. if (ccb->ccb_tag == t2i->tag)
  355. break;
  356. }
  357. if (ccb == NULL)
  358. return (EFAULT);
  359. TAILQ_REMOVE(&sc->sc_ccb_t2i, ccb, ccb_entry);
  360. xs = ccb->ccb_xs;
  361. link = xs->sc_link;
  362. xs->resid = xs->datalen - ccb->ccb_datalen;
  363. xs->status = SCSI_OK;
  364. switch (t2i->status) {
  365. case VSCSI_STAT_DONE:
  366. xs->error = XS_NOERROR;
  367. break;
  368. case VSCSI_STAT_SENSE:
  369. xs->error = XS_SENSE;
  370. memcpy(&xs->sense, &t2i->sense, sizeof(xs->sense));
  371. break;
  372. case VSCSI_STAT_RESET:
  373. xs->error = XS_RESET;
  374. break;
  375. case VSCSI_STAT_ERR:
  376. default:
  377. xs->error = XS_DRIVER_STUFFUP;
  378. break;
  379. }
  380. vscsi_done(sc, ccb);
  381. return (rv);
  382. }
  383. struct vscsi_devevent_task {
  384. struct vscsi_softc *sc;
  385. struct task t;
  386. struct vscsi_ioc_devevent de;
  387. u_long cmd;
  388. };
  389. int
  390. vscsi_devevent(struct vscsi_softc *sc, u_long cmd,
  391. struct vscsi_ioc_devevent *de)
  392. {
  393. struct vscsi_devevent_task *dt;
  394. dt = malloc(sizeof(*dt), M_TEMP, M_WAITOK | M_CANFAIL);
  395. if (dt == NULL)
  396. return (ENOMEM);
  397. task_set(&dt->t, vscsi_devevent_task, dt);
  398. dt->sc = sc;
  399. dt->de = *de;
  400. dt->cmd = cmd;
  401. device_ref(&sc->sc_dev);
  402. task_add(systq, &dt->t);
  403. return (0);
  404. }
  405. void
  406. vscsi_devevent_task(void *xdt)
  407. {
  408. struct vscsi_devevent_task *dt = xdt;
  409. struct vscsi_softc *sc = dt->sc;
  410. int state;
  411. mtx_enter(&sc->sc_state_mtx);
  412. state = sc->sc_state;
  413. mtx_leave(&sc->sc_state_mtx);
  414. if (state != VSCSI_S_RUNNING)
  415. goto gone;
  416. switch (dt->cmd) {
  417. case VSCSI_REQPROBE:
  418. scsi_probe(sc->sc_scsibus, dt->de.target, dt->de.lun);
  419. break;
  420. case VSCSI_REQDETACH:
  421. scsi_detach(sc->sc_scsibus, dt->de.target, dt->de.lun,
  422. DETACH_FORCE);
  423. break;
  424. #ifdef DIAGNOSTIC
  425. default:
  426. panic("unexpected vscsi_devevent cmd");
  427. /* NOTREACHED */
  428. #endif
  429. }
  430. gone:
  431. device_unref(&sc->sc_dev);
  432. free(dt, M_TEMP, 0);
  433. }
  434. int
  435. vscsipoll(dev_t dev, int events, struct proc *p)
  436. {
  437. struct vscsi_softc *sc = DEV2SC(dev);
  438. int revents = 0;
  439. if (sc == NULL)
  440. return (ENXIO);
  441. if (events & (POLLIN | POLLRDNORM)) {
  442. mtx_enter(&sc->sc_state_mtx);
  443. if (!TAILQ_EMPTY(&sc->sc_ccb_i2t))
  444. revents |= events & (POLLIN | POLLRDNORM);
  445. mtx_leave(&sc->sc_state_mtx);
  446. }
  447. if (revents == 0) {
  448. if (events & (POLLIN | POLLRDNORM))
  449. selrecord(p, &sc->sc_sel);
  450. }
  451. device_unref(&sc->sc_dev);
  452. return (revents);
  453. }
  454. int
  455. vscsikqfilter(dev_t dev, struct knote *kn)
  456. {
  457. struct vscsi_softc *sc = DEV2SC(dev);
  458. struct klist *klist;
  459. if (sc == NULL)
  460. return (ENXIO);
  461. klist = &sc->sc_sel.si_note;
  462. switch (kn->kn_filter) {
  463. case EVFILT_READ:
  464. kn->kn_fop = &vscsi_filtops;
  465. break;
  466. default:
  467. device_unref(&sc->sc_dev);
  468. return (EINVAL);
  469. }
  470. kn->kn_hook = sc;
  471. mtx_enter(&sc->sc_sel_mtx);
  472. SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  473. mtx_leave(&sc->sc_sel_mtx);
  474. /* device ref is given to the knote in the klist */
  475. return (0);
  476. }
  477. void
  478. filt_vscsidetach(struct knote *kn)
  479. {
  480. struct vscsi_softc *sc = kn->kn_hook;
  481. struct klist *klist = &sc->sc_sel.si_note;
  482. mtx_enter(&sc->sc_sel_mtx);
  483. SLIST_REMOVE(klist, kn, knote, kn_selnext);
  484. mtx_leave(&sc->sc_sel_mtx);
  485. device_unref(&sc->sc_dev);
  486. }
  487. int
  488. filt_vscsiread(struct knote *kn, long hint)
  489. {
  490. struct vscsi_softc *sc = kn->kn_hook;
  491. int event = 0;
  492. mtx_enter(&sc->sc_state_mtx);
  493. if (!TAILQ_EMPTY(&sc->sc_ccb_i2t))
  494. event = 1;
  495. mtx_leave(&sc->sc_state_mtx);
  496. return (event);
  497. }
  498. int
  499. vscsiclose(dev_t dev, int flags, int mode, struct proc *p)
  500. {
  501. struct vscsi_softc *sc = DEV2SC(dev);
  502. struct vscsi_ccb *ccb;
  503. if (sc == NULL)
  504. return (ENXIO);
  505. mtx_enter(&sc->sc_state_mtx);
  506. KASSERT(sc->sc_state == VSCSI_S_RUNNING);
  507. sc->sc_state = VSCSI_S_CONFIG;
  508. mtx_leave(&sc->sc_state_mtx);
  509. scsi_activate(sc->sc_scsibus, -1, -1, DVACT_DEACTIVATE);
  510. while ((ccb = TAILQ_FIRST(&sc->sc_ccb_t2i)) != NULL) {
  511. TAILQ_REMOVE(&sc->sc_ccb_t2i, ccb, ccb_entry);
  512. ccb->ccb_xs->error = XS_RESET;
  513. vscsi_done(sc, ccb);
  514. }
  515. while ((ccb = TAILQ_FIRST(&sc->sc_ccb_i2t)) != NULL) {
  516. TAILQ_REMOVE(&sc->sc_ccb_i2t, ccb, ccb_entry);
  517. ccb->ccb_xs->error = XS_RESET;
  518. vscsi_done(sc, ccb);
  519. }
  520. scsi_req_detach(sc->sc_scsibus, -1, -1, DETACH_FORCE);
  521. mtx_enter(&sc->sc_state_mtx);
  522. while (sc->sc_ref_count > 0) {
  523. msleep(&sc->sc_ref_count, &sc->sc_state_mtx,
  524. PRIBIO, "vscsiref", 0);
  525. }
  526. mtx_leave(&sc->sc_state_mtx);
  527. pool_destroy(&sc->sc_ccb_pool);
  528. mtx_enter(&sc->sc_state_mtx);
  529. sc->sc_state = VSCSI_S_CLOSED;
  530. mtx_leave(&sc->sc_state_mtx);
  531. device_unref(&sc->sc_dev);
  532. return (0);
  533. }
  534. void *
  535. vscsi_ccb_get(void *cookie)
  536. {
  537. struct vscsi_softc *sc = cookie;
  538. struct vscsi_ccb *ccb = NULL;
  539. ccb = pool_get(&sc->sc_ccb_pool, PR_NOWAIT);
  540. if (ccb != NULL) {
  541. ccb->ccb_tag = sc->sc_ccb_tag++;
  542. ccb->ccb_datalen = 0;
  543. }
  544. return (ccb);
  545. }
  546. void
  547. vscsi_ccb_put(void *cookie, void *io)
  548. {
  549. struct vscsi_softc *sc = cookie;
  550. struct vscsi_ccb *ccb = io;
  551. pool_put(&sc->sc_ccb_pool, ccb);
  552. }