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