xref: /NextBSD/sys/sys/mach/device/io_req.h (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
1 /*
2  * Copyright 1991-1998 by Open Software Foundation, Inc.
3  *              All Rights Reserved
4  *
5  * Permission to use, copy, modify, and distribute this software and
6  * its documentation for any purpose and without fee is hereby granted,
7  * provided that the above copyright notice appears in all copies and
8  * that both the copyright notice and this permission notice appear in
9  * supporting documentation.
10  *
11  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
12  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE.
14  *
15  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
16  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
18  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
19  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 /*
22  * MkLinux
23  */
24 /* CMU_HIST */
25 /*
26  * Revision 2.12.4.1  92/03/03  16:13:59  jeffreyh
27  * 	Pick up changes from TRUNK.
28  * 	[92/02/26  11:01:36  jeffreyh]
29  *
30  * Revision 2.13  92/01/03  20:03:43  dbg
31  * 	Rename io_lock to io_req_lock to avoid conflict with io_lock
32  * 	macro for ipc_objects.
33  * 	[91/10/21            dbg]
34  *
35  * Revision 2.12  91/08/28  11:11:24  jsb
36  * 	Removed semicolon after decl_simple_lock_data in io_req declaration.
37  * 	[91/08/16  15:31:22  jsb]
38  *
39  * 	Add lock and associated macros to io_req structure.
40  * 	[91/08/12  17:28:46  dlb]
41  *
42  * 	Add io_total for use by writes - io_count is for each driver
43  * 	operation, io_total is for the entire device_write.
44  * 	[91/08/05  17:34:49  dlb]
45  *
46  * 	Add io_copy field to remember vm_map_copy_t that must be discarded
47  * 	when a mapped (not inline) device_write completes.
48  * 	[91/07/31  14:43:07  dlb]
49  *
50  * Revision 2.11  91/08/03  18:17:39  jsb
51  * 	Added IO_LOANED flag, initially for norma_ipc support.
52  * 	Loaned ior's are returned directly at interrupt level;
53  * 	see iodone() for details.
54  * 	[91/07/27  22:28:29  jsb]
55  *
56  * Revision 2.10  91/05/14  15:58:41  mrt
57  * 	Correcting copyright
58  *
59  * Revision 2.9  91/05/13  06:02:25  af
60  * 	Added IO_INTERNAL, for use when an io_request packet is used
61  * 	just for synchronization purposes.
62  * 	[91/03/11            af]
63  *
64  * Revision 2.8  91/02/05  17:09:49  mrt
65  * 	Changed to new Mach copyright
66  * 	[91/01/31  17:29:53  mrt]
67  *
68  * Revision 2.7  90/06/02  14:48:08  rpd
69  * 	Converted to new IPC.  Removed io_dev_port.
70  * 	[90/03/26  21:56:39  rpd]
71  *
72  * Revision 2.6  90/05/03  15:19:09  dbg
73  * 	Add spare flags definition for device-dependent uses.
74  * 	[90/03/14            dbg]
75  *
76  * Revision 2.5  90/01/11  11:42:13  dbg
77  * 	De-lint.
78  * 	[89/12/06            dbg]
79  *
80  * Revision 2.4  89/09/08  11:24:30  dbg
81  * 	Allocate io_req elements from kalloc pool, to allow a
82  * 	variable-length vm_page_t array at the end of the io_req_t.
83  * 	[89/08/14            dbg]
84  *
85  * 	Changed 'dev_hdr_t' to 'device_t'.
86  * 	[89/08/01            dbg]
87  *
88  * Revision 2.3  89/08/31  16:18:51  rwd
89  * 	Added io_inband_zone
90  * 	[89/08/15            rwd]
91  *
92  * Revision 2.2  89/08/05  16:06:50  rwd
93  * 	Added IO_INBAND.
94  * 	[89/08/04            rwd]
95  *
96  * 10-Oct-88  David Golub (dbg) at Carnegie-Mellon University
97  *	Created.
98  *
99  */
100 /* CMU_ENDHIST */
101 /*
102  * Mach Operating System
103  * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
104  * All Rights Reserved.
105  *
106  * Permission to use, copy, modify and distribute this software and its
107  * documentation is hereby granted, provided that both the copyright
108  * notice and this permission notice appear in all copies of the
109  * software, derivative works or modified versions, and any portions
110  * thereof, and that both notices appear in supporting documentation.
111  *
112  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
113  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
114  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
115  *
116  * Carnegie Mellon requests users of this software to return to
117  *
118  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
119  *  School of Computer Science
120  *  Carnegie Mellon University
121  *  Pittsburgh PA 15213-3890
122  *
123  * any improvements or extensions that they make and grant Carnegie Mellon
124  * the rights to redistribute these changes.
125  */
126 /*
127  */
128 /*
129  *	Author: David B. Golub, Carnegie Mellon University
130  *	Date: 	10/88
131  */
132 
133 #ifndef	_IO_REQ_
134 #define	_IO_REQ_
135 
136 #include <mach_kdb.h>
137 #include <chained_ios.h>
138 
139 #include <mach/boolean.h>
140 #include <mach/port.h>
141 #include <mach/message.h>
142 #include <mach/vm_param.h>
143 #include <kern/kalloc.h>
144 #include <kern/lock.h>
145 #include <vm/vm_page.h>
146 #include <device/device_types.h>
147 #include <device/device_typedefs.h>
148 #include <device/io_scatter.h>
149 
150 #include <kern/macro_help.h>
151 
152 /*
153  * IO request scatter/gather list
154  */
155 struct io_sg_entry {            /* sg list entry */
156 	vm_offset_t     iosge_phys;     /* physical address */
157 	vm_size_t       iosge_length;   /* length in bytes */
158 };
159 
160 struct io_sglist_hdr {          /* sg list header */
161 	vm_size_t       length;         /* total bytes covered by list */
162 	int             nentries;       /* number of entries */
163 };
164 
165 typedef struct io_sglist {      /* sg list structure */
166 	struct io_sglist_hdr iosg_hdr;	/* list header */
167 	struct io_sg_entry   iosg_list[1];   /* variable sized list */
168 } *io_sglist_t;
169 
170 /*
171  * Size of an sglist with n entries
172  */
173 #define IO_SGLIST_SIZE(n) \
174   (sizeof(struct io_sglist_hdr) + (n)*sizeof(struct io_sg_entry))
175 
176 /*
177  * IO request element, queued on device for delayed replies.
178  */
179 struct io_req {
180 	struct io_req *	io_next;	/* next, ... */
181 	struct io_req *	io_prev;	/* prev pointers: link in done,
182 					   defered, or in-progress list */
183 	mach_device_t	io_device;	/* pointer to open-device structure */
184 	char *		io_dev_ptr;	/* pointer to driver structure -
185 					   filled in by driver if necessary */
186 	int		io_unit;	/* unit number ('minor') of device */
187 	int		io_op;		/* IO operation */
188 	dev_mode_t	io_mode;	/* operation mode (wait, truncate) */
189 	recnum_t	io_recnum;	/* starting record number for
190 					   random-access devices */
191 
192 	union io_un {
193 	    io_buf_ptr_t    data;	/* data, for IO requests */
194 	} io_un;
195 #define	io_data		io_un.data
196 
197 	union io_seg {
198 		io_sglist_t	sgp;	        /* sglist, for IO requests */
199 		unsigned	seg_count;	/* Chained IOs seg count */
200 	} io_seg;
201 #define	io_sgp		io_seg.sgp
202 #define	io_seg_count	io_seg.seg_count
203 
204 	vm_address_t    io_uaddr;	/* user buf for overwrite requests */
205 	vm_map_t	io_map;		/* target map for overwrite requests */
206 	io_buf_len_t	io_count;	/* amount requested */
207 	io_buf_len_t	io_alloc_size;	/* amount allocated */
208 	io_buf_len_t	io_residual;	/* amount NOT done */
209 	io_return_t	io_error;	/* error code */
210 	boolean_t	(*io_done)(	/* call when done - returns TRUE
211 					   if IO really finished */
212 					io_req_t	ior);
213 	struct ipc_port	*io_reply_port;	/* reply port/queue, for asynchronous
214 					   messages */
215 	mach_msg_type_name_t io_reply_port_type;
216 					/* send or send-once right? */
217 	struct io_req *	io_link;	/* forward link (for driver header) */
218 	struct io_req *	io_rlink;	/* reverse link (for driver header) */
219 	vm_map_copy_t	io_copy;	/* vm_map_copy obj. for this op. */
220 					/* Lock for this structure */
221 #if	MACH_KDB
222 	int		io_ioip;
223 #endif
224 	io_buf_len_t	io_total;	/* total op size, for write */
225 	int		io_save;	/* Saved IO operation */
226 	decl_simple_lock_data(,io_req_lock) /* Lock for this structure */
227 };
228 
229 
230 /*
231  * LOCKING NOTE: Operations on io_req's are in general single threaded by
232  * the invoking code, obviating the need for a lock.  The usual IO_CALL
233  * path through the code is: Initiating thread hands io_req to device driver,
234  * driver passes it to io_done thread, io_done thread sends reply message.  No
235  * locking is needed in this sequence.  Unfortunately, a synchronous wait
236  * for a buffer requires a lock to avoid problems if the wait and interrupt
237  * happen simultaneously on different processors.
238  */
239 
240 #define ior_lock(ior)	simple_lock(&(ior)->io_req_lock)
241 #define ior_unlock(ior)	simple_unlock(&(ior)->io_req_lock)
242 
243 /*
244  * Flags and operations
245  */
246 
247 #define	IO_WRITE	0x00000000	/* operation is write */
248 #define	IO_READ		0x00000001	/* operation is read */
249 #define	IO_OPEN		0x00000002	/* operation is open */
250 #define	IO_DONE		0x00000100	/* operation complete */
251 #define	IO_ERROR	0x00000200	/* error on operation */
252 #define	IO_BUSY		0x00000400	/* operation in progress */
253 #define	IO_WANTED	0x00000800	/* wakeup when no longer BUSY */
254 #define	IO_BAD		0x00001000	/* bad disk block */
255 #define	IO_CALL		0x00002000	/* call io_done_thread when done */
256 #define IO_INBAND	0x00004000	/* mig call was inband */
257 #define IO_INTERNAL	0x00008000	/* internal, device-driver specific */
258 #define	IO_LOANED	0x00010000	/* ior loaned by another module */
259 #define IO_SYNC		0x00020000	/* caller is synchronous */
260 #define IO_OVERWRITE	0x00040000	/* overwrite request */
261 #define IO_KERNEL_BUF	0x00080000	/* buffer address is in kernel */
262 #define	IO_QUEUE	0x00100000	/* use completion queue when done */
263 #define IO_SGLIST	0x00200000	/* data points to scatter/gather list*/
264 #define	IO_TRANSPORT	0x00400000	/* Special IOR from transport */
265 #define	IO_PASSIVE	0x00800000	/* Post target mode request */
266 #define	IO_SCATTER	0x01000000	/* io_data points to io_scatter */
267 #define	IO_PAD		0x02000000	/* This is a padded IO and we
268 					   don't care as much about residual */
269 #define IO_HANDOFF	0x04000000	/* ior moved from user io_done_queue to
270 					   io_done_thread_queue */
271 #define IO_FREE		0x08000000	/* ior can be freed now */
272 #define IO_WCLONED	0x10000000	/* caller recycled written data */
273 #define	IO_SPARE_START	0x20000000	/* start of spare flags */
274 #define IO_CHAINED	0x40000000	/* Chained io. This means that several
275 					   IO requests are chained with this
276 					   one. A single I/O operation will
277 					   performed for the complete chain.
278 					   It is mostly used to gather disk
279 					   IOs on contiguous disk blocks.
280 					   Not te be mixed up with IO_SGLIST */
281 
282 extern io_return_t	block_io(
283 				void		(*strat)(io_req_t ior),
284 				void		(*max_count)(io_req_t ior),
285 				io_req_t	ior);
286 extern void		disksort(
287 				io_req_t	head,
288 				io_req_t	ior);
289 extern vm_offset_t	block_io_mmap(dev_t, vm_offset_t, vm_prot_t);
290 
291 zone_t	io_req_zone;
292 
293 /*
294  * Macros to allocate and free IORs
295  */
296 #if	MACH_KDB
297 #define	io_req_alloc(ior)					\
298 	MACRO_BEGIN						\
299 	(ior) = (io_req_t)zalloc(io_req_zone);			\
300 	simple_lock_init(&(ior)->io_req_lock, ETAP_IO_REQ);	\
301 	ior->io_ioip = 0;\
302 	MACRO_END
303 
304 #define	io_req_free(ior)					\
305 	MACRO_BEGIN						\
306 	assert(!ior->io_ioip);					\
307 	zfree(io_req_zone, (vm_offset_t)(ior));			\
308 	MACRO_END
309 
310 #else
311 #define	io_req_alloc(ior)					\
312 	MACRO_BEGIN						\
313 	(ior) = (io_req_t)zalloc(io_req_zone);			\
314 	simple_lock_init(&(ior)->io_req_lock, ETAP_IO_REQ);	\
315 	MACRO_END
316 
317 #define	io_req_free(ior)					\
318 	MACRO_BEGIN						\
319 	zfree(io_req_zone, (vm_offset_t)(ior));			\
320 	MACRO_END
321 #endif
322 
323 #define	io_sglist_alloc(sglist, nentries)			\
324 	MACRO_BEGIN						\
325 	(sglist) = (io_sglist_t)kalloc(IO_SGLIST_SIZE(nentries));\
326 	(sglist)->iosg_hdr.nentries = (nentries);		\
327 	MACRO_END
328 
329 #define	io_sglist_free(sglist)					\
330 	(kfree((vm_offset_t)(sglist),				\
331 	       IO_SGLIST_SIZE((sglist)->iosg_hdr.nentries)))
332 
333 zone_t	io_inband_zone; /* for inband reads */
334 
335 #if CHAINED_IOS
336 
337 extern void 	chain_io_reqs(io_req_t		ior1,
338 			      io_req_t		ior2,
339 			      io_req_t	 	head);
340 
341 extern	void	chained_iodone(io_req_t         ior);
342 
343 extern	void	split_io_reqs(io_req_t		ior);
344 
345 #endif	/* CHAINED_IOS */
346 
347 #endif	/* _IO_REQ_ */
348