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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _SYS_DR_H 28 #define _SYS_DR_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 #include <sys/types.h> 37 #include <sys/processor.h> 38 #include <sys/obpdefs.h> 39 #include <sys/memlist.h> 40 #include <sys/sbd_ioctl.h> 41 #include <sys/mem_config.h> 42 #include <sys/dr_util.h> 43 #include <sys/drmach.h> 44 #include <sys/param.h> /* for MAXPATHLEN */ 45 #include <sys/varargs.h> 46 #include <sys/note.h> 47 48 #define DR_MAXNUM_NT 3 49 50 /* used to map sbd_comp_type_t to array index */ 51 #define NIX(t) \ 52 (((t) == SBD_COMP_CPU) ? 0 : \ 53 ((t) == SBD_COMP_MEM) ? 1 : \ 54 ((t) == SBD_COMP_IO) ? 2 : \ 55 ((t) == SBD_COMP_CMP) ? 0 : DR_MAXNUM_NT) 56 57 /* 58 * helper macros for constructing and reporting internal error messages. 59 * NOTE: each module which uses one or more this these macros is expected 60 * to supply a char *dr_ie_fmt string containing the SCCS filename 61 * expansion macro (percent M percent) and a sprintf %d to render the 62 * line number argument. 63 */ 64 #define DR_INTERNAL_ERROR(hp) \ 65 drerr_new(1, ESBD_INTERNAL, dr_ie_fmt, __LINE__) 66 67 #define DR_OP_INTERNAL_ERROR(hp) \ 68 drerr_set_c(CE_WARN, &(hp)->h_err, \ 69 ESBD_INTERNAL, dr_ie_fmt, __LINE__) 70 71 #define DR_DEV_INTERNAL_ERROR(cp) \ 72 drerr_set_c(CE_WARN, &(cp)->sbdev_error, \ 73 ESBD_INTERNAL, dr_ie_fmt, __LINE__) 74 75 /* 76 * TODO: Simplify or get rid of this. 77 * Macros for keeping an error code and an associated list of integers. 78 */ 79 #define DR_MAX_ERR_INT (32) 80 #define DR_GET_E_CODE(sep) ((sep)->e_code) 81 #define DR_SET_E_CODE(sep, en) ((sep)->e_code = (en)) 82 #define DR_GET_E_RSC(sep) ((sep)->e_rsc) 83 84 /* 85 * Format of dr_devset_t bit masks: 86 * 87 * 32 16 8 0 88 * |....|....|....|IIII|....|...M|CCCC|CCCC| 89 * 90 * 1 = indicates respective component present/attached. 91 * I = I/O, M = Memory, C = CPU. 92 */ 93 #define DEVSET_ANYUNIT (-1) 94 #define _NT2DEVPOS(t, u) ((NIX(t) << 3) + (u)) 95 #define _DEVSET_MASK 0x000f01ff 96 #define _CMP_DEVSET_MASK 0x11 97 #define DEVSET(t, u) \ 98 (((u) == DEVSET_ANYUNIT) ? \ 99 (dr_devset_t)((0xff << _NT2DEVPOS((t), 0)) & _DEVSET_MASK) : \ 100 ((t) == SBD_COMP_CMP) ? \ 101 (dr_devset_t)(_CMP_DEVSET_MASK << _NT2DEVPOS((t), (u))) : \ 102 (dr_devset_t)(1 << _NT2DEVPOS((t), (u)))) 103 104 #define DEVSET_IN_SET(ds, t, u) (((ds) & DEVSET((t), (u))) != 0) 105 #define DEVSET_ADD(ds, t, u) ((ds) |= DEVSET((t), (u))) 106 #define DEVSET_DEL(ds, t, u) ((ds) &= ~DEVSET((t), (u))) 107 #define DEVSET_GET_UNITSET(ds, t) \ 108 (((ds) & DEVSET((t), DEVSET_ANYUNIT)) >> _NT2DEVPOS((t), 0)) 109 110 /* 111 * Ops for dr_board_t.b_dev_* 112 */ 113 #define DR_DEV_IS(ds, cp) DEVSET_IN_SET( \ 114 (cp)->sbdev_bp->b_dev_##ds, \ 115 (cp)->sbdev_type, \ 116 (cp)->sbdev_unum) 117 118 #define DR_DEV_ADD(ds, cp) DEVSET_ADD( \ 119 (cp)->sbdev_bp->b_dev_##ds, \ 120 (cp)->sbdev_type, \ 121 (cp)->sbdev_unum) 122 123 #define DR_DEV_DEL(ds, cp) DEVSET_DEL( \ 124 (cp)->sbdev_bp->b_dev_##ds, \ 125 (cp)->sbdev_type, \ 126 (cp)->sbdev_unum) 127 128 /* 129 * Ops for dr_board_t.b_dev_present 130 */ 131 #define DR_DEV_IS_PRESENT(cp) DR_DEV_IS(present, cp) 132 #define DR_DEV_SET_PRESENT(cp) DR_DEV_ADD(present, cp) 133 #define DR_DEV_CLR_PRESENT(cp) DR_DEV_DEL(present, cp) 134 135 /* 136 * Ops for dr_board_t.b_dev_attached 137 */ 138 #define DR_DEV_IS_ATTACHED(cp) DR_DEV_IS(attached, cp) 139 #define DR_DEV_SET_ATTACHED(cp) DR_DEV_ADD(attached, cp) 140 #define DR_DEV_CLR_ATTACHED(cp) DR_DEV_DEL(attached, cp) 141 142 /* 143 * Ops for dr_board_t.b_dev_released 144 */ 145 #define DR_DEV_IS_RELEASED(cp) DR_DEV_IS(released, cp) 146 #define DR_DEV_SET_RELEASED(cp) DR_DEV_ADD(released, cp) 147 #define DR_DEV_CLR_RELEASED(cp) DR_DEV_DEL(released, cp) 148 149 /* 150 * Ops for dr_board_t.b_dev_unreferenced 151 */ 152 #define DR_DEV_IS_UNREFERENCED(cp) DR_DEV_IS(unreferenced, cp) 153 #define DR_DEV_SET_UNREFERENCED(cp) DR_DEV_ADD(unreferenced, cp) 154 #define DR_DEV_CLR_UNREFERENCED(cp) DR_DEV_DEL(unreferenced, cp) 155 156 #define DR_DEVS_PRESENT(bp) \ 157 ((bp)->b_dev_present) 158 #define DR_DEVS_ATTACHED(bp) \ 159 ((bp)->b_dev_attached) 160 #define DR_DEVS_RELEASED(bp) \ 161 ((bp)->b_dev_released) 162 #define DR_DEVS_UNREFERENCED(bp) \ 163 ((bp)->b_dev_unreferenced) 164 #define DR_DEVS_UNATTACHED(bp) \ 165 ((bp)->b_dev_present & ~(bp)->b_dev_attached) 166 #define DR_DEVS_CONFIGURE(bp, devs) \ 167 ((bp)->b_dev_attached = (devs)) 168 #define DR_DEVS_DISCONNECT(bp, devs) \ 169 ((bp)->b_dev_present &= ~(devs)) 170 #define DR_DEVS_CANCEL(bp, devs) \ 171 ((bp)->b_dev_released &= ~(devs), \ 172 (bp)->b_dev_unreferenced &= ~(devs)) 173 174 /* 175 * CMP Specific Helpers 176 */ 177 #define DR_CMP_CORE_UNUM(cmp, core) (cmp + (core * 4)) 178 #define DR_UNUM2SBD_UNUM(unum) (unum & 0x3) 179 180 /* 181 * Some stuff to assist in debug. 182 */ 183 #ifdef DEBUG 184 #define DRDBG_STATE 0x00000001 185 #define DRDBG_QR 0x00000002 186 #define DRDBG_CPU 0x00000004 187 #define DRDBG_MEM 0x00000008 188 #define DRDBG_IO 0x00000010 189 190 #define PR_ALL if (dr_debug) printf 191 #define PR_STATE if (dr_debug & DRDBG_STATE) printf 192 #define PR_QR if (dr_debug & DRDBG_QR) prom_printf 193 #define PR_CPU if (dr_debug & DRDBG_CPU) printf 194 #define PR_MEM if (dr_debug & DRDBG_MEM) printf 195 #define PR_IO if (dr_debug & DRDBG_IO) printf 196 #define PR_MEMLIST_DUMP if (dr_debug & DRDBG_MEM) MEMLIST_DUMP 197 198 extern uint_t dr_debug; 199 #else /* DEBUG */ 200 #define PR_ALL _NOTE(CONSTANTCONDITION) if (0) printf 201 #define PR_STATE PR_ALL 202 #define PR_QR PR_ALL 203 #define PR_CPU PR_ALL 204 #define PR_MEM PR_ALL 205 #define PR_IO PR_ALL 206 #define PR_MEMLIST_DUMP _NOTE(CONSTANTCONDITION) if (0) MEMLIST_DUMP 207 208 #endif /* DEBUG */ 209 210 /* 211 * dr_board_t b_sflags. 212 */ 213 #define DR_BSLOCK 0x01 /* for blocking status (protected by b_slock) */ 214 215 typedef const char *fn_t; 216 typedef uint32_t dr_devset_t; /* TODO: fix limitation */ 217 218 /* 219 * Unsafe devices based on dr.conf prop "unsupported-io-drivers" 220 */ 221 typedef struct { 222 char **devnames; 223 uint_t ndevs; 224 } dr_unsafe_devs_t; 225 226 /* 227 * Device states. 228 * PARTIAL state is really only relevant for board state. 229 */ 230 typedef enum { 231 DR_STATE_EMPTY = 0, 232 DR_STATE_OCCUPIED, 233 DR_STATE_CONNECTED, 234 DR_STATE_UNCONFIGURED, 235 DR_STATE_PARTIAL, /* part connected, part configured */ 236 DR_STATE_CONFIGURED, 237 DR_STATE_RELEASE, 238 DR_STATE_UNREFERENCED, 239 DR_STATE_FATAL, 240 DR_STATE_MAX 241 } dr_state_t; 242 243 typedef struct dr_handle { 244 struct dr_board *h_bd; 245 sbd_error_t *h_err; 246 int h_op_intr; /* nz if op interrupted */ 247 dev_t h_dev; /* dev_t of opened device */ 248 int h_cmd; /* PIM ioctl argument */ 249 int h_mode; /* device open mode */ 250 sbd_cmd_t h_sbdcmd; /* copied-in ioctl cmd struct */ 251 sbd_ioctl_arg_t *h_iap; /* ptr to caller-space cmd struct */ 252 dr_devset_t h_devset; /* based on h_dev */ 253 uint_t h_ndi; 254 drmach_opts_t h_opts; /* command-line platform options */ 255 } dr_handle_t; 256 257 typedef struct dr_common_unit { 258 dr_state_t sbdev_state; 259 sbd_state_t sbdev_ostate; 260 sbd_cond_t sbdev_cond; 261 time_t sbdev_time; 262 int sbdev_busy; 263 struct dr_board *sbdev_bp; 264 int sbdev_unum; 265 sbd_comp_type_t sbdev_type; 266 drmachid_t sbdev_id; 267 char sbdev_path[MAXNAMELEN]; 268 sbd_error_t *sbdev_error; 269 } dr_common_unit_t; 270 271 typedef struct dr_mem_unit { 272 dr_common_unit_t sbm_cm; /* mem-unit state */ 273 uint_t sbm_flags; 274 pfn_t sbm_basepfn; 275 pgcnt_t sbm_npages; 276 pgcnt_t sbm_pageslost; 277 struct memlist *sbm_dyn_segs; /* kphysm_add_dynamic segs */ 278 /* 279 * The following fields are used during 280 * the memory detach process only. sbm_mlist 281 * will be used to store the board memlist 282 * following a detach. The memlist will be 283 * used to re-attach the board when configuring 284 * the unit directly after an unconfigure. 285 */ 286 struct dr_mem_unit *sbm_peer; 287 struct memlist *sbm_mlist; 288 struct memlist *sbm_del_mlist; 289 memhandle_t sbm_memhandle; 290 pfn_t sbm_alignment_mask; 291 pfn_t sbm_slice_offset; 292 uint64_t sbm_slice_size; 293 } dr_mem_unit_t; 294 295 /* 296 * Currently only maintain state information for individual 297 * components. 298 */ 299 typedef struct dr_cpu_unit { 300 dr_common_unit_t sbc_cm; /* cpu-unit state */ 301 processorid_t sbc_cpu_id; 302 cpu_flag_t sbc_cpu_flags; /* snapshot of CPU flags */ 303 ushort_t sbc_pad1; /* padded for compatibility */ 304 int sbc_speed; 305 int sbc_ecache; 306 int sbc_cpu_impl; 307 } dr_cpu_unit_t; 308 309 typedef struct dr_io_unit { 310 dr_common_unit_t sbi_cm; /* io-unit state */ 311 } dr_io_unit_t; 312 313 typedef union { 314 dr_common_unit_t du_common; 315 dr_mem_unit_t du_mem; 316 dr_cpu_unit_t du_cpu; 317 dr_io_unit_t du_io; 318 } dr_dev_unit_t; 319 320 typedef struct dr_board { 321 kmutex_t b_lock; /* lock for this board struct */ 322 kmutex_t b_slock; /* lock for status on the board */ 323 kcondvar_t b_scv; /* condvar for status on the board */ 324 int b_sflags; /* for serializing status */ 325 sbd_state_t b_rstate; /* board's cfgadm receptacle state */ 326 sbd_state_t b_ostate; /* board's cfgadm occupant state */ 327 sbd_cond_t b_cond; /* cfgadm condition */ 328 int b_busy; 329 int b_assigned; 330 time_t b_time; /* time of last board operation */ 331 char b_type[MAXNAMELEN]; 332 drmachid_t b_id; 333 int b_num; /* board number */ 334 int b_ndev; /* # of devices on board */ 335 dev_info_t *b_dip; /* dip for make-nodes */ 336 dr_state_t b_state; /* board DR state */ 337 dr_devset_t b_dev_present; /* present mask */ 338 dr_devset_t b_dev_attached; /* attached mask */ 339 dr_devset_t b_dev_released; /* released mask */ 340 dr_devset_t b_dev_unreferenced; /* unreferenced mask */ 341 char b_path[MAXNAMELEN]; 342 dr_dev_unit_t *b_dev[DR_MAXNUM_NT]; 343 } dr_board_t; 344 345 /* 346 * dr_quiesce.c interfaces 347 */ 348 struct dr_sr_handle; 349 typedef struct dr_sr_handle dr_sr_handle_t; 350 351 extern dr_sr_handle_t *dr_get_sr_handle(dr_handle_t *handle); 352 extern void dr_release_sr_handle(dr_sr_handle_t *srh); 353 extern int dr_suspend(dr_sr_handle_t *srh); 354 extern void dr_resume(dr_sr_handle_t *srh); 355 extern void dr_check_devices(dev_info_t *dip, int *refcount, 356 dr_handle_t *handle, uint64_t *arr, 357 int *idx, int len); 358 extern int dr_pt_test_suspend(dr_handle_t *hp); 359 360 /* 361 * dr_cpu.c interface 362 */ 363 extern void dr_init_cpu_unit(dr_cpu_unit_t *cp); 364 extern int dr_pre_attach_cpu(dr_handle_t *hp, 365 dr_common_unit_t **devlist, int devnum); 366 extern void dr_attach_cpu(dr_handle_t *hp, dr_common_unit_t *cp); 367 extern int dr_post_attach_cpu(dr_handle_t *hp, 368 dr_common_unit_t **devlist, int devnum); 369 extern int dr_pre_release_cpu(dr_handle_t *hp, 370 dr_common_unit_t **devlist, int devnum); 371 extern int dr_pre_detach_cpu(dr_handle_t *hp, 372 dr_common_unit_t **devlist, int devnum); 373 extern void dr_detach_cpu(dr_handle_t *hp, dr_common_unit_t *cp); 374 extern int dr_post_detach_cpu(dr_handle_t *hp, 375 dr_common_unit_t **devlist, int devnum); 376 extern int dr_cpu_status(dr_handle_t *hp, dr_devset_t devset, 377 sbd_dev_stat_t *dsp); 378 extern int dr_cancel_cpu(dr_cpu_unit_t *cp); 379 extern int dr_disconnect_cpu(dr_cpu_unit_t *cp); 380 381 382 /* 383 * dr_mem.c interface 384 */ 385 extern void dr_init_mem_unit(dr_mem_unit_t *mp); 386 extern int dr_pre_attach_mem(dr_handle_t *hp, 387 dr_common_unit_t **devlist, int devnum); 388 extern void dr_attach_mem(dr_handle_t *hp, dr_common_unit_t *cp); 389 extern int dr_post_attach_mem(dr_handle_t *hp, 390 dr_common_unit_t **devlist, int devnum); 391 extern int dr_pre_release_mem(dr_handle_t *hp, 392 dr_common_unit_t **devlist, int devnum); 393 extern void dr_release_mem(dr_common_unit_t *cp); 394 extern void dr_release_mem_done(dr_common_unit_t *cp); 395 extern int dr_pre_detach_mem(dr_handle_t *hp, 396 dr_common_unit_t **devlist, int devnum); 397 extern void dr_detach_mem(dr_handle_t *, dr_common_unit_t *); 398 extern int dr_post_detach_mem(dr_handle_t *hp, 399 dr_common_unit_t **devlist, int devnum); 400 extern int dr_mem_status(dr_handle_t *hp, dr_devset_t devset, 401 sbd_dev_stat_t *dsp); 402 extern int dr_cancel_mem(dr_mem_unit_t *mp); 403 extern int dr_disconnect_mem(dr_mem_unit_t *mp); 404 405 /* 406 * dr_io.c interface 407 */ 408 extern void dr_init_io_unit(dr_io_unit_t *io); 409 extern int dr_disconnect_io(dr_io_unit_t *ip); 410 extern int dr_pre_attach_io(dr_handle_t *hp, 411 dr_common_unit_t **devlist, int devnum); 412 extern void dr_attach_io(dr_handle_t *hp, dr_common_unit_t *cp); 413 extern int dr_post_attach_io(dr_handle_t *hp, 414 dr_common_unit_t **devlist, int devnum); 415 extern int dr_pre_release_io(dr_handle_t *hp, 416 dr_common_unit_t **devlist, int devnum); 417 extern int dr_pre_detach_io(dr_handle_t *hp, 418 dr_common_unit_t **devlist, int devnum); 419 extern void dr_detach_io(dr_handle_t *hp, dr_common_unit_t *cp); 420 extern int dr_post_detach_io(dr_handle_t *hp, 421 dr_common_unit_t **devlist, int devnum); 422 extern int dr_io_status(dr_handle_t *hp, dr_devset_t devset, 423 sbd_dev_stat_t *dsp); 424 425 426 /* 427 * dr.c interface 428 */ 429 extern void dr_op_err(int ce, dr_handle_t *hp, int code, char *fmt, ...); 430 extern void dr_dev_err(int ce, dr_common_unit_t *cp, int code); 431 432 extern dr_cpu_unit_t *dr_get_cpu_unit(dr_board_t *bp, int unit_num); 433 extern dr_mem_unit_t *dr_get_mem_unit(dr_board_t *bp, int unit_num); 434 extern dr_io_unit_t *dr_get_io_unit(dr_board_t *bp, int unit_num); 435 436 extern dr_board_t *dr_lookup_board(int board_num); 437 extern int dr_release_dev_done(dr_common_unit_t *cp); 438 extern char *dr_nt_to_dev_type(int type); 439 extern void dr_device_transition(dr_common_unit_t *cp, 440 dr_state_t new_state); 441 extern void dr_lock_status(dr_board_t *bp); 442 extern void dr_unlock_status(dr_board_t *bp); 443 extern int dr_cmd_flags(dr_handle_t *hp); 444 445 #ifdef __cplusplus 446 } 447 #endif 448 449 #endif /* _SYS_DR_H */ 450