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