summaryrefslogtreecommitdiff
path: root/device/io_req.h
blob: 1ad46801fdc40d8df085ce408031d144f4a7bca7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 * Mach Operating System
 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
/*
 *	Author: David B. Golub, Carnegie Mellon University
 *	Date: 	10/88
 */

#ifndef	_IO_REQ_
#define	_IO_REQ_

#include <mach/boolean.h>
#include <mach/port.h>
#include <mach/message.h>
#include <mach/vm_param.h>
#include <kern/slab.h>
#include <kern/kalloc.h>
#include <kern/lock.h>
#include <vm/vm_page.h>
#include <device/device_types.h>
#include <device/dev_hdr.h>

#include <kern/macros.h>

/*
 * IO request element, queued on device for delayed replies.
 */
typedef struct io_req *io_req_t;
struct io_req {
	struct io_req *	io_next;	/* next, ... */
	struct io_req *	io_prev;	/* prev pointers: link in done,
					   defered, or in-progress list */
	mach_device_t	io_device;	/* pointer to open-device structure */
	char *		io_dev_ptr;	/* pointer to driver structure -
					   filled in by driver if necessary */
	int		io_unit;	/* unit number ('minor') of device */
	int		io_op;		/* IO operation */
	dev_mode_t	io_mode;	/* operation mode (wait, truncate) */
	recnum_t	io_recnum;	/* starting record number for
					   random-access devices */

	union io_un {
	    io_buf_ptr_t    data;	/* data, for IO requests */
	} io_un;
#define	io_data		io_un.data

	long		io_count;	/* amount requested */
	vm_size_t	io_alloc_size;	/* amount allocated */
	long		io_residual;	/* amount NOT done */
	io_return_t	io_error;	/* error code */
	/* call when done - returns TRUE if IO really finished */
	boolean_t	(*io_done)(io_req_t);
	struct ipc_port	*io_reply_port;	/* reply port, for asynchronous
					   messages */
	mach_msg_type_name_t io_reply_port_type;
					/* send or send-once right? */
	struct io_req *	io_link;	/* forward link (for driver header) */
	struct io_req *	io_rlink;	/* reverse link (for driver header) */
	vm_map_copy_t	io_copy;	/* vm_map_copy obj. for this op. */
	long		io_total;	/* total op size, for write */
	decl_simple_lock_data(,io_req_lock)
					/* Lock for this structure */
	long            io_physrec;    /* mapping to the physical block
					   number */
	long            io_rectotal;   /* total number of blocks to move */
};

/*
 * LOCKING NOTE: Operations on io_req's are in general single threaded by
 * the invoking code, obviating the need for a lock.  The usual IO_CALL
 * path through the code is: Initiating thread hands io_req to device driver,
 * driver passes it to io_done thread, io_done thread sends reply message.  No
 * locking is needed in this sequence.  Unfortunately, a synchronous wait
 * for a buffer requires a lock to avoid problems if the wait and interrupt
 * happen simultaneously on different processors.
 */

#define ior_lock(ior)	simple_lock(&(ior)->io_req_lock)
#define ior_unlock(ior)	simple_unlock(&(ior)->io_req_lock)

/*
 * Flags and operations
 */

#define	IO_WRITE	0x00000000	/* operation is write */
#define	IO_READ		0x00000001	/* operation is read */
#define	IO_OPEN		0x00000002	/* operation is open */
#define	IO_DONE		0x00000100	/* operation complete */
#define	IO_ERROR	0x00000200	/* error on operation */
#define	IO_BUSY		0x00000400	/* operation in progress */
#define	IO_WANTED	0x00000800	/* wakeup when no longer BUSY */
#define	IO_BAD		0x00001000	/* bad disk block */
#define	IO_CALL		0x00002000	/* call io_done_thread when done */
#define IO_INBAND	0x00004000	/* mig call was inband */
#define IO_INTERNAL	0x00008000	/* internal, device-driver specific */
#define	IO_LOANED	0x00010000	/* ior loaned by another module */

#define	IO_SPARE_START	0x00020000	/* start of spare flags */

/*
 * Standard completion routine for io_requests.
 */
void	iodone(io_req_t);

/*
 * Macros to allocate and free IORs - will convert to caches later.
 */
#define	io_req_alloc(ior,size)					\
	MACRO_BEGIN						\
	(ior) = (io_req_t)kalloc(sizeof(struct io_req));	\
	simple_lock_init(&(ior)->io_req_lock);			\
	MACRO_END

#define	io_req_free(ior)					\
	(kfree((vm_offset_t)(ior), sizeof(struct io_req)))


struct kmem_cache io_inband_cache; /* for inband reads */

#endif	/* _IO_REQ_ */