1 /* 2 * Common functions for SCSI Interface Modules (SIMs). 3 * 4 * Copyright (c) 1997 Justin T. Gibbs. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions, and the following disclaimer, 12 * without modification, immediately at the beginning of the file. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: src/sys/cam/cam_sim.c,v 1.3 1999/08/28 00:40:42 peter Exp $ 29 * $DragonFly: src/sys/bus/cam/cam_sim.c,v 1.9 2007/06/14 01:09:30 dillon Exp $ 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/malloc.h> 35 36 #include "cam.h" 37 #include "cam_ccb.h" 38 #include "cam_sim.h" 39 #include "cam_queue.h" 40 #include "cam_xpt_sim.h" 41 42 #define CAM_PATH_ANY (u_int32_t)-1 43 44 struct cam_devq * 45 cam_simq_alloc(u_int32_t max_sim_transactions) 46 { 47 return (cam_devq_alloc(/*size*/0, max_sim_transactions)); 48 } 49 50 void 51 cam_simq_release(struct cam_devq *devq) 52 { 53 cam_devq_release(devq); 54 } 55 56 /* 57 * cam_sim_alloc() may potentially be called from an interrupt (?) but 58 * unexpected things happen to the system if malloc() returns NULL so we 59 * use M_INTWAIT anyway. 60 */ 61 struct cam_sim * 62 cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll, 63 const char *sim_name, void *softc, u_int32_t unit, 64 int max_dev_transactions, 65 int max_tagged_dev_transactions, struct cam_devq *queue) 66 { 67 struct cam_sim *sim; 68 69 /* 70 * XXX ahd was limited to 256 instead of 512 for unknown reasons, 71 * move that to a global limit here. We may be able to remove this 72 * code, needs testing. 73 */ 74 if (max_dev_transactions > 256) 75 max_dev_transactions = 256; 76 if (max_tagged_dev_transactions > 256) 77 max_tagged_dev_transactions = 256; 78 79 /* 80 * Allocate a simq or use the supplied (possibly shared) simq. 81 */ 82 if (queue == NULL) 83 queue = cam_simq_alloc(max_tagged_dev_transactions); 84 else 85 cam_devq_reference(queue); 86 87 sim = kmalloc(sizeof(struct cam_sim), M_DEVBUF, M_INTWAIT | M_ZERO); 88 sim->sim_action = sim_action; 89 sim->sim_poll = sim_poll; 90 sim->sim_name = sim_name; 91 sim->softc = softc; 92 sim->path_id = CAM_PATH_ANY; 93 sim->unit_number = unit; 94 sim->bus_id = 0; /* set in xpt_bus_register */ 95 sim->max_tagged_dev_openings = max_tagged_dev_transactions; 96 sim->max_dev_openings = max_dev_transactions; 97 sim->flags = 0; 98 sim->refcount = 1; 99 callout_init(&sim->c_handle); 100 sim->devq = queue; 101 102 return (sim); 103 } 104 105 static void deadsim_poll(struct cam_sim *sim); 106 static void deadsim_action(struct cam_sim *sim, union ccb *ccb); 107 108 void 109 cam_sim_free(struct cam_sim *sim) 110 { 111 sim->sim_action = deadsim_action; 112 sim->sim_poll = deadsim_poll; 113 cam_sim_release(sim, CAM_SIM_SOFTC); 114 } 115 116 /* 117 * Note: the devq is still used by individual peripherals even if the 118 * backend sim disappears, so do not destroy it until the sim itself 119 * is no longer needed. 120 */ 121 void 122 cam_sim_release(struct cam_sim *sim, int flags) 123 { 124 if (flags & CAM_SIM_SOFTC) 125 sim->softc = NULL; 126 if (sim->refcount == 1) { 127 if (sim->devq) { 128 cam_simq_release(sim->devq); 129 sim->devq = NULL; 130 } 131 sim->refcount = 0; 132 kfree(sim, M_DEVBUF); 133 } else { 134 --sim->refcount; 135 } 136 } 137 138 void 139 cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id) 140 { 141 sim->path_id = path_id; 142 } 143 144 /* 145 * Dead sim poll and action functions. The backend to the sim has gone 146 * away, aka usb, scsi device, etc... deal with it. 147 */ 148 static void 149 deadsim_poll(struct cam_sim *sim) 150 { 151 /* empty */ 152 } 153 154 static void 155 deadsim_action(struct cam_sim *sim, union ccb *ccb) 156 { 157 ccb->ccb_h.status = CAM_TID_INVALID; 158 xpt_done(ccb); 159 } 160 161