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