xref: /freebsd/sys/cam/cam_periph.h (revision 1e637ba6770e6ae758073120d23b5fbf0f0ac2ef)
1898b0535SWarner Losh /*-
28b8a9b1dSJustin T. Gibbs  * Data structures and definitions for CAM peripheral ("type") drivers.
38b8a9b1dSJustin T. Gibbs  *
48b8a9b1dSJustin T. Gibbs  * Copyright (c) 1997, 1998 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  *
28c3aac50fSPeter Wemm  * $FreeBSD$
298b8a9b1dSJustin T. Gibbs  */
308b8a9b1dSJustin T. Gibbs 
318b8a9b1dSJustin T. Gibbs #ifndef _CAM_CAM_PERIPH_H
328b8a9b1dSJustin T. Gibbs #define _CAM_CAM_PERIPH_H 1
338b8a9b1dSJustin T. Gibbs 
348b8a9b1dSJustin T. Gibbs #include <sys/queue.h>
3511e4faceSScott Long #include <cam/cam_sim.h>
368b8a9b1dSJustin T. Gibbs 
37c4473420SPeter Wemm #ifdef _KERNEL
388b8a9b1dSJustin T. Gibbs 
3960794e04SPoul-Henning Kamp struct devstat;
4060794e04SPoul-Henning Kamp 
419a1c8571SNick Hibma extern struct cam_periph *xpt_periph;
42540d9130SNick Hibma 
430b7c27b9SPeter Wemm extern struct periph_driver **periph_drivers;
440b7c27b9SPeter Wemm void periphdriver_register(void *);
450b7c27b9SPeter Wemm 
460b7c27b9SPeter Wemm #include <sys/module.h>
470b7c27b9SPeter Wemm #define PERIPHDRIVER_DECLARE(name, driver) \
480b7c27b9SPeter Wemm 	static int name ## _modevent(module_t mod, int type, void *data) \
490b7c27b9SPeter Wemm 	{ \
500b7c27b9SPeter Wemm 		switch (type) { \
510b7c27b9SPeter Wemm 		case MOD_LOAD: \
520b7c27b9SPeter Wemm 			periphdriver_register(data); \
530b7c27b9SPeter Wemm 			break; \
540b7c27b9SPeter Wemm 		case MOD_UNLOAD: \
550b7c27b9SPeter Wemm 			printf(#name " module unload - not possible for this module type\n"); \
560b7c27b9SPeter Wemm 			return EINVAL; \
573e019deaSPoul-Henning Kamp 		default: \
583e019deaSPoul-Henning Kamp 			return EOPNOTSUPP; \
590b7c27b9SPeter Wemm 		} \
600b7c27b9SPeter Wemm 		return 0; \
610b7c27b9SPeter Wemm 	} \
620b7c27b9SPeter Wemm 	static moduledata_t name ## _mod = { \
630b7c27b9SPeter Wemm 		#name, \
640b7c27b9SPeter Wemm 		name ## _modevent, \
650b7c27b9SPeter Wemm 		(void *)&driver \
660b7c27b9SPeter Wemm 	}; \
670b7c27b9SPeter Wemm 	DECLARE_MODULE(name, name ## _mod, SI_SUB_DRIVERS, SI_ORDER_ANY); \
680b7c27b9SPeter Wemm 	MODULE_DEPEND(name, cam, 1, 1, 1)
698b8a9b1dSJustin T. Gibbs 
708b8a9b1dSJustin T. Gibbs typedef void (periph_init_t)(void); /*
718b8a9b1dSJustin T. Gibbs 				     * Callback informing the peripheral driver
728b8a9b1dSJustin T. Gibbs 				     * it can perform it's initialization since
738b8a9b1dSJustin T. Gibbs 				     * the XPT is now fully initialized.
748b8a9b1dSJustin T. Gibbs 				     */
758b8a9b1dSJustin T. Gibbs typedef periph_init_t *periph_init_func_t;
768b8a9b1dSJustin T. Gibbs 
778b8a9b1dSJustin T. Gibbs struct periph_driver {
788b8a9b1dSJustin T. Gibbs 	periph_init_func_t	 init;
798b8a9b1dSJustin T. Gibbs 	char			 *driver_name;
80e3975643SJake Burkholder 	TAILQ_HEAD(,cam_periph)	 units;
818b8a9b1dSJustin T. Gibbs 	u_int			 generation;
821e637ba6SAlexander Motin 	u_int			 flags;
831e637ba6SAlexander Motin #define CAM_PERIPH_DRV_EARLY		0x01
848b8a9b1dSJustin T. Gibbs };
858b8a9b1dSJustin T. Gibbs 
868b8a9b1dSJustin T. Gibbs typedef enum {
872e8f0ae6SScott Long 	CAM_PERIPH_BIO
888b8a9b1dSJustin T. Gibbs } cam_periph_type;
898b8a9b1dSJustin T. Gibbs 
908b8a9b1dSJustin T. Gibbs /* Generically usefull offsets into the peripheral private area */
918b8a9b1dSJustin T. Gibbs #define ppriv_ptr0 periph_priv.entries[0].ptr
928b8a9b1dSJustin T. Gibbs #define ppriv_ptr1 periph_priv.entries[1].ptr
938b8a9b1dSJustin T. Gibbs #define ppriv_field0 periph_priv.entries[0].field
948b8a9b1dSJustin T. Gibbs #define ppriv_field1 periph_priv.entries[1].field
958b8a9b1dSJustin T. Gibbs 
968b8a9b1dSJustin T. Gibbs typedef void		periph_start_t (struct cam_periph *periph,
978b8a9b1dSJustin T. Gibbs 					union ccb *start_ccb);
988b8a9b1dSJustin T. Gibbs typedef cam_status	periph_ctor_t (struct cam_periph *periph,
998b8a9b1dSJustin T. Gibbs 				       void *arg);
100ee9c90c7SKenneth D. Merry typedef void		periph_oninv_t (struct cam_periph *periph);
1018b8a9b1dSJustin T. Gibbs typedef void		periph_dtor_t (struct cam_periph *periph);
1028b8a9b1dSJustin T. Gibbs struct cam_periph {
1038b8a9b1dSJustin T. Gibbs 	cam_pinfo		 pinfo;
1048b8a9b1dSJustin T. Gibbs 	periph_start_t		*periph_start;
105ee9c90c7SKenneth D. Merry 	periph_oninv_t		*periph_oninval;
1068b8a9b1dSJustin T. Gibbs 	periph_dtor_t		*periph_dtor;
1078b8a9b1dSJustin T. Gibbs 	char			*periph_name;
1088b8a9b1dSJustin T. Gibbs 	struct cam_path		*path;	/* Compiled path to device */
1098b8a9b1dSJustin T. Gibbs 	void			*softc;
1102b83592fSScott Long 	struct cam_sim		*sim;
1118b8a9b1dSJustin T. Gibbs 	u_int32_t		 unit_number;
1128b8a9b1dSJustin T. Gibbs 	cam_periph_type		 type;
1138b8a9b1dSJustin T. Gibbs 	u_int32_t		 flags;
1148b8a9b1dSJustin T. Gibbs #define CAM_PERIPH_RUNNING		0x01
1158b8a9b1dSJustin T. Gibbs #define CAM_PERIPH_LOCKED		0x02
1168b8a9b1dSJustin T. Gibbs #define CAM_PERIPH_LOCK_WANTED		0x04
1178b8a9b1dSJustin T. Gibbs #define CAM_PERIPH_INVALID		0x08
1188b8a9b1dSJustin T. Gibbs #define CAM_PERIPH_NEW_DEV_FOUND	0x10
11960a899a0SKenneth D. Merry #define CAM_PERIPH_RECOVERY_INPROG	0x20
1202b83592fSScott Long #define CAM_PERIPH_POLLED		0x40
1218b8a9b1dSJustin T. Gibbs 	u_int32_t		 immediate_priority;
1228b8a9b1dSJustin T. Gibbs 	u_int32_t		 refcount;
123e3975643SJake Burkholder 	SLIST_HEAD(, ccb_hdr)	 ccb_list;	/* For "immediate" requests */
124e3975643SJake Burkholder 	SLIST_ENTRY(cam_periph)  periph_links;
125e3975643SJake Burkholder 	TAILQ_ENTRY(cam_periph)  unit_links;
1268b8a9b1dSJustin T. Gibbs 	ac_callback_t		*deferred_callback;
1278b8a9b1dSJustin T. Gibbs 	ac_code			 deferred_ac;
1288b8a9b1dSJustin T. Gibbs };
1298b8a9b1dSJustin T. Gibbs 
1308b8a9b1dSJustin T. Gibbs #define CAM_PERIPH_MAXMAPS	2
1318b8a9b1dSJustin T. Gibbs 
1328b8a9b1dSJustin T. Gibbs struct cam_periph_map_info {
1338b8a9b1dSJustin T. Gibbs 	int		num_bufs_used;
1348b8a9b1dSJustin T. Gibbs 	struct buf	*bp[CAM_PERIPH_MAXMAPS];
1358b8a9b1dSJustin T. Gibbs };
1368b8a9b1dSJustin T. Gibbs 
137ee9c90c7SKenneth D. Merry cam_status cam_periph_alloc(periph_ctor_t *periph_ctor,
138ee9c90c7SKenneth D. Merry 			    periph_oninv_t *periph_oninvalidate,
139ee9c90c7SKenneth D. Merry 			    periph_dtor_t *periph_dtor,
140ee9c90c7SKenneth D. Merry 			    periph_start_t *periph_start,
1410cdabce0SNick Hibma 			    char *name, cam_periph_type type, struct cam_path *,
1420cdabce0SNick Hibma 			    ac_callback_t *, ac_code, void *arg);
1438b8a9b1dSJustin T. Gibbs struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
1448b8a9b1dSJustin T. Gibbs cam_status	cam_periph_acquire(struct cam_periph *periph);
1458b8a9b1dSJustin T. Gibbs void		cam_periph_release(struct cam_periph *periph);
14624ebf566SEdward Tomasz Napierala void		cam_periph_release_locked(struct cam_periph *periph);
1472b83592fSScott Long int		cam_periph_hold(struct cam_periph *periph, int priority);
1482b83592fSScott Long void		cam_periph_unhold(struct cam_periph *periph);
1498b8a9b1dSJustin T. Gibbs void		cam_periph_invalidate(struct cam_periph *periph);
1508b8a9b1dSJustin T. Gibbs int		cam_periph_mapmem(union ccb *ccb,
1518b8a9b1dSJustin T. Gibbs 				  struct cam_periph_map_info *mapinfo);
1528b8a9b1dSJustin T. Gibbs void		cam_periph_unmapmem(union ccb *ccb,
1538b8a9b1dSJustin T. Gibbs 				    struct cam_periph_map_info *mapinfo);
1548b8a9b1dSJustin T. Gibbs union ccb	*cam_periph_getccb(struct cam_periph *periph,
1558b8a9b1dSJustin T. Gibbs 				   u_int32_t priority);
1568b8a9b1dSJustin T. Gibbs void		cam_periph_ccbwait(union ccb *ccb);
1578b8a9b1dSJustin T. Gibbs int		cam_periph_runccb(union ccb *ccb,
1588b8a9b1dSJustin T. Gibbs 				  int (*error_routine)(union ccb *ccb,
1598b8a9b1dSJustin T. Gibbs 						       cam_flags camflags,
1608b8a9b1dSJustin T. Gibbs 						       u_int32_t sense_flags),
1618b8a9b1dSJustin T. Gibbs 				  cam_flags camflags, u_int32_t sense_flags,
1628b8a9b1dSJustin T. Gibbs 				  struct devstat *ds);
163571e8e20SScott Long int		cam_periph_ioctl(struct cam_periph *periph, u_long cmd,
1648b8a9b1dSJustin T. Gibbs 				 caddr_t addr,
1658b8a9b1dSJustin T. Gibbs 				 int (*error_routine)(union ccb *ccb,
1668b8a9b1dSJustin T. Gibbs 						      cam_flags camflags,
1678b8a9b1dSJustin T. Gibbs 						      u_int32_t sense_flags));
16887cfaf0eSJustin T. Gibbs void		cam_freeze_devq(struct cam_path *path);
1698b8a9b1dSJustin T. Gibbs u_int32_t	cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
1708b8a9b1dSJustin T. Gibbs 				 u_int32_t opening_reduction, u_int32_t timeout,
1718b8a9b1dSJustin T. Gibbs 				 int getcount_only);
17287cfaf0eSJustin T. Gibbs void		cam_periph_async(struct cam_periph *periph, u_int32_t code,
17387cfaf0eSJustin T. Gibbs 		 		 struct cam_path *path, void *arg);
17487cfaf0eSJustin T. Gibbs void		cam_periph_bus_settle(struct cam_periph *periph,
17587cfaf0eSJustin T. Gibbs 				      u_int bus_settle_ms);
17687cfaf0eSJustin T. Gibbs void		cam_periph_freeze_after_event(struct cam_periph *periph,
17787cfaf0eSJustin T. Gibbs 					      struct timeval* event_time,
17887cfaf0eSJustin T. Gibbs 					      u_int duration_ms);
1798b8a9b1dSJustin T. Gibbs int		cam_periph_error(union ccb *ccb, cam_flags camflags,
1808b8a9b1dSJustin T. Gibbs 				 u_int32_t sense_flags, union ccb *save_ccb);
1818b8a9b1dSJustin T. Gibbs 
18211e4faceSScott Long static __inline void
18311e4faceSScott Long cam_periph_lock(struct cam_periph *periph)
18411e4faceSScott Long {
18511e4faceSScott Long 	mtx_lock(periph->sim->mtx);
18611e4faceSScott Long }
18711e4faceSScott Long 
18811e4faceSScott Long static __inline void
18911e4faceSScott Long cam_periph_unlock(struct cam_periph *periph)
19011e4faceSScott Long {
19111e4faceSScott Long 	mtx_unlock(periph->sim->mtx);
19211e4faceSScott Long }
19311e4faceSScott Long 
194c4473420SPeter Wemm #endif /* _KERNEL */
1958b8a9b1dSJustin T. Gibbs #endif /* _CAM_CAM_PERIPH_H */
196