xref: /illumos-gate/usr/src/uts/common/sys/cmlb.h (revision 5196acaea56d98e47010f746097c6f61b937a987)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2016 Toomas Soome <tsoome@me.com>
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _SYS_CMLB_H
28 #define	_SYS_CMLB_H
29 
30 #ifdef	__cplusplus
31 extern "C" {
32 #endif
33 
34 #include <sys/dktp/fdisk.h>
35 
36 /*
37  * structure used for getting phygeom and virtgeom from target driver
38  */
39 typedef struct cmlb_geom {
40 	unsigned int    g_ncyl;
41 	unsigned short  g_acyl;
42 	unsigned short  g_nhead;
43 	unsigned short  g_nsect;
44 	unsigned short  g_secsize;
45 	diskaddr_t	g_capacity;
46 	unsigned short  g_intrlv;
47 	unsigned short  g_rpm;
48 } cmlb_geom_t;
49 
50 
51 typedef struct tg_attribute {
52 	int media_is_writable;
53 	int media_is_solid_state;
54 	int media_is_rotational;
55 } tg_attribute_t;
56 
57 
58 
59 /* bit definitions for alter_behavior passed to cmlb_attach */
60 
61 #define	CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT	0x00000001
62 #define	CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8		0x00000002
63 #define	CMLB_OFF_BY_ONE					0x00000004
64 #define	CMLB_FAKE_LABEL_ONE_PARTITION			0x00000008
65 #define	CMLB_INTERNAL_MINOR_NODES			0x00000010
66 #define	CMLB_CREATE_P0_MINOR_NODE			0x00000020
67 
68 /* bit definitions of flag passed to cmlb_validate */
69 #define	CMLB_SILENT					0x00000001
70 
71 /* version for tg_ops */
72 #define	TG_DK_OPS_VERSION_0	0
73 #define	TG_DK_OPS_VERSION_1	1
74 
75 /* definitions for cmd passed to tg_rdwr */
76 #define	TG_READ			0
77 #define	TG_WRITE		1
78 
79 /* definitions for cmd passed to tg_getinfo */
80 #define	TG_GETPHYGEOM		1
81 #define	TG_GETVIRTGEOM		2
82 #define	TG_GETCAPACITY		3
83 #define	TG_GETBLOCKSIZE		4
84 #define	TG_GETATTR		5
85 
86 #if defined(_SUNOS_VTOC_8)
87 
88 #define	CMLBUNIT_DFT_SHIFT	3
89 /* This will support p0 node on sparc */
90 #define	CMLBUNIT_FORCE_P0_SHIFT	(CMLBUNIT_DFT_SHIFT + 1)
91 
92 #elif defined(_SUNOS_VTOC_16)
93 
94 #define	CMLBUNIT_DFT_SHIFT	6
95 #define	CMLBUNIT_FORCE_P0_SHIFT	(CMLBUNIT_DFT_SHIFT)
96 
97 #else	/* defined(_SUNOS_VTOC_16) */
98 
99 #error "No VTOC format defined."
100 
101 #endif	/* defined(_SUNOS_VTOC_8) */
102 
103 /*
104  * Ops vector including utility functions into target driver that cmlb uses.
105  */
106 typedef struct cmlb_tg_ops {
107 	int	tg_version;
108 
109 	/*
110 	 * tg_rdwr:
111 	 *	perform read/write on target device associated with devi.
112 	 *
113 	 * Arguments:
114 	 *
115 	 *	devi:		pointer to device's dev_info structure.
116 	 *
117 	 *	cmd:		operation to perform.
118 	 *			Possible values: TG_READ, TG_WRITE
119 	 *
120 	 *	bufp:		pointer to allocated buffer for transfer
121 	 *
122 	 *	start_block:	starting block number to read/write (based on
123 	 *			system blocksize, DEV_BSIZE)
124 	 *
125 	 *	reqlength:	requested transfer length (in bytes)
126 	 *
127 	 *	tg_cookie 	cookie from target driver to be passed back to
128 	 *			target driver when we call back to it through
129 	 *			tg_ops.
130 	 *
131 	 * Note: It is the responsibility of caller to make sure
132 	 *	length of buffer pointed to by bufp is at least equal to
133 	 *	requested transfer length
134 	 *
135 	 * Return values:
136 	 *	0		success
137 	 *	ENOMEM		can not allocate memory
138 	 *	EACCESS  	reservation conflict
139 	 *	EIO		I/O error
140 	 *	EFAULT		copyin/copyout error
141 	 *	ENXIO		internal error/ invalid devi
142 	 *	EINVAL		invalid command value.
143 	 */
144 	int (*tg_rdwr)(dev_info_t *devi, uchar_t cmd, void *bufp,
145 	    diskaddr_t start_block, size_t reqlength, void *tg_cookie);
146 
147 	/*
148 	 * tg_getinfo:
149 	 * 	Report the information requested on device/media and
150 	 *	store the requested info in area pointed to by arg.
151 	 *
152 	 * Arguments:
153 	 *	devi:		pointer to device's dev_info structure.
154 	 *
155 	 *	cmd:		operation to perform
156 	 *
157 	 *	arg:		arg for the operation for result.
158 	 *
159 	 *	tg_cookie 	cookie from target driver to be passed back to
160 	 *			target driver when we call back to it through
161 	 *			tg_ops.
162 	 *
163 	 * 	Possible commands and the interpretation of arg:
164 	 *
165 	 *	cmd:
166 	 *		TG_GETPHYGEOM
167 	 *			Obtain raw physical geometry from target,
168 	 *			and store in structure pointed to by arg,
169 	 *			a cmlb_geom_t structure.
170 	 *
171 	 * 		TG_GETVIRTGEOM:
172 	 *			Obtain HBA geometry for the target and
173 	 *			store in struct pointed to by arg,
174 	 *			a cmlb_geom_t structure.
175 	 *
176 	 *		TG_GETCAPACITY:
177 	 *			Report the capacity of the target (in system
178 	 *			blocksize (DEV_BSIZE) and store in the
179 	 *			space pointed to by arg, a diskaddr_t.
180 	 *
181 	 *		TG_GETBLOCKSIZE:
182 	 *			Report the block size of the target
183 	 *			in the space pointed to by arg, a uint32_t.
184 	 *
185 	 *		TG_GETATTR:
186 	 * 			Report the information requested on
187 	 *			device/media and store in area pointed to by
188 	 *			arg, a tg_attribute_t structure.
189 	 *			Return values:
190 	 *
191 	 * Return values:
192 	 *	0		success
193 	 *
194 	 *	EACCESS		reservation conflict
195 	 *
196 	 *	ENXIO		internal error/invalid devi
197 	 *
198 	 *	EINVAL		When command is TG_GETPHYGEOM or
199 	 *			TG_GETVIRTGEOM, or TG_GETATTR, this return code
200 	 *			indicates the operation is not applicable to
201 	 *			target.
202 	 *			In case of TG_GETCAP, this return code
203 	 *			indicates no media in the drive.
204 	 *
205 	 *	EIO		An error occurred during obtaining info
206 	 *			from device/media.
207 	 *
208 	 *	ENOTSUP		In case of TG_GETCAP, target does not
209 	 *			support getting capacity info.
210 	 *
211 	 *	ENOTTY		Unknown command.
212 	 *
213 	 *
214 	 */
215 	int (*tg_getinfo)(dev_info_t *devi, int cmd, void *arg,
216 	    void *tg_cookie);
217 
218 } cmlb_tg_ops_t;
219 
220 
221 typedef struct __cmlb_handle *cmlb_handle_t;
222 
223 /*
224  *
225  * Functions exported from cmlb
226  *
227  * Note: Most these functions can callback to target driver through the
228  * tg_ops functions. Target driver should consider this for synchronization.
229  * Any functions that may adjust minor nodes should be called when
230  * the target driver ensures it is safe to do so.
231  */
232 
233 /*
234  * cmlb_alloc_handle:
235  *
236  *	Allocates a handle.
237  *
238  * Arguments:
239  *	cmlbhandlep	pointer to handle
240  *
241  * Notes:
242  *	Allocates a handle and stores the allocated handle in the area
243  *	pointed to by cmlbhandlep
244  *
245  * Context:
246  *	Kernel thread only (can sleep).
247  */
248 void
249 cmlb_alloc_handle(cmlb_handle_t *cmlbhandlep);
250 
251 
252 /*
253  * cmlb_attach:
254  *
255  *	Attach handle to device, create minor nodes for device.
256  *
257  *
258  * Arguments:
259  * 	devi		pointer to device's dev_info structure.
260  * 	tgopsp		pointer to array of functions cmlb can use to callback
261  *			to target driver.
262  *
263  *	device_type	Peripheral device type as defined in
264  *			scsi/generic/inquiry.h
265  *
266  *	is_removable	whether or not device is removable.
267  *
268  *	is_hotpluggable	whether or not device is hotpluggable.
269  *
270  *	node_type	minor node type (as used by ddi_create_minor_node)
271  *
272  *	alter_behavior
273  *			bit flags:
274  *
275  *			CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT: create
276  *			an alternate slice for the default label, if
277  *			device type is DTYPE_DIRECT an architectures default
278  *			label type is VTOC16.
279  *			Otherwise alternate slice will no be created.
280  *
281  *
282  *			CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8: report a default
283  *			geometry and label for DKIOCGGEOM and DKIOCGVTOC
284  *			on architecture with VTOC 8 label types.
285  *
286  * 			CMLB_OFF_BY_ONE: do the workaround for legacy off-by-
287  *			one bug in obtaining capacity (used for sd).
288  *
289  *
290  *	cmlbhandle	cmlb handle associated with device
291  *
292  *	tg_cookie 	cookie from target driver to be passed back to target
293  *			driver when we call back to it through tg_ops.
294  *
295  *			cmlb does not interpret the values. It is currently
296  *			used for sd to indicate whether retries are allowed
297  *			on commands or not. e.g when cmlb entries are called
298  *			from interrupt context on removable media, sd rather
299  *			not have retries done.
300  *
301  *
302  *
303  * Notes:
304  *	Assumes a default label based on capacity for non-removable devices.
305  *	If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC
306  *	for the architecture).
307  *	For removable devices, default label type is assumed to be VTOC
308  *	type. Create minor nodes based on a default label type.
309  *	Label on the media is not validated.
310  *	minor number consists of:
311  *		if _SUNOS_VTOC_8 is defined
312  *			lowest 3 bits is taken as partition number
313  *			the rest is instance number
314  *		if _SUNOS_VTOC_16 is defined
315  *			lowest 6 bits is taken as partition number
316  *			the rest is instance number
317  *
318  *
319  * Return values:
320  *	0 	Success
321  * 	ENXIO 	creating minor nodes failed.
322  *	EINVAL	invalid arg, unsupported tg_ops version
323  *
324  */
325 int
326 cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type,
327     boolean_t is_removable, boolean_t is_hotpluggable, char *node_type,
328     int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie);
329 
330 
331 /*
332  * cmlb_validate:
333  *
334  *	Validates label.
335  *
336  * Arguments
337  *	cmlbhandle	cmlb handle associated with device.
338  *
339  * 	int 		flags
340  *			currently used for verbosity control.
341  *			CMLB_SILENT is the only current definition for it
342  *	tg_cookie 	cookie from target driver to be passed back to target
343  *			driver when we call back to it through tg_ops.
344  * Notes:
345  *	If new label type is different from the current, adjust minor nodes
346  *	accordingly.
347  *
348  * Return values:
349  *	0		success
350  *			Note: having fdisk but no solaris partition is assumed
351  *			success.
352  *
353  *	ENOMEM		memory allocation failed
354  *	EIO		i/o errors during read or get capacity
355  * 	EACCESS		reservation conflicts
356  * 	EINVAL		label was corrupt, or no default label was assumed
357  *	ENXIO		invalid handle
358  *
359  */
360 int
361 cmlb_validate(cmlb_handle_t cmlbhandle, int flags, void *tg_cookie);
362 
363 /*
364  * cmlb_invalidate:
365  *	Invalidate in core label data
366  *
367  * Arguments:
368  *	cmlbhandle	cmlb handle associated with device.
369  *	tg_cookie 	cookie from target driver to be passed back to target
370  *			driver when we call back to it through tg_ops.
371  */
372 void
373 cmlb_invalidate(cmlb_handle_t cmlbhandle, void *tg_cookie);
374 
375 
376 
377 /*
378  * cmlb_is_valid
379  *	 Get status on whether the incore label/geom data is valid
380  *
381  * Arguments:
382  *      cmlbhandle      cmlb handle associated with device.
383  *
384  * Return values:
385  *      TRUE if valid
386  *      FALSE otherwise.
387  *
388  */
389 boolean_t
390 cmlb_is_valid(cmlb_handle_t cmlbhandle);
391 
392 /*
393  * cmlb_partinfo:
394  *	Get partition info for specified partition number.
395  *
396  * Arguments:
397  *	cmlbhandle	cmlb handle associated with device.
398  *	part		partition number
399  *			driver when we call back to it through tg_ops.
400  *	nblocksp	pointer to number of blocks
401  *	startblockp	pointer to starting block
402  *	partnamep	pointer to name of partition
403  *	tagp		pointer to tag info
404  *	tg_cookie 	cookie from target driver to be passed back to target
405  *
406  * Notes:
407  *	If in-core label is not valid, this functions tries to revalidate
408  *	the label. If label is valid, it stores the total number of blocks
409  *	in this partition in the area pointed to by nblocksp, starting
410  *	block number in area pointed to by startblockp,  pointer to partition
411  *	name in area pointed to by partnamep, and tag value in area
412  *	pointed by tagp.
413  *	For EFI labels, tag value will be set to 0.
414  *
415  *	For all nblocksp, startblockp and partnamep, tagp, a value of NULL
416  *	indicates the corresponding info is not requested.
417  *
418  *
419  * Return values:
420  *	0	success
421  *	EINVAL  no valid label or requested partition number is invalid.
422  *
423  */
424 int
425 cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp,
426     diskaddr_t *startblockp, char **partnamep, uint16_t *tagp, void *tg_cookie);
427 
428 /*
429  * cmlb_efi_label_capacity:
430  *	Get capacity stored in EFI disk label.
431  *
432  * Arguments:
433  *	cmlbhandle	cmlb handle associated with device.
434  *	capacity	pointer to capacity stored in EFI disk label.
435  *	tg_cookie	cookie from target driver to be passed back to target
436  *			driver when we call back to it through tg_ops.
437  *
438  *
439  * Notes:
440  *	If in-core label is not valid, this functions tries to revalidate
441  *	the label. If label is valid and is an EFI label, it stores the capacity
442  *      in disk label in the area pointed to by capacity.
443  *
444  *
445  * Return values:
446  *	0	success
447  *	EINVAL  no valid EFI label or capacity is NULL.
448  *
449  */
450 int
451 cmlb_efi_label_capacity(cmlb_handle_t cmlbhandle, diskaddr_t *capacity,
452     void *tg_cookie);
453 
454 /*
455  * cmlb_ioctl:
456  * Ioctls for label handling will be handled by this function.
457  * These are:
458  *	DKIOCGGEOM
459  *	DKIOCSGEOM
460  *	DKIOCGAPART
461  *	DKIOCSAPART
462  *	DKIOCGVTOC
463  *	DKIOCGETEFI
464  *	DKIOCPARTITION
465  *	DKIOCSVTOC
466  * 	DKIOCSETEFI
467  *	DKIOCGMBOOT
468  *	DKIOCSMBOOT
469  *	DKIOCG_PHYGEOM
470  *	DKIOCG_VIRTGEOM
471  *	DKIOCPARTINFO
472  *
473  *
474  *   Arguments:
475  *	cmlbhandle 	handle associated with device.
476  *      cmd     	ioctl operation to be performed
477  *      arg     	user argument, contains data to be set or reference
478  *                      parameter for get
479  *	flag    	bit flag, indicating open settings, 32/64 bit type
480  *      cred_p  	user credential pointer (not currently used)
481  *	rval_p  	not currently used
482  *	tg_cookie 	cookie from target driver to be passed back to target
483  *			driver when we call back to it through tg_ops.
484  *
485  *
486  *
487  * Return values:
488  *	0
489  *	EINVAL
490  *	ENOTTY
491  *	ENXIO
492  *	EIO
493  *	EFAULT
494  *	ENOTSUP
495  *	EPERM
496  */
497 int
498 cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd,
499     intptr_t arg, int flag, cred_t *cred_p, int *rval_p, void *tg_cookie);
500 
501 /*
502  * cmlb_prop_op:
503  *	provide common label prop_op(9E) implementation that understands the
504  *	size(9p) properties.
505  *
506  * Arguments:
507  *	cmlbhandle	cmlb handle associated with device.
508  *	dev		See prop_op(9E)
509  *	dip		"
510  *	prop_op		"
511  *	mod_flags	"
512  *	name		"
513  *	valuep		"
514  *	lengthp		"
515  *	part		partition number
516  *	tg_cookie 	cookie from target driver to be passed back to target
517  */
518 int
519 cmlb_prop_op(cmlb_handle_t cmlbhandle,
520     dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
521     char *name, caddr_t valuep, int *lengthp, int part, void *tg_cookie);
522 
523 /*
524  * cmlb_get_devid_block:
525  *	 get the block number where device id is stored.
526  *
527  * Arguments:
528  *	cmlbhandle	cmlb handle associated with device.
529  *	devidblockp	pointer to block number.
530  *	tg_cookie 	cookie from target driver to be passed back to target
531  *			driver when we call back to it through tg_ops.
532  *
533  * Notes:
534  *	It stores the block number of device id in the area pointed to
535  *	by devidblockp.
536  *
537  * Return values:
538  *	0	success
539  *	EINVAL 	device id does not apply to current label type.
540  */
541 int
542 cmlb_get_devid_block(cmlb_handle_t cmlbhandle, diskaddr_t *devidblockp,
543     void *tg_cookie);
544 
545 
546 /*
547  * cmlb_close:
548  *
549  * Close the device, revert to a default label minor node for the device,
550  * if it is removable.
551  *
552  * Arguments:
553  *	cmlbhandle	cmlb handle associated with device.
554  *
555  *	tg_cookie 	cookie from target driver to be passed back to target
556  *			driver when we call back to it through tg_ops.
557  * Return values:
558  *	0	Success
559  * 	ENXIO	Re-creating minor node failed.
560  */
561 int
562 cmlb_close(cmlb_handle_t cmlbhandle, void *tg_cookie);
563 
564 /*
565  * cmlb_detach:
566  *
567  * Invalidate in-core labeling data and remove all minor nodes for
568  * the device associate with handle.
569  *
570  * Arguments:
571  *	cmlbhandle	cmlb handle associated with device.
572  *	tg_cookie 	cookie from target driver to be passed back to target
573  *			driver when we call back to it through tg_ops.
574  *
575  */
576 void
577 cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie);
578 
579 /*
580  * cmlb_free_handle
581  *
582  *	Frees handle.
583  *
584  * Arguments:
585  *	cmlbhandlep	pointer to handle
586  *
587  */
588 void
589 cmlb_free_handle(cmlb_handle_t *cmlbhandlep);
590 
591 #ifdef	__cplusplus
592 }
593 #endif
594 
595 #endif /* _SYS_CMLB_H */
596