1898b0535SWarner Losh /*- 28b8a9b1dSJustin T. Gibbs * Common functions for SCSI Interface Modules (SIMs). 38b8a9b1dSJustin T. Gibbs * 48b8a9b1dSJustin T. Gibbs * Copyright (c) 1997 Justin T. Gibbs. 58b8a9b1dSJustin T. Gibbs * All rights reserved. 68b8a9b1dSJustin T. Gibbs * 78b8a9b1dSJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 88b8a9b1dSJustin T. Gibbs * modification, are permitted provided that the following conditions 98b8a9b1dSJustin T. Gibbs * are met: 108b8a9b1dSJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 118b8a9b1dSJustin T. Gibbs * notice, this list of conditions, and the following disclaimer, 128b8a9b1dSJustin T. Gibbs * without modification, immediately at the beginning of the file. 138b8a9b1dSJustin T. Gibbs * 2. The name of the author may not be used to endorse or promote products 148b8a9b1dSJustin T. Gibbs * derived from this software without specific prior written permission. 158b8a9b1dSJustin T. Gibbs * 168b8a9b1dSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 178b8a9b1dSJustin T. Gibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 188b8a9b1dSJustin T. Gibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 198b8a9b1dSJustin T. Gibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 208b8a9b1dSJustin T. Gibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 218b8a9b1dSJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 228b8a9b1dSJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 238b8a9b1dSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 248b8a9b1dSJustin T. Gibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 258b8a9b1dSJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 268b8a9b1dSJustin T. Gibbs * SUCH DAMAGE. 278b8a9b1dSJustin T. Gibbs */ 288b8a9b1dSJustin T. Gibbs 299c963d87SDavid E. O'Brien #include <sys/cdefs.h> 309c963d87SDavid E. O'Brien __FBSDID("$FreeBSD$"); 319c963d87SDavid E. O'Brien 328b8a9b1dSJustin T. Gibbs #include <sys/param.h> 338b8a9b1dSJustin T. Gibbs #include <sys/systm.h> 348b8a9b1dSJustin T. Gibbs #include <sys/malloc.h> 35362abc44STai-hwa Liang #include <sys/kernel.h> 362b83592fSScott Long #include <sys/lock.h> 372b83592fSScott Long #include <sys/mutex.h> 388b8a9b1dSJustin T. Gibbs 398b8a9b1dSJustin T. Gibbs #include <cam/cam.h> 408b8a9b1dSJustin T. Gibbs #include <cam/cam_ccb.h> 418b8a9b1dSJustin T. Gibbs #include <cam/cam_sim.h> 428b8a9b1dSJustin T. Gibbs #include <cam/cam_queue.h> 438b8a9b1dSJustin T. Gibbs 448b8a9b1dSJustin T. Gibbs #define CAM_PATH_ANY (u_int32_t)-1 458b8a9b1dSJustin T. Gibbs 46362abc44STai-hwa Liang MALLOC_DEFINE(M_CAMSIM, "CAM SIM", "CAM SIM buffers"); 47362abc44STai-hwa Liang 488b8a9b1dSJustin T. Gibbs struct cam_devq * 498b8a9b1dSJustin T. Gibbs cam_simq_alloc(u_int32_t max_sim_transactions) 508b8a9b1dSJustin T. Gibbs { 518b8a9b1dSJustin T. Gibbs return (cam_devq_alloc(/*size*/0, max_sim_transactions)); 528b8a9b1dSJustin T. Gibbs } 538b8a9b1dSJustin T. Gibbs 548b8a9b1dSJustin T. Gibbs void 558b8a9b1dSJustin T. Gibbs cam_simq_free(struct cam_devq *devq) 568b8a9b1dSJustin T. Gibbs { 578b8a9b1dSJustin T. Gibbs cam_devq_free(devq); 588b8a9b1dSJustin T. Gibbs } 598b8a9b1dSJustin T. Gibbs 608b8a9b1dSJustin T. Gibbs struct cam_sim * 618b8a9b1dSJustin T. Gibbs cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll, 62e2138feeSJohn Baldwin const char *sim_name, void *softc, u_int32_t unit, 632b83592fSScott Long struct mtx *mtx, int max_dev_transactions, 649deea857SKenneth D. Merry int max_tagged_dev_transactions, struct cam_devq *queue) 658b8a9b1dSJustin T. Gibbs { 668b8a9b1dSJustin T. Gibbs struct cam_sim *sim; 678b8a9b1dSJustin T. Gibbs 682b83592fSScott Long if (mtx == NULL) 692b83592fSScott Long return (NULL); 702b83592fSScott Long 718b8a9b1dSJustin T. Gibbs sim = (struct cam_sim *)malloc(sizeof(struct cam_sim), 7283c5d981SAlexander Motin M_CAMSIM, M_ZERO | M_NOWAIT); 738b8a9b1dSJustin T. Gibbs 742b83592fSScott Long if (sim == NULL) 752b83592fSScott Long return (NULL); 762b83592fSScott Long 778b8a9b1dSJustin T. Gibbs sim->sim_action = sim_action; 788b8a9b1dSJustin T. Gibbs sim->sim_poll = sim_poll; 798b8a9b1dSJustin T. Gibbs sim->sim_name = sim_name; 808b8a9b1dSJustin T. Gibbs sim->softc = softc; 818b8a9b1dSJustin T. Gibbs sim->path_id = CAM_PATH_ANY; 828b8a9b1dSJustin T. Gibbs sim->unit_number = unit; 838b8a9b1dSJustin T. Gibbs sim->bus_id = 0; /* set in xpt_bus_register */ 848b8a9b1dSJustin T. Gibbs sim->max_tagged_dev_openings = max_tagged_dev_transactions; 858b8a9b1dSJustin T. Gibbs sim->max_dev_openings = max_dev_transactions; 868b8a9b1dSJustin T. Gibbs sim->flags = 0; 87fa6099fdSEdward Tomasz Napierala sim->refcount = 1; 888b8a9b1dSJustin T. Gibbs sim->devq = queue; 8983c5d981SAlexander Motin sim->max_ccbs = 8; /* Reserve for management purposes. */ 902b83592fSScott Long sim->mtx = mtx; 912b83592fSScott Long if (mtx == &Giant) { 922b83592fSScott Long sim->flags |= 0; 932b83592fSScott Long callout_init(&sim->callout, 0); 942b83592fSScott Long } else { 952b83592fSScott Long sim->flags |= CAM_SIM_MPSAFE; 962b83592fSScott Long callout_init(&sim->callout, 1); 978b8a9b1dSJustin T. Gibbs } 988b8a9b1dSJustin T. Gibbs 992b83592fSScott Long SLIST_INIT(&sim->ccb_freeq); 1009758cc83SScott Long TAILQ_INIT(&sim->sim_doneq); 1012b83592fSScott Long 1028b8a9b1dSJustin T. Gibbs return (sim); 1038b8a9b1dSJustin T. Gibbs } 1048b8a9b1dSJustin T. Gibbs 1058b8a9b1dSJustin T. Gibbs void 1068b8a9b1dSJustin T. Gibbs cam_sim_free(struct cam_sim *sim, int free_devq) 1078b8a9b1dSJustin T. Gibbs { 108fa6099fdSEdward Tomasz Napierala int error; 109fa6099fdSEdward Tomasz Napierala 110fa6099fdSEdward Tomasz Napierala sim->refcount--; 111fa6099fdSEdward Tomasz Napierala if (sim->refcount > 0) { 112fa6099fdSEdward Tomasz Napierala error = msleep(sim, sim->mtx, PRIBIO, "simfree", 0); 113fa6099fdSEdward Tomasz Napierala KASSERT(error == 0, ("invalid error value for msleep(9)")); 114fa6099fdSEdward Tomasz Napierala } 115fa6099fdSEdward Tomasz Napierala 116fa6099fdSEdward Tomasz Napierala KASSERT(sim->refcount == 0, ("sim->refcount == 0")); 117fa6099fdSEdward Tomasz Napierala 1188b8a9b1dSJustin T. Gibbs if (free_devq) 1198b8a9b1dSJustin T. Gibbs cam_simq_free(sim->devq); 120362abc44STai-hwa Liang free(sim, M_CAMSIM); 1218b8a9b1dSJustin T. Gibbs } 1228b8a9b1dSJustin T. Gibbs 1238b8a9b1dSJustin T. Gibbs void 124fa6099fdSEdward Tomasz Napierala cam_sim_release(struct cam_sim *sim) 125fa6099fdSEdward Tomasz Napierala { 126fa6099fdSEdward Tomasz Napierala KASSERT(sim->refcount >= 1, ("sim->refcount >= 1")); 1277412d60dSEdward Tomasz Napierala mtx_assert(sim->mtx, MA_OWNED); 128fa6099fdSEdward Tomasz Napierala 129fa6099fdSEdward Tomasz Napierala sim->refcount--; 1307412d60dSEdward Tomasz Napierala if (sim->refcount == 0) 131fa6099fdSEdward Tomasz Napierala wakeup(sim); 132fa6099fdSEdward Tomasz Napierala } 133fa6099fdSEdward Tomasz Napierala 134fa6099fdSEdward Tomasz Napierala void 135fa6099fdSEdward Tomasz Napierala cam_sim_hold(struct cam_sim *sim) 136fa6099fdSEdward Tomasz Napierala { 137fa6099fdSEdward Tomasz Napierala KASSERT(sim->refcount >= 1, ("sim->refcount >= 1")); 1387412d60dSEdward Tomasz Napierala mtx_assert(sim->mtx, MA_OWNED); 139fa6099fdSEdward Tomasz Napierala 140fa6099fdSEdward Tomasz Napierala sim->refcount++; 141fa6099fdSEdward Tomasz Napierala } 142fa6099fdSEdward Tomasz Napierala 143fa6099fdSEdward Tomasz Napierala void 1448b8a9b1dSJustin T. Gibbs cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id) 1458b8a9b1dSJustin T. Gibbs { 1468b8a9b1dSJustin T. Gibbs sim->path_id = path_id; 1478b8a9b1dSJustin T. Gibbs } 148