1 |
1275 |
phoenix |
/*
|
2 |
|
|
* File...........: linux/drivers/s390/block/dasd_int.h
|
3 |
|
|
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
|
4 |
|
|
* Horst Hummel <Horst.Hummel@de.ibm.com>
|
5 |
|
|
* Bugreports.to..: <Linux390@de.ibm.com>
|
6 |
|
|
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
|
7 |
|
|
*
|
8 |
|
|
* $Revision: 1.1.1.1 $
|
9 |
|
|
*
|
10 |
|
|
* History of changes (starts July 2000)
|
11 |
|
|
* 02/01/01 added dynamic registration of ioctls
|
12 |
|
|
*/
|
13 |
|
|
|
14 |
|
|
#ifndef DASD_INT_H
|
15 |
|
|
#define DASD_INT_H
|
16 |
|
|
|
17 |
|
|
#include <asm/dasd.h>
|
18 |
|
|
|
19 |
|
|
#define CONFIG_DASD_DYNAMIC
|
20 |
|
|
|
21 |
|
|
typedef int(*dasd_ioctl_fn_t) (void *inp, int no, long args);
|
22 |
|
|
int dasd_ioctl_no_register(struct module *, int no, dasd_ioctl_fn_t handler);
|
23 |
|
|
int dasd_ioctl_no_unregister(struct module *, int no, dasd_ioctl_fn_t handler);
|
24 |
|
|
|
25 |
|
|
#define DASD_NAME "dasd"
|
26 |
|
|
#define DASD_PER_MAJOR ( 1U<<(MINORBITS-DASD_PARTN_BITS))
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
#define DASD_FORMAT_INTENS_WRITE_RECZERO 0x01
|
30 |
|
|
#define DASD_FORMAT_INTENS_WRITE_HOMEADR 0x02
|
31 |
|
|
|
32 |
|
|
#define DASD_STATE_DEL -1 /* "unknown" */
|
33 |
|
|
#define DASD_STATE_NEW 0 /* memory for dasd_device_t and lowmem ccw/idals allocated */
|
34 |
|
|
#define DASD_STATE_BOXED 1 /* boxed dasd could not be analysed "plugged" */
|
35 |
|
|
#define DASD_STATE_KNOWN 2 /* major_info/devinfo/discipline/devfs-'device'/gendisk - "detected" */
|
36 |
|
|
#define DASD_STATE_ACCEPT 3 /* irq requested - "accepted" */
|
37 |
|
|
#define DASD_STATE_INIT 4 /* init_cqr started - "busy" */
|
38 |
|
|
#define DASD_STATE_READY 5 /* init finished - "fenced(plugged)" */
|
39 |
|
|
#define DASD_STATE_ONLINE 6 /* unplugged "active" */
|
40 |
|
|
|
41 |
|
|
#define DASD_HOTPLUG_EVENT_ADD 0
|
42 |
|
|
#define DASD_HOTPLUG_EVENT_REMOVE 1
|
43 |
|
|
#define DASD_HOTPLUG_EVENT_PARTCHK 2
|
44 |
|
|
#define DASD_HOTPLUG_EVENT_PARTREMOVE 3
|
45 |
|
|
|
46 |
|
|
#define DASD_FORMAT_INTENS_WRITE_RECZERO 0x01
|
47 |
|
|
#define DASD_FORMAT_INTENS_WRITE_HOMEADR 0x02
|
48 |
|
|
#define DASD_FORMAT_INTENS_INVALIDATE 0x04
|
49 |
|
|
#define DASD_FORMAT_INTENS_CDL 0x08
|
50 |
|
|
#ifdef __KERNEL__
|
51 |
|
|
#include <linux/module.h>
|
52 |
|
|
#include <linux/version.h>
|
53 |
|
|
#include <linux/major.h>
|
54 |
|
|
#include <linux/wait.h>
|
55 |
|
|
#include <linux/blk.h>
|
56 |
|
|
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
|
57 |
|
|
#include <linux/blkdev.h>
|
58 |
|
|
#include <linux/devfs_fs_kernel.h>
|
59 |
|
|
#endif
|
60 |
|
|
#include <linux/genhd.h>
|
61 |
|
|
#include <linux/hdreg.h>
|
62 |
|
|
#include <linux/compatmac.h>
|
63 |
|
|
|
64 |
|
|
#include <asm/ccwcache.h>
|
65 |
|
|
#include <asm/irq.h>
|
66 |
|
|
#include <asm/s390dyn.h>
|
67 |
|
|
#include <asm/todclk.h>
|
68 |
|
|
#include <asm/debug.h>
|
69 |
|
|
|
70 |
|
|
/********************************************************************************
|
71 |
|
|
* SECTION: Kernel Version Compatibility section
|
72 |
|
|
********************************************************************************/
|
73 |
|
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
|
74 |
|
|
typedef struct request *request_queue_t;
|
75 |
|
|
#define block_device_operations file_operations
|
76 |
|
|
#define __setup(x,y) struct dasd_device_t
|
77 |
|
|
#define devfs_register_blkdev(major,name,ops) register_blkdev(major,name,ops)
|
78 |
|
|
#define register_disk(dd,dev,partn,ops,size) \
|
79 |
|
|
do { \
|
80 |
|
|
dd->sizes[MINOR(dev)] = size >> 1; \
|
81 |
|
|
resetup_one_dev(dd,MINOR(dev)>>DASD_PARTN_BITS); \
|
82 |
|
|
} while(0)
|
83 |
|
|
#define init_waitqueue_head(x) do { *x = NULL; } while(0)
|
84 |
|
|
#define blk_cleanup_queue(x) do {} while(0)
|
85 |
|
|
#define blk_init_queue(x...) do {} while(0)
|
86 |
|
|
#define blk_queue_headactive(x...) do {} while(0)
|
87 |
|
|
#define blk_queue_make_request(x) do {} while(0)
|
88 |
|
|
#define list_empty(x) (0)
|
89 |
|
|
#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
|
90 |
|
|
do { \
|
91 |
|
|
blk_dev[d_major].request_fn = d_request_fn; \
|
92 |
|
|
blk_dev[d_major].queue = d_queue_fn; \
|
93 |
|
|
blk_dev[d_major].current_request = d_current; \
|
94 |
|
|
} while(0)
|
95 |
|
|
#define INIT_GENDISK(D_MAJOR,D_NAME,D_PARTN_BITS,D_PER_MAJOR) \
|
96 |
|
|
major:D_MAJOR, \
|
97 |
|
|
major_name:D_NAME, \
|
98 |
|
|
minor_shift:D_PARTN_BITS, \
|
99 |
|
|
max_p:1 << D_PARTN_BITS, \
|
100 |
|
|
max_nr:D_PER_MAJOR, \
|
101 |
|
|
nr_real:D_PER_MAJOR,
|
102 |
|
|
static inline struct request *
|
103 |
|
|
dasd_next_request( request_queue_t *queue )
|
104 |
|
|
{
|
105 |
|
|
return *queue;
|
106 |
|
|
}
|
107 |
|
|
static inline void
|
108 |
|
|
dasd_dequeue_request( request_queue_t * q, struct request *req )
|
109 |
|
|
{
|
110 |
|
|
*q = req->next;
|
111 |
|
|
req->next = NULL;
|
112 |
|
|
}
|
113 |
|
|
|
114 |
|
|
#else
|
115 |
|
|
#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
|
116 |
|
|
do { \
|
117 |
|
|
blk_dev[d_major].queue = d_queue_fn; \
|
118 |
|
|
} while(0)
|
119 |
|
|
#define INIT_GENDISK(D_MAJOR,D_NAME,D_PARTN_BITS,D_PER_MAJOR) \
|
120 |
|
|
major:D_MAJOR, \
|
121 |
|
|
major_name:D_NAME, \
|
122 |
|
|
minor_shift:D_PARTN_BITS, \
|
123 |
|
|
max_p:1 << D_PARTN_BITS, \
|
124 |
|
|
nr_real:D_PER_MAJOR, \
|
125 |
|
|
fops:&dasd_device_operations,
|
126 |
|
|
static inline struct request *
|
127 |
|
|
dasd_next_request( request_queue_t *queue )
|
128 |
|
|
{
|
129 |
|
|
return blkdev_entry_next_request(&queue->queue_head);
|
130 |
|
|
}
|
131 |
|
|
static inline void
|
132 |
|
|
dasd_dequeue_request( request_queue_t * q, struct request *req )
|
133 |
|
|
{
|
134 |
|
|
blkdev_dequeue_request (req);
|
135 |
|
|
}
|
136 |
|
|
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98)) */
|
137 |
|
|
|
138 |
|
|
/********************************************************************************
|
139 |
|
|
* SECTION: Type definitions
|
140 |
|
|
********************************************************************************/
|
141 |
|
|
|
142 |
|
|
typedef struct dasd_devreg_t {
|
143 |
|
|
devreg_t devreg; /* the devreg itself */
|
144 |
|
|
/* build a linked list of devregs, needed for cleanup */
|
145 |
|
|
struct list_head list;
|
146 |
|
|
} dasd_devreg_t;
|
147 |
|
|
|
148 |
|
|
typedef struct {
|
149 |
|
|
struct list_head list;
|
150 |
|
|
struct module *owner;
|
151 |
|
|
int no;
|
152 |
|
|
dasd_ioctl_fn_t handler;
|
153 |
|
|
} dasd_ioctl_list_t;
|
154 |
|
|
|
155 |
|
|
typedef enum {
|
156 |
|
|
dasd_era_fatal = -1, /* no chance to recover */
|
157 |
|
|
dasd_era_none = 0, /* don't recover, everything alright */
|
158 |
|
|
dasd_era_msg = 1, /* don't recover, just report... */
|
159 |
|
|
dasd_era_recover = 2 /* recovery action recommended */
|
160 |
|
|
} dasd_era_t;
|
161 |
|
|
|
162 |
|
|
/* BIT DEFINITIONS FOR SENSE DATA */
|
163 |
|
|
#define DASD_SENSE_BIT_0 0x80
|
164 |
|
|
#define DASD_SENSE_BIT_1 0x40
|
165 |
|
|
#define DASD_SENSE_BIT_2 0x20
|
166 |
|
|
#define DASD_SENSE_BIT_3 0x10
|
167 |
|
|
|
168 |
|
|
/*
|
169 |
|
|
* struct dasd_sizes_t
|
170 |
|
|
* represents all data needed to access dasd with properly set up sectors
|
171 |
|
|
*/
|
172 |
|
|
typedef
|
173 |
|
|
struct dasd_sizes_t {
|
174 |
|
|
unsigned long blocks; /* size of volume in blocks */
|
175 |
|
|
unsigned int bp_block; /* bytes per block */
|
176 |
|
|
unsigned int s2b_shift; /* log2 (bp_block/512) */
|
177 |
|
|
unsigned int pt_block; /* from which block to read the partn table */
|
178 |
|
|
} dasd_sizes_t;
|
179 |
|
|
|
180 |
|
|
/*
|
181 |
|
|
* struct dasd_chanq_t
|
182 |
|
|
* represents a queue of channel programs related to a single device
|
183 |
|
|
*/
|
184 |
|
|
typedef
|
185 |
|
|
struct dasd_chanq_t {
|
186 |
|
|
ccw_req_t *head;
|
187 |
|
|
ccw_req_t *tail;
|
188 |
|
|
} dasd_chanq_t;
|
189 |
|
|
|
190 |
|
|
/*
|
191 |
|
|
* struct dasd_lowmem_t
|
192 |
|
|
* represents a queue of pages for lowmem request
|
193 |
|
|
*/
|
194 |
|
|
typedef struct {
|
195 |
|
|
struct list_head list;
|
196 |
|
|
} dasd_lowmem_t;
|
197 |
|
|
|
198 |
|
|
#define DASD_LOWMEM_PAGES 2 /* # of lowmem pages per device (min 2) */
|
199 |
|
|
|
200 |
|
|
/********************************************************************************
|
201 |
|
|
* SECTION: MACROS
|
202 |
|
|
********************************************************************************/
|
203 |
|
|
|
204 |
|
|
/*
|
205 |
|
|
* CHECK_THEN_SET
|
206 |
|
|
*
|
207 |
|
|
* Change 'where' value from 'from' to 'to'.
|
208 |
|
|
' BUG if the 'from' value doesn't match.
|
209 |
|
|
*/
|
210 |
|
|
#define check_then_set(where,from,to) \
|
211 |
|
|
do { \
|
212 |
|
|
if ((*(where)) != (from) ) { \
|
213 |
|
|
printk (KERN_ERR PRINTK_HEADER "was %d\n", *(where)); \
|
214 |
|
|
BUG(); \
|
215 |
|
|
} \
|
216 |
|
|
(*(where)) = (to); \
|
217 |
|
|
} while(0)
|
218 |
|
|
|
219 |
|
|
|
220 |
|
|
/********************************************************************************
|
221 |
|
|
* SECION: MACROs for klogd and s390 debug feature (dbf)
|
222 |
|
|
********************************************************************************/
|
223 |
|
|
|
224 |
|
|
#define DBF_DEV_EVENT(d_level, d_device, d_str, d_data...) \
|
225 |
|
|
do { \
|
226 |
|
|
if (d_device->debug_area != NULL) \
|
227 |
|
|
debug_sprintf_event(d_device->debug_area, \
|
228 |
|
|
d_level, \
|
229 |
|
|
d_str "\n", \
|
230 |
|
|
d_data); \
|
231 |
|
|
} while(0)
|
232 |
|
|
|
233 |
|
|
#define DBF_DEV_EXC(d_level, d_device, d_str, d_data...) \
|
234 |
|
|
do { \
|
235 |
|
|
if (d_device->debug_area != NULL) \
|
236 |
|
|
debug_sprintf_exception(d_device->debug_area, \
|
237 |
|
|
d_level, \
|
238 |
|
|
d_str "\n", \
|
239 |
|
|
d_data); \
|
240 |
|
|
} while(0)
|
241 |
|
|
|
242 |
|
|
#define DBF_EVENT(d_level, d_str, d_data...)\
|
243 |
|
|
do { \
|
244 |
|
|
if (dasd_debug_area != NULL) \
|
245 |
|
|
debug_sprintf_event(dasd_debug_area, \
|
246 |
|
|
d_level,\
|
247 |
|
|
d_str "\n", \
|
248 |
|
|
d_data); \
|
249 |
|
|
} while(0)
|
250 |
|
|
|
251 |
|
|
#define DBF_EXC(d_level, d_str, d_data...)\
|
252 |
|
|
do { \
|
253 |
|
|
if (dasd_debug_area != NULL) \
|
254 |
|
|
debug_sprintf_exception(dasd_debug_area, \
|
255 |
|
|
d_level,\
|
256 |
|
|
d_str "\n", \
|
257 |
|
|
d_data); \
|
258 |
|
|
} while(0)
|
259 |
|
|
|
260 |
|
|
/* definition of dbf debug levels */
|
261 |
|
|
#define DBF_EMERG 0 /* system is unusable */
|
262 |
|
|
#define DBF_ALERT 1 /* action must be taken immediately */
|
263 |
|
|
#define DBF_CRIT 2 /* critical conditions */
|
264 |
|
|
#define DBF_ERR 3 /* error conditions */
|
265 |
|
|
#define DBF_WARNING 4 /* warning conditions */
|
266 |
|
|
#define DBF_NOTICE 5 /* normal but significant condition */
|
267 |
|
|
#define DBF_INFO 6 /* informational */
|
268 |
|
|
#define DBF_DEBUG 6 /* debug-level messages */
|
269 |
|
|
|
270 |
|
|
/* messages to be written via klogd and dbf */
|
271 |
|
|
#define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
|
272 |
|
|
do { \
|
273 |
|
|
int d_devno = d_device->devinfo.devno; \
|
274 |
|
|
int d_irq = d_device->devinfo.irq; \
|
275 |
|
|
char *d_name = d_device->name; \
|
276 |
|
|
int d_major = MAJOR(d_device->kdev); \
|
277 |
|
|
int d_minor = MINOR(d_device->kdev); \
|
278 |
|
|
\
|
279 |
|
|
printk(d_loglevel PRINTK_HEADER \
|
280 |
|
|
" /dev/%-7s(%3d:%3d),%04x@%02x: " \
|
281 |
|
|
d_string "\n", \
|
282 |
|
|
d_name, \
|
283 |
|
|
d_major, \
|
284 |
|
|
d_minor, \
|
285 |
|
|
d_devno, \
|
286 |
|
|
d_irq, \
|
287 |
|
|
d_args); \
|
288 |
|
|
\
|
289 |
|
|
DBF_DEV_EVENT(DBF_ALERT, \
|
290 |
|
|
d_device, \
|
291 |
|
|
d_string, \
|
292 |
|
|
d_args); \
|
293 |
|
|
} while(0)
|
294 |
|
|
|
295 |
|
|
/* general messages to be written via klogd and dbf */
|
296 |
|
|
#define MESSAGE(d_loglevel,d_string,d_args...)\
|
297 |
|
|
do { \
|
298 |
|
|
printk(d_loglevel PRINTK_HEADER \
|
299 |
|
|
" " d_string "\n", \
|
300 |
|
|
d_args); \
|
301 |
|
|
\
|
302 |
|
|
DBF_EVENT(DBF_ALERT, \
|
303 |
|
|
d_string, \
|
304 |
|
|
d_args); \
|
305 |
|
|
} while(0)
|
306 |
|
|
|
307 |
|
|
/* general messages to be written via klogd only */
|
308 |
|
|
#define MESSAGE_LOG(d_loglevel,d_string,d_args...)\
|
309 |
|
|
do { \
|
310 |
|
|
printk(d_loglevel PRINTK_HEADER \
|
311 |
|
|
" " d_string "\n", \
|
312 |
|
|
d_args); \
|
313 |
|
|
} while(0)
|
314 |
|
|
|
315 |
|
|
struct dasd_device_t;
|
316 |
|
|
struct request;
|
317 |
|
|
|
318 |
|
|
/********************************************************************************
|
319 |
|
|
* SECTION: signatures for the functions of dasd_discipline_t
|
320 |
|
|
* make typecasts much easier
|
321 |
|
|
********************************************************************************/
|
322 |
|
|
|
323 |
|
|
typedef int (*dasd_ck_id_fn_t) (s390_dev_info_t *);
|
324 |
|
|
typedef int (*dasd_ck_characteristics_fn_t) (struct dasd_device_t *);
|
325 |
|
|
typedef int (*dasd_fill_geometry_fn_t) (struct dasd_device_t *,
|
326 |
|
|
struct hd_geometry *);
|
327 |
|
|
typedef int (*dasd_do_analysis_fn_t) (struct dasd_device_t *);
|
328 |
|
|
typedef int (*dasd_io_starter_fn_t) (ccw_req_t *);
|
329 |
|
|
typedef int (*dasd_io_stopper_fn_t) (ccw_req_t *);
|
330 |
|
|
typedef int (*dasd_info_fn_t) (struct dasd_device_t *,
|
331 |
|
|
dasd_information2_t *);
|
332 |
|
|
typedef int (*dasd_use_count_fn_t) (int);
|
333 |
|
|
typedef int (*dasd_get_attrib_fn_t) (struct dasd_device_t *,
|
334 |
|
|
struct attrib_data_t *);
|
335 |
|
|
typedef int (*dasd_set_attrib_fn_t) (struct dasd_device_t *,
|
336 |
|
|
struct attrib_data_t *);
|
337 |
|
|
typedef void (*dasd_int_handler_fn_t) (int irq, void *,
|
338 |
|
|
struct pt_regs *);
|
339 |
|
|
typedef void (*dasd_dump_sense_fn_t) (struct dasd_device_t *,
|
340 |
|
|
ccw_req_t *);
|
341 |
|
|
typedef ccw_req_t *(*dasd_format_fn_t) (struct dasd_device_t *,
|
342 |
|
|
struct format_data_t *);
|
343 |
|
|
typedef ccw_req_t *(*dasd_init_analysis_fn_t ) (struct dasd_device_t *);
|
344 |
|
|
typedef ccw_req_t *(*dasd_cp_builder_fn_t) (struct dasd_device_t *,
|
345 |
|
|
struct request *);
|
346 |
|
|
typedef ccw_req_t *(*dasd_reserve_fn_t) (struct dasd_device_t *);
|
347 |
|
|
typedef ccw_req_t *(*dasd_release_fn_t) (struct dasd_device_t *);
|
348 |
|
|
typedef ccw_req_t *(*dasd_steal_lock_fn_t) (struct dasd_device_t *);
|
349 |
|
|
typedef ccw_req_t *(*dasd_merge_cp_fn_t) (struct dasd_device_t *);
|
350 |
|
|
typedef ccw_req_t *(*dasd_erp_action_fn_t) (ccw_req_t * cqr);
|
351 |
|
|
typedef ccw_req_t *(*dasd_erp_postaction_fn_t) (ccw_req_t * cqr);
|
352 |
|
|
typedef ccw_req_t *(*dasd_read_stats_fn_t) (struct dasd_device_t *);
|
353 |
|
|
|
354 |
|
|
typedef dasd_rssd_perf_stats_t * (*dasd_ret_stats_fn_t) (ccw_req_t *);
|
355 |
|
|
typedef dasd_era_t (*dasd_error_examine_fn_t) (ccw_req_t *,
|
356 |
|
|
devstat_t * stat);
|
357 |
|
|
typedef dasd_erp_action_fn_t (*dasd_error_analyse_fn_t) (ccw_req_t *);
|
358 |
|
|
typedef dasd_erp_postaction_fn_t (*dasd_erp_analyse_fn_t) (ccw_req_t *);
|
359 |
|
|
|
360 |
|
|
/*
|
361 |
|
|
* the dasd_discipline_t is
|
362 |
|
|
* sth like a table of virtual functions, if you think of dasd_eckd
|
363 |
|
|
* inheriting dasd...
|
364 |
|
|
* no, currently we are not planning to reimplement the driver in C++
|
365 |
|
|
*/
|
366 |
|
|
typedef struct dasd_discipline_t {
|
367 |
|
|
struct module *owner;
|
368 |
|
|
char ebcname[8]; /* a name used for tagging and printks */
|
369 |
|
|
char name[8]; /* a name used for tagging and printks */
|
370 |
|
|
int max_blocks; /* maximum number of blocks to be chained */
|
371 |
|
|
dasd_ck_id_fn_t id_check; /* check sense data */
|
372 |
|
|
dasd_ck_characteristics_fn_t check_characteristics; /* check the characteristics */
|
373 |
|
|
dasd_init_analysis_fn_t init_analysis; /* start the analysis of the volume */
|
374 |
|
|
dasd_do_analysis_fn_t do_analysis; /* complete the analysis of the volume */
|
375 |
|
|
dasd_fill_geometry_fn_t fill_geometry; /* set up hd_geometry */
|
376 |
|
|
dasd_io_starter_fn_t start_IO;
|
377 |
|
|
dasd_io_stopper_fn_t term_IO;
|
378 |
|
|
dasd_format_fn_t format_device; /* format the device */
|
379 |
|
|
dasd_error_examine_fn_t examine_error;
|
380 |
|
|
dasd_error_analyse_fn_t erp_action;
|
381 |
|
|
dasd_erp_analyse_fn_t erp_postaction;
|
382 |
|
|
dasd_cp_builder_fn_t build_cp_from_req;
|
383 |
|
|
dasd_dump_sense_fn_t dump_sense;
|
384 |
|
|
dasd_int_handler_fn_t int_handler;
|
385 |
|
|
dasd_reserve_fn_t reserve;
|
386 |
|
|
dasd_release_fn_t release;
|
387 |
|
|
dasd_steal_lock_fn_t steal_lock;
|
388 |
|
|
dasd_merge_cp_fn_t merge_cp;
|
389 |
|
|
dasd_info_fn_t fill_info;
|
390 |
|
|
dasd_read_stats_fn_t read_stats;
|
391 |
|
|
dasd_ret_stats_fn_t ret_stats; /* return performance statistics */
|
392 |
|
|
dasd_get_attrib_fn_t get_attrib; /* get attributes (cache operations */
|
393 |
|
|
dasd_set_attrib_fn_t set_attrib; /* set attributes (cache operations */
|
394 |
|
|
struct list_head list; /* used for list of disciplines */
|
395 |
|
|
} dasd_discipline_t;
|
396 |
|
|
|
397 |
|
|
/* dasd_range_t are used for ordering the DASD devices */
|
398 |
|
|
typedef struct dasd_range_t {
|
399 |
|
|
unsigned int from; /* first DASD in range */
|
400 |
|
|
unsigned int to; /* last DASD in range */
|
401 |
|
|
char discipline[4]; /* placeholder to force discipline */
|
402 |
|
|
int features;
|
403 |
|
|
struct list_head list; /* next one in linked list */
|
404 |
|
|
} dasd_range_t;
|
405 |
|
|
|
406 |
|
|
|
407 |
|
|
|
408 |
|
|
#define DASD_MAJOR_INFO_REGISTERED 1
|
409 |
|
|
#define DASD_MAJOR_INFO_IS_STATIC 2
|
410 |
|
|
|
411 |
|
|
typedef struct major_info_t {
|
412 |
|
|
struct list_head list;
|
413 |
|
|
struct dasd_device_t **dasd_device;
|
414 |
|
|
int flags;
|
415 |
|
|
struct gendisk gendisk; /* actually contains the major number */
|
416 |
|
|
} __attribute__ ((packed)) major_info_t;
|
417 |
|
|
|
418 |
|
|
typedef struct dasd_device_t {
|
419 |
|
|
s390_dev_info_t devinfo;
|
420 |
|
|
dasd_discipline_t *discipline;
|
421 |
|
|
int level;
|
422 |
|
|
atomic_t open_count;
|
423 |
|
|
kdev_t kdev;
|
424 |
|
|
major_info_t *major_info;
|
425 |
|
|
struct dasd_chanq_t queue;
|
426 |
|
|
wait_queue_head_t wait_q;
|
427 |
|
|
request_queue_t *request_queue;
|
428 |
|
|
struct timer_list timer; /* used for start_IO */
|
429 |
|
|
struct timer_list late_timer; /* to get late devices online */
|
430 |
|
|
struct timer_list blocking_timer; /* used for ERP */
|
431 |
|
|
devstat_t dev_status; /* needed ONLY!! for request_irq */
|
432 |
|
|
dasd_sizes_t sizes;
|
433 |
|
|
char name[16]; /* The name of the device in /dev */
|
434 |
|
|
char *private; /* to be used by the discipline internally */
|
435 |
|
|
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
|
436 |
|
|
devfs_handle_t devfs_entry;
|
437 |
|
|
#endif /* LINUX_IS_24 */
|
438 |
|
|
struct tq_struct bh_tq;
|
439 |
|
|
atomic_t bh_scheduled;
|
440 |
|
|
debug_info_t *debug_area;
|
441 |
|
|
dasd_profile_info_t profile;
|
442 |
|
|
ccw_req_t *init_cqr;
|
443 |
|
|
atomic_t plugged;
|
444 |
|
|
int stopped; /* device (do_IO) was stopped */
|
445 |
|
|
struct list_head lowmem_pool;
|
446 |
|
|
} dasd_device_t;
|
447 |
|
|
|
448 |
|
|
/* reasons why device (do_IO) was stopped */
|
449 |
|
|
#define DASD_STOPPED_NOT_ACC 1 /* not accessible */
|
450 |
|
|
#define DASD_STOPPED_PENDING 2 /* long busy */
|
451 |
|
|
|
452 |
|
|
|
453 |
|
|
int dasd_init (void);
|
454 |
|
|
void dasd_discipline_add (dasd_discipline_t *);
|
455 |
|
|
void dasd_discipline_del (dasd_discipline_t *);
|
456 |
|
|
int dasd_start_IO (ccw_req_t *);
|
457 |
|
|
int dasd_term_IO (ccw_req_t *);
|
458 |
|
|
void dasd_int_handler (int , void *, struct pt_regs *);
|
459 |
|
|
void dasd_free_request (ccw_req_t *, dasd_device_t *);
|
460 |
|
|
int dasd_oper_handler (int irq, devreg_t * devreg);
|
461 |
|
|
void dasd_schedule_bh (dasd_device_t *);
|
462 |
|
|
void dasd_schedule_bh_timed (unsigned long);
|
463 |
|
|
int dasd_sleep_on_req (ccw_req_t*);
|
464 |
|
|
int dasd_set_normalized_cda (ccw1_t * cp, unsigned long address,
|
465 |
|
|
ccw_req_t* request,
|
466 |
|
|
dasd_device_t* device );
|
467 |
|
|
ccw_req_t * dasd_default_erp_action (ccw_req_t *);
|
468 |
|
|
ccw_req_t * dasd_default_erp_postaction (ccw_req_t *);
|
469 |
|
|
inline void dasd_chanq_deq (dasd_chanq_t *, ccw_req_t *);
|
470 |
|
|
inline void dasd_chanq_enq (dasd_chanq_t *, ccw_req_t *);
|
471 |
|
|
inline void dasd_chanq_enq_head (dasd_chanq_t *, ccw_req_t *);
|
472 |
|
|
ccw_req_t * dasd_alloc_request (char *, int, int, dasd_device_t *);
|
473 |
|
|
dasd_device_t * dasd_device_from_kdev (kdev_t kdev);
|
474 |
|
|
|
475 |
|
|
extern debug_info_t *dasd_debug_area;
|
476 |
|
|
extern int (*genhd_dasd_name) (char *, int, int, struct gendisk *);
|
477 |
|
|
extern int (*genhd_dasd_ioctl) (struct inode *inp, struct file *filp,
|
478 |
|
|
unsigned int no, unsigned long data);
|
479 |
|
|
|
480 |
|
|
#endif /* __KERNEL__ */
|
481 |
|
|
|
482 |
|
|
#endif /* DASD_H */
|
483 |
|
|
|
484 |
|
|
/*
|
485 |
|
|
* Overrides for Emacs so that we follow Linus's tabbing style.
|
486 |
|
|
* Emacs will notice this stuff at the end of the file and automatically
|
487 |
|
|
* adjust the settings for this buffer only. This must remain at the end
|
488 |
|
|
* of the file.
|
489 |
|
|
* ---------------------------------------------------------------------------
|
490 |
|
|
* Local variables:
|
491 |
|
|
* c-indent-level: 4
|
492 |
|
|
* c-brace-imaginary-offset: 0
|
493 |
|
|
* c-brace-offset: -4
|
494 |
|
|
* c-argdecl-indent: 4
|
495 |
|
|
* c-label-offset: -4
|
496 |
|
|
* c-continued-statement-offset: 4
|
497 |
|
|
* c-continued-brace-offset: 0
|
498 |
|
|
* indent-tabs-mode: nil
|
499 |
|
|
* tab-width: 8
|
500 |
|
|
* End:
|
501 |
|
|
*/
|