cam_periph.h revision 248868
1/*- 2 * Data structures and definitions for CAM peripheral ("type") drivers. 3 * 4 * Copyright (c) 1997, 1998 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: head/sys/cam/cam_periph.h 248868 2013-03-29 07:50:47Z mav $ 29 */ 30 31#ifndef _CAM_CAM_PERIPH_H 32#define _CAM_CAM_PERIPH_H 1 33 34#include <sys/queue.h> 35#include <cam/cam_sim.h> 36 37#ifdef _KERNEL 38 39struct devstat; 40 41extern struct cam_periph *xpt_periph; 42 43extern struct periph_driver **periph_drivers; 44void periphdriver_register(void *); 45void periphdriver_init(int level); 46 47#include <sys/module.h> 48#define PERIPHDRIVER_DECLARE(name, driver) \ 49 static int name ## _modevent(module_t mod, int type, void *data) \ 50 { \ 51 switch (type) { \ 52 case MOD_LOAD: \ 53 periphdriver_register(data); \ 54 break; \ 55 case MOD_UNLOAD: \ 56 printf(#name " module unload - not possible for this module type\n"); \ 57 return EINVAL; \ 58 default: \ 59 return EOPNOTSUPP; \ 60 } \ 61 return 0; \ 62 } \ 63 static moduledata_t name ## _mod = { \ 64 #name, \ 65 name ## _modevent, \ 66 (void *)&driver \ 67 }; \ 68 DECLARE_MODULE(name, name ## _mod, SI_SUB_DRIVERS, SI_ORDER_ANY); \ 69 MODULE_DEPEND(name, cam, 1, 1, 1) 70 71typedef void (periph_init_t)(void); /* 72 * Callback informing the peripheral driver 73 * it can perform it's initialization since 74 * the XPT is now fully initialized. 75 */ 76typedef periph_init_t *periph_init_func_t; 77 78struct periph_driver { 79 periph_init_func_t init; 80 char *driver_name; 81 TAILQ_HEAD(,cam_periph) units; 82 u_int generation; 83 u_int flags; 84#define CAM_PERIPH_DRV_EARLY 0x01 85}; 86 87typedef enum { 88 CAM_PERIPH_BIO 89} cam_periph_type; 90 91/* Generically usefull offsets into the peripheral private area */ 92#define ppriv_ptr0 periph_priv.entries[0].ptr 93#define ppriv_ptr1 periph_priv.entries[1].ptr 94#define ppriv_field0 periph_priv.entries[0].field 95#define ppriv_field1 periph_priv.entries[1].field 96 97typedef void periph_start_t (struct cam_periph *periph, 98 union ccb *start_ccb); 99typedef cam_status periph_ctor_t (struct cam_periph *periph, 100 void *arg); 101typedef void periph_oninv_t (struct cam_periph *periph); 102typedef void periph_dtor_t (struct cam_periph *periph); 103struct cam_periph { 104 cam_pinfo pinfo; 105 periph_start_t *periph_start; 106 periph_oninv_t *periph_oninval; 107 periph_dtor_t *periph_dtor; 108 char *periph_name; 109 struct cam_path *path; /* Compiled path to device */ 110 void *softc; 111 struct cam_sim *sim; 112 u_int32_t unit_number; 113 cam_periph_type type; 114 u_int32_t flags; 115#define CAM_PERIPH_RUNNING 0x01 116#define CAM_PERIPH_LOCKED 0x02 117#define CAM_PERIPH_LOCK_WANTED 0x04 118#define CAM_PERIPH_INVALID 0x08 119#define CAM_PERIPH_NEW_DEV_FOUND 0x10 120#define CAM_PERIPH_RECOVERY_INPROG 0x20 121#define CAM_PERIPH_FREE 0x80 122 u_int32_t immediate_priority; 123 u_int32_t refcount; 124 SLIST_HEAD(, ccb_hdr) ccb_list; /* For "immediate" requests */ 125 SLIST_ENTRY(cam_periph) periph_links; 126 TAILQ_ENTRY(cam_periph) unit_links; 127 ac_callback_t *deferred_callback; 128 ac_code deferred_ac; 129}; 130 131#define CAM_PERIPH_MAXMAPS 2 132 133struct cam_periph_map_info { 134 int num_bufs_used; 135 struct buf *bp[CAM_PERIPH_MAXMAPS]; 136}; 137 138cam_status cam_periph_alloc(periph_ctor_t *periph_ctor, 139 periph_oninv_t *periph_oninvalidate, 140 periph_dtor_t *periph_dtor, 141 periph_start_t *periph_start, 142 char *name, cam_periph_type type, struct cam_path *, 143 ac_callback_t *, ac_code, void *arg); 144struct cam_periph *cam_periph_find(struct cam_path *path, char *name); 145int cam_periph_list(struct cam_path *, struct sbuf *); 146cam_status cam_periph_acquire(struct cam_periph *periph); 147void cam_periph_release(struct cam_periph *periph); 148void cam_periph_release_locked(struct cam_periph *periph); 149void cam_periph_release_locked_buses(struct cam_periph *periph); 150int cam_periph_hold(struct cam_periph *periph, int priority); 151void cam_periph_unhold(struct cam_periph *periph); 152void cam_periph_invalidate(struct cam_periph *periph); 153int cam_periph_mapmem(union ccb *ccb, 154 struct cam_periph_map_info *mapinfo); 155void cam_periph_unmapmem(union ccb *ccb, 156 struct cam_periph_map_info *mapinfo); 157union ccb *cam_periph_getccb(struct cam_periph *periph, 158 u_int32_t priority); 159void cam_periph_ccbwait(union ccb *ccb); 160int cam_periph_runccb(union ccb *ccb, 161 int (*error_routine)(union ccb *ccb, 162 cam_flags camflags, 163 u_int32_t sense_flags), 164 cam_flags camflags, u_int32_t sense_flags, 165 struct devstat *ds); 166int cam_periph_ioctl(struct cam_periph *periph, u_long cmd, 167 caddr_t addr, 168 int (*error_routine)(union ccb *ccb, 169 cam_flags camflags, 170 u_int32_t sense_flags)); 171void cam_freeze_devq(struct cam_path *path); 172void cam_freeze_devq_arg(struct cam_path *path, u_int32_t flags, 173 uint32_t arg); 174u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags, 175 u_int32_t opening_reduction, u_int32_t arg, 176 int getcount_only); 177void cam_periph_async(struct cam_periph *periph, u_int32_t code, 178 struct cam_path *path, void *arg); 179void cam_periph_bus_settle(struct cam_periph *periph, 180 u_int bus_settle_ms); 181void cam_periph_freeze_after_event(struct cam_periph *periph, 182 struct timeval* event_time, 183 u_int duration_ms); 184int cam_periph_error(union ccb *ccb, cam_flags camflags, 185 u_int32_t sense_flags, union ccb *save_ccb); 186void xpt_lock_buses(void); 187void xpt_unlock_buses(void); 188 189static __inline void 190cam_periph_lock(struct cam_periph *periph) 191{ 192 mtx_lock(periph->sim->mtx); 193} 194 195static __inline void 196cam_periph_unlock(struct cam_periph *periph) 197{ 198 mtx_unlock(periph->sim->mtx); 199} 200 201static __inline int 202cam_periph_owned(struct cam_periph *periph) 203{ 204 return (mtx_owned(periph->sim->mtx)); 205} 206 207static __inline int 208cam_periph_sleep(struct cam_periph *periph, void *chan, int priority, 209 const char *wmesg, int timo) 210{ 211 return (msleep(chan, periph->sim->mtx, priority, wmesg, timo)); 212} 213 214static inline struct cam_periph * 215cam_periph_acquire_first(struct periph_driver *driver) 216{ 217 struct cam_periph *periph; 218 219 xpt_lock_buses(); 220 periph = TAILQ_FIRST(&driver->units); 221 while (periph != NULL && (periph->flags & CAM_PERIPH_INVALID) != 0) 222 periph = TAILQ_NEXT(periph, unit_links); 223 if (periph != NULL) 224 periph->refcount++; 225 xpt_unlock_buses(); 226 return (periph); 227} 228 229static inline struct cam_periph * 230cam_periph_acquire_next(struct cam_periph *pperiph) 231{ 232 struct cam_periph *periph = pperiph; 233 234 mtx_assert(pperiph->sim->mtx, MA_NOTOWNED); 235 xpt_lock_buses(); 236 do { 237 periph = TAILQ_NEXT(periph, unit_links); 238 } while (periph != NULL && (periph->flags & CAM_PERIPH_INVALID) != 0); 239 if (periph != NULL) 240 periph->refcount++; 241 xpt_unlock_buses(); 242 cam_periph_release(pperiph); 243 return (periph); 244} 245 246#define CAM_PERIPH_FOREACH(periph, driver) \ 247 for ((periph) = cam_periph_acquire_first(driver); \ 248 (periph) != NULL; \ 249 (periph) = cam_periph_acquire_next(periph)) 250 251#endif /* _KERNEL */ 252#endif /* _CAM_CAM_PERIPH_H */ 253