1/* $NetBSD: disk.h,v 1.74 2019/05/22 08:47:02 hannken Exp $ */
2
3/*-
4 * Copyright (c) 1996, 1997, 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1992, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * This software was developed by the Computer Systems Engineering group
38 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
39 * contributed to Berkeley.
40 *
41 * All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Lawrence Berkeley Laboratories.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE.
69 *
70 * from: Header: disk.h,v 1.5 92/11/19 04:33:03 torek Exp (LBL)
71 *
72 * @(#)disk.h 8.2 (Berkeley) 1/9/95
73 */
74
75#ifndef _SYS_DISK_H_
76#define _SYS_DISK_H_
77
78/*
79 * Disk device structures.
80 */
81
82#include <sys/dkio.h>
83#include <sys/time.h>
84#include <sys/queue.h>
85#include <sys/iostat.h>
86
87/*
88 * Disk information dictionary.
89 *
90 * This contains general infomation for disk devices.
91 *
92 * <dict>
93 * <key>type</key>
94 * <string>...</string>
95 * <key>geometry</key>
96 * <dict>
97 * <!-- See below for disk geometry dictionary
98 * contents. -->
99 * </dict>
100 *
101 * <!-- optional information -->
102 * <key>rpm</key>
103 * <integer>...</integer>
104 * <key>sector-interleave</key>
105 * <integer>...</integer>
106 * <key>track-skew</key>
107 * <integer>...</integer>
108 * <key>cylinder-skew</key>
109 * <integer>...</integer>
110 * <key>head-switch-usecs</key>
111 * <integer>...</integer>
112 * <key>track-seek-usecs</key>
113 * <integer>...</integer>
114 * <key>removable</key>
115 * <false/>
116 * <key>ecc</key>
117 * <false/>
118 * <key>bad-sector-forwarding</key>
119 * <true/>
120 * <key>ramdisk</key>
121 * <false/>
122 * <key>back-to-back-transfers</key>
123 * <true/>
124 *
125 * <!-- additional information for SMD drives -->
126 * <key>smd-skip-sectoring</key>
127 * <false/>
128 * <!-- XXX better names for these properties -->
129 * <key>smd-mindist</key>
130 * <integer>...</integer>
131 * <key>smd-maxdist</key>
132 * <integer>...</integer>
133 * <key>smd-sdist</key>
134 * <integer>...</integer>
135 *
136 * <!-- additional information for ST506 drives -->
137 * <!-- XXX better names for these properties -->
138 * <key>st506-precompcyl</key>
139 * <integer>...</integer>
140 * <key>st506-gap3</key>
141 * <integer>...</integer>
142 *
143 * <!-- additional information for ATA drives -->
144 * <!-- XXX -->
145 *
146 * <!-- additional information for SCSI drives -->
147 * <!-- XXX -->
148 * </dict>
149 */
150
151/*
152 * dkwedge_info:
153 *
154 * Information needed to configure (or query configuration of) a
155 * disk wedge.
156 */
157struct dkwedge_info {
158 char dkw_devname[16];/* device-style name (e.g. "dk0") */
159 uint8_t dkw_wname[128]; /* wedge name (Unicode, UTF-8) */
160 char dkw_parent[16]; /* parent disk device name */
161 daddr_t dkw_offset; /* LBA offset of wedge in parent */
162 uint64_t dkw_size; /* size of wedge in blocks */
163 char dkw_ptype[32]; /* partition type string */
164};
165
166/*
167 * dkwedge_list:
168 *
169 * Structure used to query a list of wedges.
170 */
171struct dkwedge_list {
172 void *dkwl_buf; /* storage for dkwedge_info array */
173 size_t dkwl_bufsize; /* size of that buffer */
174 u_int dkwl_nwedges; /* total number of wedges */
175 u_int dkwl_ncopied; /* number actually copied */
176};
177
178/* Some common partition types */
179#define DKW_PTYPE_UNKNOWN ""
180#define DKW_PTYPE_UNUSED "unused"
181#define DKW_PTYPE_SWAP "swap"
182#define DKW_PTYPE_V6 "v6"
183#define DKW_PTYPE_V7 "v7"
184#define DKW_PTYPE_SYSV "sysv"
185#define DKW_PTYPE_V71K "v71k"
186#define DKW_PTYPE_V8 "v8"
187#define DKW_PTYPE_FFS "ffs"
188#define DKW_PTYPE_FAT "msdos"
189#define DKW_PTYPE_LFS "lfs"
190#define DKW_PTYPE_OTHER "other"
191#define DKW_PTYPE_HPFS "hpfs"
192#define DKW_PTYPE_ISO9660 "cd9660"
193#define DKW_PTYPE_BOOT "boot"
194#define DKW_PTYPE_AMIGADOS "ados"
195#define DKW_PTYPE_HFS "hfs"
196#define DKW_PTYPE_FILECORE "filecore"
197#define DKW_PTYPE_EXT2FS "ext2fs"
198#define DKW_PTYPE_NTFS "ntfs"
199#define DKW_PTYPE_RAIDFRAME "raidframe"
200#define DKW_PTYPE_CCD "ccd"
201#define DKW_PTYPE_JFS2 "jfs2"
202#define DKW_PTYPE_APPLEUFS "appleufs"
203#define DKW_PTYPE_VINUM "vinum"
204#define DKW_PTYPE_UDF "udf"
205#define DKW_PTYPE_APPLEHFS "hfs"
206#define DKW_PTYPE_SYSVBFS "sysvbfs"
207#define DKW_PTYPE_EFS "efs"
208#define DKW_PTYPE_NILFS "nilfs"
209#define DKW_PTYPE_CGD "cgd"
210#define DKW_PTYPE_MINIXFS3 "minixfs3"
211#define DKW_PTYPE_VMKCORE "vmkcore"
212#define DKW_PTYPE_VMFS "vmfs"
213#define DKW_PTYPE_VMWRESV "vmwresv"
214
215/*
216 * Ensure each symbol used in FSTYPE_DEFN in <sys/disklabel.h>
217 * has a corresponding DKW_PTYPE_* definition.
218 */
219#define DKW_PTYPE_MSDOS DKW_PTYPE_FAT
220#define DKW_PTYPE_BSDFFS DKW_PTYPE_FFS
221#define DKW_PTYPE_BSDLFS DKW_PTYPE_LFS
222#define DKW_PTYPE_ADOS DKW_PTYPE_AMIGADOS
223#define DKW_PTYPE_EX2FS DKW_PTYPE_EXT2FS
224#define DKW_PTYPE_RAID DKW_PTYPE_RAIDFRAME
225
226/*
227 * Disk geometry dictionary.
228 *
229 * NOTE: Not all geometry information is relevant for every kind of disk.
230 *
231 * <dict>
232 * <key>sectors-per-unit</key>
233 * <integer>...</integer>
234 * <key>sector-size</key>
235 * <integer>...</integer>
236 * <key>sectors-per-track</key>
237 * <integer>...</integer>
238 * <key>tracks-per-cylinder</key>
239 * <integer>...</integer>
240 * <key>cylinders-per-unit</key>
241 * <integer>...</integer>
242 * <key>physical-cylinders-per-unit</key>
243 * <integer>...</integer>
244 * <key>spare-sectors-per-track</key>
245 * <integer>...</integer>
246 * <key>spare-sectors-per-cylinder</key>
247 * <integer>...</integer>
248 * <key>alternative-cylinders</key>
249 * <integer>...</integer>
250 * </dict>
251 * NOTE: Not all geometry information is relevant for every kind of disk.
252 */
253
254struct disk_geom {
255 int64_t dg_secperunit; /* # of data sectors per unit */
256 uint32_t dg_secsize; /* # of bytes per sector */
257 uint32_t dg_nsectors; /* # of data sectors per track */
258 uint32_t dg_ntracks; /* # of tracks per cylinder */
259 uint32_t dg_ncylinders; /* # of data cylinders per unit */
260 uint32_t dg_secpercyl; /* # of data sectors per cylinder */
261 uint32_t dg_pcylinders; /* # of physical cylinders per unit */
262
263 /*
264 * Spares (bad sector replacements) below are not counted in
265 * dg_nsectors or dg_secpercyl. Spare sectors are assumed to
266 * be physical sectors which occupy space at the end of each
267 * track and/or cylinder.
268 */
269 uint32_t dg_sparespertrack;
270 uint32_t dg_sparespercyl;
271 /*
272 * Alternative cylinders include maintenance, replacement,
273 * configuration description areas, etc.
274 */
275 uint32_t dg_acylinders;
276};
277
278/*
279 * Bad sector lists per fixed disk
280 */
281struct disk_badsectors {
282 SLIST_ENTRY(disk_badsectors) dbs_next;
283 daddr_t dbs_min; /* min. sector number */
284 daddr_t dbs_max; /* max. sector number */
285 struct timeval dbs_failedat; /* first failure at */
286};
287
288struct disk_badsecinfo {
289 uint32_t dbsi_bufsize; /* size of region pointed to */
290 uint32_t dbsi_skip; /* how many to skip past */
291 uint32_t dbsi_copied; /* how many got copied back */
292 uint32_t dbsi_left; /* remaining to copy */
293 void * dbsi_buffer; /* region to copy disk_badsectors to */
294};
295
296#define DK_STRATEGYNAMELEN 32
297struct disk_strategy {
298 char dks_name[DK_STRATEGYNAMELEN]; /* name of strategy */
299 char *dks_param; /* notyet; should be NULL */
300 size_t dks_paramlen; /* notyet; should be 0 */
301};
302
303#ifdef _KERNEL
304#include <sys/device.h>
305#include <sys/mutex.h>
306
307#include <prop/proplib.h>
308
309struct buf;
310struct disk;
311struct disklabel;
312struct cpu_disklabel;
313struct lwp;
314struct vnode;
315
316/*
317 * dkwedge_discovery_method:
318 *
319 * Structure used to describe partition map parsing schemes
320 * used for wedge autodiscovery.
321 */
322struct dkwedge_discovery_method {
323 /* link in wedge driver's list */
324 LIST_ENTRY(dkwedge_discovery_method) ddm_list;
325 const char *ddm_name; /* name of this method */
326 int ddm_priority; /* search priority */
327 int (*ddm_discover)(struct disk *, struct vnode *);
328};
329
330#define DKWEDGE_DISCOVERY_METHOD_DECL(name, prio, discover) \
331static struct dkwedge_discovery_method name ## _ddm = { \
332 { NULL, NULL }, \
333 #name, \
334 prio, \
335 discover \
336}; \
337__link_set_add_data(dkwedge_methods, name ## _ddm)
338
339/*
340 * Disk partition dictionary.
341 *
342 * A partition is represented as a dictionary containing generic partition
343 * properties (such as starting block and block count), as well as information
344 * that is specific to individual partition map formats.
345 *
346 * <dict>
347 * <key>start-block</key>
348 * <integer>...</integer>
349 * <key>block-count</key>
350 * <integer>...</integer>
351 * <!-- DKW_PTYPE strings ("" or missing if unknown) -->
352 * <key>type</type>
353 * <string>...</string>
354 * <!-- optional -->
355 * <key>name</key>
356 * <string>...</string>
357 *
358 * <!-- these are valid for GPT partition maps -->
359 * <key>gpt-type-guid</key>
360 * <string>...</string>
361 * <key>gpt-partition-guid</key>
362 * <string>...</string>
363 * <key>gpt-platform-required</key>
364 * <false/>
365 *
366 * <!-- these are valid for 4.4BSD partition maps -->
367 * <key>bsd44-partition-type</key>
368 * <integer>...</integer>
369 * <key>bsd44-fs-fragment-size</key>
370 * <integer>...</integer>
371 * <key>bsd44-iso9660-session-offset</key>
372 * <integer>...</integer>
373 * <key>bsd44-ffs-cylinders-per-group</key>
374 * <integer>...</integer>
375 * <key>bsd44-lfs-segment-shift</key>
376 * <integer>...</integer>
377 *
378 * <!-- these are valid for NeXT partition maps -->
379 * <key>next-block-size</key>
380 * <integer>...</integer>
381 * <key>next-fs-fragment-size</key>
382 * <integer>...</integer>
383 * <key>next-fs-optimization</key>
384 * <string>...</string> <!-- "space" or "time" -->
385 * <key>next-fs-cylinders-per-group</key>
386 * <integer>...</integer>
387 * <key>next-bytes-per-inode-density</key>
388 * <integer>...</integer>
389 * <key>next-minfree-percentage</key>
390 * <integer>...</integer>
391 * <key>next-run-newfs-during-init</key>
392 * <false/>
393 * <key>next-mount-point</key>
394 * <string>...</string>
395 * <key>next-automount</key>
396 * <true/>
397 * <key>next-partition-type</key>
398 * <string>...</string>
399 *
400 * <!-- these are valid for MBR partition maps -->
401 * <key>mbr-start-head</key>
402 * <integer>...</integer>
403 * <key>mbr-start-sector</key>
404 * <integer>...</integer>
405 * <key>mbr-start-cylinder</key>
406 * <integer>...</integer>
407 * <key>mbr-partition-type</key>
408 * <integer>...</integer>
409 * <key>mbr-end-head</key>
410 * <integer>...</integer>
411 * <key>mbr-end-sector</key>
412 * <integer>...</integer>
413 * <key>mbr-end-cylinder</key>
414 * <integer>...</integer>
415 * <key>mbr-active-partition</key>
416 * <false/>
417 *
418 * <!-- these are valid for Apple partition maps -->
419 * <key>apple-partition-type</key>
420 * <string>...</string>
421 * <!-- XXX What else do we need? wrstuden? -->
422 *
423 * <!-- these are valid for RISCiX partition maps -->
424 * <key>riscix-partition-type</key>
425 * <integer>...</integer>
426 *
427 * <!-- these are valid for MIPS/SGI partition maps -->
428 * <key>mips-partition-type</key>
429 * <integer>...</integer>
430 *
431 * <!-- SunOS 4 partition maps have no specific
432 * additional information. Note, however,
433 * that SunOS 4 partitions must begin on
434 * cylinder boundaries. -->
435 *
436 * <!-- XXX Need Amiga partition map info -->
437 *
438 * <!-- these are valid for VTOC partition maps -->
439 * <key>vtoc-tag</key>
440 * <integer>...</integer>
441 * <key>vtoc-unmount</key>
442 * <false/>
443 * <key>vtoc-read-only</key>
444 * <false/>
445 * <!-- XXX is this really part of the partition info? -->
446 * <key>vtoc-timestamp</key>
447 * <integer>...</integer>
448 *
449 * <!-- mvme68k partition maps use 4.4BSD partition
450 * info stuffed into two different areas of the
451 * disk information label recognized by BUG. -->
452 *
453 * <!-- XXX What else? -->
454 * </dict>
455 */
456
457struct disk {
458 TAILQ_ENTRY(disk) dk_link; /* link in global disklist */
459 const char *dk_name; /* disk name */
460 prop_dictionary_t dk_info; /* reference to disk-info dictionary */
461 struct disk_geom dk_geom; /* cooked version of dk_info */
462 int dk_bopenmask; /* block devices open */
463 int dk_copenmask; /* character devices open */
464 int dk_openmask; /* composite (bopen|copen) */
465 int dk_state; /* label state ### */
466 int dk_blkshift; /* shift to convert DEV_BSIZE to blks */
467 int dk_byteshift; /* shift to convert bytes to blks */
468
469 /*
470 * Metrics data; note that some metrics may have no meaning
471 * on certain types of disks.
472 */
473 struct io_stats *dk_stats;
474
475 const struct dkdriver *dk_driver; /* pointer to driver */
476
477 /*
478 * Information required to be the parent of a disk wedge.
479 */
480 kmutex_t dk_rawlock; /* lock on these fields */
481 u_int dk_rawopens; /* # of openes of rawvp */
482 struct vnode *dk_rawvp; /* vnode for the RAW_PART bdev */
483
484 kmutex_t dk_openlock; /* lock on these and openmask */
485 u_int dk_nwedges; /* # of configured wedges */
486 /* all wedges on this disk */
487 LIST_HEAD(, dkwedge_softc) dk_wedges;
488
489 /*
490 * Disk label information. Storage for the in-core disk label
491 * must be dynamically allocated, otherwise the size of this
492 * structure becomes machine-dependent.
493 */
494 daddr_t dk_labelsector; /* sector containing label */
495 struct disklabel *dk_label; /* label */
496 struct cpu_disklabel *dk_cpulabel;
497};
498
499struct dkdriver {
500 void (*d_strategy)(struct buf *);
501 void (*d_minphys)(struct buf *);
502 int (*d_open)(dev_t, int, int, struct lwp *);
503 int (*d_close)(dev_t, int, int, struct lwp *);
504 int (*d_diskstart)(device_t, struct buf *);
505 void (*d_iosize)(device_t, int *);
506 int (*d_dumpblocks)(device_t, void *, daddr_t, int);
507 int (*d_lastclose)(device_t);
508 int (*d_discard)(device_t, off_t, off_t);
509 int (*d_firstopen)(device_t, dev_t, int, int);
510 void (*d_label)(device_t, struct disklabel *lp);
511};
512
513/* states */
514#define DK_CLOSED 0 /* drive is closed */
515#define DK_WANTOPEN 1 /* drive being opened */
516#define DK_WANTOPENRAW 2 /* drive being opened */
517#define DK_RDLABEL 3 /* label being read */
518#define DK_OPEN 4 /* label read, drive open */
519#define DK_OPENRAW 5 /* open without label */
520
521#define DK_BSIZE2BLKSHIFT(b) ((ffs((b) / DEV_BSIZE)) - 1)
522#define DK_BSIZE2BYTESHIFT(b) (ffs((b)) - 1)
523#define DK_DEV_BSIZE_OK(b) \
524 ((b) >= DEV_BSIZE && ((b) & ((b) - 1)) == 0 && (b) <= MAXPHYS)
525
526extern int disk_count; /* number of disks in global disklist */
527
528struct proc;
529
530void disk_rename(struct disk *, const char *);
531void disk_attach(struct disk *);
532int disk_begindetach(struct disk *, int (*)(device_t), device_t, int);
533void disk_detach(struct disk *);
534void disk_init(struct disk *, const char *, const struct dkdriver *);
535void disk_destroy(struct disk *);
536void disk_wait(struct disk *);
537void disk_busy(struct disk *);
538void disk_unbusy(struct disk *, long, int);
539bool disk_isbusy(struct disk *);
540struct disk *disk_find(const char *);
541int disk_ioctl(struct disk *, dev_t, u_long, void *, int, struct lwp *);
542void disk_set_info(device_t, struct disk *, const char *);
543
544void dkwedge_init(void);
545int dkwedge_add(struct dkwedge_info *);
546int dkwedge_del(struct dkwedge_info *);
547void dkwedge_delall(struct disk *);
548int dkwedge_list(struct disk *, struct dkwedge_list *, struct lwp *);
549void dkwedge_discover(struct disk *);
550int dkwedge_read(struct disk *, struct vnode *, daddr_t, void *, size_t);
551device_t dkwedge_find_by_wname(const char *);
552device_t dkwedge_find_by_parent(const char *, size_t *);
553const char *dkwedge_get_parent_name(dev_t);
554void dkwedge_print_wnames(void);
555device_t dkwedge_find_partition(device_t, daddr_t, uint64_t);
556
557#endif /* _KERNEL */
558
559#endif /* _SYS_DISK_H_ */
560