17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 525e8c5aaSvikram * Common Development and Distribution License (the "License"). 625e8c5aaSvikram * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2107d06da5SSurya Prakki 227c478bd9Sstevel@tonic-gate /* 23*56f33205SJonathan Adams * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * safari system board DR module. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <sys/debug.h> 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/errno.h> 347c478bd9Sstevel@tonic-gate #include <sys/cred.h> 357c478bd9Sstevel@tonic-gate #include <sys/dditypes.h> 367c478bd9Sstevel@tonic-gate #include <sys/devops.h> 377c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 387c478bd9Sstevel@tonic-gate #include <sys/poll.h> 397c478bd9Sstevel@tonic-gate #include <sys/conf.h> 407c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 417c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 427c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 437c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 447c478bd9Sstevel@tonic-gate #include <sys/stat.h> 457c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 467c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 477c478bd9Sstevel@tonic-gate #include <sys/mem_config.h> 487c478bd9Sstevel@tonic-gate #include <sys/mem_cage.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 517c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 547c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 557c478bd9Sstevel@tonic-gate #include <sys/param.h> 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate #include <sys/sbdpriv.h> 587c478bd9Sstevel@tonic-gate #include <sys/sbd_io.h> 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* start sbd includes */ 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #include <sys/systm.h> 637c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 647c478bd9Sstevel@tonic-gate #include <sys/x_call.h> 657c478bd9Sstevel@tonic-gate #include <sys/membar.h> 667c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate extern int nulldev(); 697c478bd9Sstevel@tonic-gate extern int nodev(); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate typedef struct { /* arg to sbd_get_handle */ 727c478bd9Sstevel@tonic-gate dev_t dev; 737c478bd9Sstevel@tonic-gate int cmd; 747c478bd9Sstevel@tonic-gate int mode; 757c478bd9Sstevel@tonic-gate sbd_ioctl_arg_t *ioargp; 767c478bd9Sstevel@tonic-gate } sbd_init_arg_t; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * sbd support operations. 817c478bd9Sstevel@tonic-gate */ 827c478bd9Sstevel@tonic-gate static void sbd_exec_op(sbd_handle_t *hp); 837c478bd9Sstevel@tonic-gate static void sbd_dev_configure(sbd_handle_t *hp); 847c478bd9Sstevel@tonic-gate static int sbd_dev_release(sbd_handle_t *hp); 857c478bd9Sstevel@tonic-gate static int sbd_dev_unconfigure(sbd_handle_t *hp); 867c478bd9Sstevel@tonic-gate static void sbd_attach_cpu(sbd_handle_t *hp, sbderror_t *ep, 877c478bd9Sstevel@tonic-gate dev_info_t *dip, int unit); 887c478bd9Sstevel@tonic-gate static void sbd_detach_cpu(sbd_handle_t *hp, sbderror_t *ep, 897c478bd9Sstevel@tonic-gate dev_info_t *dip, int unit); 907c478bd9Sstevel@tonic-gate static int sbd_detach_mem(sbd_handle_t *hp, sbderror_t *ep, int unit); 917c478bd9Sstevel@tonic-gate static void sbd_cancel(sbd_handle_t *hp); 927c478bd9Sstevel@tonic-gate void sbd_errno_decode(int err, sbderror_t *ep, dev_info_t *dip); 937c478bd9Sstevel@tonic-gate int sbd_dealloc_instance(sbd_board_t *sbp, int max_boards); 947c478bd9Sstevel@tonic-gate int sbd_errno2ecode(int error); 957c478bd9Sstevel@tonic-gate #pragma weak sbdp_cpu_get_impl 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate #ifdef DEBUG 987c478bd9Sstevel@tonic-gate uint_t sbd_debug = (uint_t)0x0; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate #ifdef SBD_DEBUG_ERRS 1017c478bd9Sstevel@tonic-gate /* controls which errors are injected */ 1027c478bd9Sstevel@tonic-gate uint_t sbd_err_debug = (uint_t)0x0; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* controls printing about error injection */ 1057c478bd9Sstevel@tonic-gate uint_t sbd_print_errs = (uint_t)0x0; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate #endif /* SBD_DEBUG_ERRS */ 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate char *sbd_state_str[] = { 1127c478bd9Sstevel@tonic-gate "EMPTY", "OCCUPIED", "CONNECTED", "UNCONFIGURED", 1137c478bd9Sstevel@tonic-gate "PARTIAL", "CONFIGURED", "RELEASE", "UNREFERENCED", 1147c478bd9Sstevel@tonic-gate "FATAL" 1157c478bd9Sstevel@tonic-gate }; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* Note: this must be changed in tandem with sbd_ioctl.h */ 1187c478bd9Sstevel@tonic-gate char *sbd_ct_str[] = { 1197c478bd9Sstevel@tonic-gate "NONE", "CPU", "MEM", "IO", "UNKNOWN" 1207c478bd9Sstevel@tonic-gate }; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* Note: this must also be changed in tandem with sbd_ioctl.h */ 1237c478bd9Sstevel@tonic-gate #define SBD_CMD_STR(c) \ 1247c478bd9Sstevel@tonic-gate (((c) == SBD_CMD_ASSIGN) ? "ASSIGN" : \ 1257c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_UNASSIGN) ? "UNASSIGN" : \ 1267c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_POWERON) ? "POWERON" : \ 1277c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_POWEROFF) ? "POWEROFF" : \ 1287c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_TEST) ? "TEST" : \ 1297c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_CONNECT) ? "CONNECT" : \ 1307c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_CONFIGURE) ? "CONFIGURE" : \ 1317c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_UNCONFIGURE) ? "UNCONFIGURE" : \ 1327c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_DISCONNECT) ? "DISCONNECT" : \ 1337c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_STATUS) ? "STATUS" : \ 1347c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_GETNCM) ? "GETNCM" : \ 1357c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_PASSTHRU) ? "PASSTHRU" : "unknown") 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * Defines and structures for device tree naming and mapping 1397c478bd9Sstevel@tonic-gate * to node types 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate sbd_devattr_t *sbd_devattr; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* defines to access the attribute struct */ 1457c478bd9Sstevel@tonic-gate #define SBD_DEVNAME(i) sbd_devattr[i].s_devname 1467c478bd9Sstevel@tonic-gate #define SBD_OTYPE(i) sbd_devattr[(i)].s_obp_type 1477c478bd9Sstevel@tonic-gate #define SBD_COMP(i) sbd_devattr[i].s_dnodetype 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * State transition table. States valid transitions for "board" state. 1517c478bd9Sstevel@tonic-gate * Recall that non-zero return value terminates operation, however 1527c478bd9Sstevel@tonic-gate * the herrno value is what really indicates an error , if any. 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate static int 1557c478bd9Sstevel@tonic-gate _cmd2index(int c) 1567c478bd9Sstevel@tonic-gate { 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Translate DR CMD to index into sbd_state_transition. 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate switch (c) { 1617c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: return (0); 1627c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: return (1); 1637c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: return (2); 1647c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: return (3); 1657c478bd9Sstevel@tonic-gate case SBD_CMD_POWEROFF: return (4); 1667c478bd9Sstevel@tonic-gate case SBD_CMD_POWERON: return (5); 1677c478bd9Sstevel@tonic-gate case SBD_CMD_UNASSIGN: return (6); 1687c478bd9Sstevel@tonic-gate case SBD_CMD_ASSIGN: return (7); 1697c478bd9Sstevel@tonic-gate case SBD_CMD_TEST: return (8); 1707c478bd9Sstevel@tonic-gate default: return (-1); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate #define CMD2INDEX(c) _cmd2index(c) 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate static struct sbd_state_trans { 1777c478bd9Sstevel@tonic-gate int x_cmd; 1787c478bd9Sstevel@tonic-gate struct { 1797c478bd9Sstevel@tonic-gate int x_rv; /* return value of pre_op */ 1807c478bd9Sstevel@tonic-gate int x_err; /* errno, if any */ 1817c478bd9Sstevel@tonic-gate } x_op[SBD_NUM_STATES]; 1827c478bd9Sstevel@tonic-gate } sbd_state_transition[] = { 1837c478bd9Sstevel@tonic-gate { SBD_CMD_CONNECT, 1847c478bd9Sstevel@tonic-gate { 1857c478bd9Sstevel@tonic-gate { 0, 0 }, /* empty */ 1867c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 1877c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 1887c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 1897c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 1907c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 1917c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 1927c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 1937c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate }, 1967c478bd9Sstevel@tonic-gate { SBD_CMD_DISCONNECT, 1977c478bd9Sstevel@tonic-gate { 1987c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 1997c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 2007c478bd9Sstevel@tonic-gate { 0, 0 }, /* connected */ 2017c478bd9Sstevel@tonic-gate { 0, 0 }, /* unconfigured */ 2027c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 2037c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 2047c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 2057c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 2067c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate }, 2097c478bd9Sstevel@tonic-gate { SBD_CMD_CONFIGURE, 2107c478bd9Sstevel@tonic-gate { 2117c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 2127c478bd9Sstevel@tonic-gate { 1, EIO }, /* occupied */ 2137c478bd9Sstevel@tonic-gate { 0, 0 }, /* connected */ 2147c478bd9Sstevel@tonic-gate { 0, 0 }, /* unconfigured */ 2157c478bd9Sstevel@tonic-gate { 0, 0 }, /* partial */ 2167c478bd9Sstevel@tonic-gate { 1, 0 }, /* configured */ 2177c478bd9Sstevel@tonic-gate { 0, 0 }, /* release */ 2187c478bd9Sstevel@tonic-gate { 0, 0 }, /* unreferenced */ 2197c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate }, 2227c478bd9Sstevel@tonic-gate { SBD_CMD_UNCONFIGURE, 2237c478bd9Sstevel@tonic-gate { 2247c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 2257c478bd9Sstevel@tonic-gate { 1, EIO }, /* occupied */ 2267c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 2277c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 2287c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 2297c478bd9Sstevel@tonic-gate { 0, 0 }, /* configured */ 2307c478bd9Sstevel@tonic-gate { 0, 0 }, /* release */ 2317c478bd9Sstevel@tonic-gate { 0, 0 }, /* unreferenced */ 2327c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate }, 2357c478bd9Sstevel@tonic-gate { SBD_CMD_POWEROFF, 2367c478bd9Sstevel@tonic-gate { 2377c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 2387c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 2397c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 2407c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 2417c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 2427c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 2437c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 2447c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 2457c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate }, 2487c478bd9Sstevel@tonic-gate { SBD_CMD_POWERON, 2497c478bd9Sstevel@tonic-gate { 2507c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 2517c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 2527c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 2537c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 2547c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 2557c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 2567c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 2577c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 2587c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate }, 2617c478bd9Sstevel@tonic-gate { SBD_CMD_UNASSIGN, 2627c478bd9Sstevel@tonic-gate { 2637c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 2647c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 2657c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 2667c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 2677c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 2687c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 2697c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 2707c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 2717c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate }, 2747c478bd9Sstevel@tonic-gate { SBD_CMD_ASSIGN, 2757c478bd9Sstevel@tonic-gate { 2767c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 2777c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 2787c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 2797c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 2807c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 2817c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 2827c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 2837c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 2847c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate }, 2877c478bd9Sstevel@tonic-gate { SBD_CMD_TEST, 2887c478bd9Sstevel@tonic-gate { 2897c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 2907c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 2917c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 2927c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 2937c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 2947c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 2957c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 2967c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 2977c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate }, 3007c478bd9Sstevel@tonic-gate }; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * Global R/W lock to synchronize access across 3047c478bd9Sstevel@tonic-gate * multiple boards. Users wanting multi-board access 3057c478bd9Sstevel@tonic-gate * must grab WRITE lock, others must grab READ lock. 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate krwlock_t sbd_grwlock; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * Global to determine if an event needs to be sent 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate char send_event = 0; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * Required/Expected functions. 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate static sbd_handle_t *sbd_get_handle(dev_t dev, sbd_softstate_t *softsp, 3197c478bd9Sstevel@tonic-gate intptr_t arg, sbd_init_arg_t *iap); 3207c478bd9Sstevel@tonic-gate static void sbd_release_handle(sbd_handle_t *hp); 3217c478bd9Sstevel@tonic-gate static int sbd_pre_op(sbd_handle_t *hp); 3227c478bd9Sstevel@tonic-gate static void sbd_post_op(sbd_handle_t *hp); 3237c478bd9Sstevel@tonic-gate static int sbd_probe_board(sbd_handle_t *hp); 3247c478bd9Sstevel@tonic-gate static int sbd_deprobe_board(sbd_handle_t *hp); 3257c478bd9Sstevel@tonic-gate static void sbd_connect(sbd_handle_t *hp); 3267c478bd9Sstevel@tonic-gate static void sbd_assign_board(sbd_handle_t *hp); 3277c478bd9Sstevel@tonic-gate static void sbd_unassign_board(sbd_handle_t *hp); 3287c478bd9Sstevel@tonic-gate static void sbd_poweron_board(sbd_handle_t *hp); 3297c478bd9Sstevel@tonic-gate static void sbd_poweroff_board(sbd_handle_t *hp); 3307c478bd9Sstevel@tonic-gate static void sbd_test_board(sbd_handle_t *hp); 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate static int sbd_disconnect(sbd_handle_t *hp); 3337c478bd9Sstevel@tonic-gate static sbd_devlist_t *sbd_get_attach_devlist(sbd_handle_t *hp, 3347c478bd9Sstevel@tonic-gate int32_t *devnump, int32_t pass); 3357c478bd9Sstevel@tonic-gate static int sbd_pre_attach_devlist(sbd_handle_t *hp, 3367c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 3377c478bd9Sstevel@tonic-gate static int sbd_post_attach_devlist(sbd_handle_t *hp, 3387c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 3397c478bd9Sstevel@tonic-gate static sbd_devlist_t *sbd_get_release_devlist(sbd_handle_t *hp, 3407c478bd9Sstevel@tonic-gate int32_t *devnump, int32_t pass); 3417c478bd9Sstevel@tonic-gate static int sbd_pre_release_devlist(sbd_handle_t *hp, 3427c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 3437c478bd9Sstevel@tonic-gate static int sbd_post_release_devlist(sbd_handle_t *hp, 3447c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 3457c478bd9Sstevel@tonic-gate static void sbd_release_done(sbd_handle_t *hp, 3467c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype, 3477c478bd9Sstevel@tonic-gate dev_info_t *dip); 3487c478bd9Sstevel@tonic-gate static sbd_devlist_t *sbd_get_detach_devlist(sbd_handle_t *hp, 3497c478bd9Sstevel@tonic-gate int32_t *devnump, int32_t pass); 3507c478bd9Sstevel@tonic-gate static int sbd_pre_detach_devlist(sbd_handle_t *hp, 3517c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 3527c478bd9Sstevel@tonic-gate static int sbd_post_detach_devlist(sbd_handle_t *hp, 3537c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 3547c478bd9Sstevel@tonic-gate static void sbd_status(sbd_handle_t *hp); 3557c478bd9Sstevel@tonic-gate static void sbd_get_ncm(sbd_handle_t *hp); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate /* 3597c478bd9Sstevel@tonic-gate * Support functions. 3607c478bd9Sstevel@tonic-gate */ 3617c478bd9Sstevel@tonic-gate static sbd_devset_t sbd_dev2devset(sbd_comp_id_t *cid); 3627c478bd9Sstevel@tonic-gate static int sbd_copyin_ioarg(sbd_handle_t *hp, int mode, int cmd, 3637c478bd9Sstevel@tonic-gate sbd_cmd_t *cmdp, sbd_ioctl_arg_t *iap); 3647c478bd9Sstevel@tonic-gate static int sbd_copyout_errs(int mode, sbd_ioctl_arg_t *iap, 3657c478bd9Sstevel@tonic-gate void *arg); 3667c478bd9Sstevel@tonic-gate static int sbd_copyout_ioarg(int mode, int cmd, sbd_cmd_t *scp, 3677c478bd9Sstevel@tonic-gate sbd_ioctl_arg_t *iap); 3687c478bd9Sstevel@tonic-gate static int sbd_check_transition(sbd_board_t *sbp, 3697c478bd9Sstevel@tonic-gate sbd_devset_t *devsetp, 3707c478bd9Sstevel@tonic-gate struct sbd_state_trans *transp); 3717c478bd9Sstevel@tonic-gate static sbd_devlist_t *sbd_get_devlist(sbd_handle_t *hp, 3727c478bd9Sstevel@tonic-gate sbd_board_t *sbp, 3737c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype, 3747c478bd9Sstevel@tonic-gate int max_units, uint_t uset, 3757c478bd9Sstevel@tonic-gate int *count, int present_only); 3767c478bd9Sstevel@tonic-gate static int sbd_mem_status(sbd_handle_t *hp, sbd_devset_t devset, 3777c478bd9Sstevel@tonic-gate sbd_dev_stat_t *dsp); 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate static int sbd_init_devlists(sbd_board_t *sbp); 3807c478bd9Sstevel@tonic-gate static int sbd_name_to_idx(char *name); 3817c478bd9Sstevel@tonic-gate static int sbd_otype_to_idx(char *otpye); 3827c478bd9Sstevel@tonic-gate static int sbd_setup_devlists(dev_info_t *dip, void *arg); 3837c478bd9Sstevel@tonic-gate static void sbd_init_mem_devlists(sbd_board_t *sbp); 3847c478bd9Sstevel@tonic-gate static void sbd_init_cpu_unit(sbd_board_t *sbp, int unit); 3857c478bd9Sstevel@tonic-gate static void sbd_board_discovery(sbd_board_t *sbp); 3867c478bd9Sstevel@tonic-gate static void sbd_board_init(sbd_board_t *sbp, 3877c478bd9Sstevel@tonic-gate sbd_softstate_t *softsp, 3887c478bd9Sstevel@tonic-gate int bd, dev_info_t *dip, int wnode); 3897c478bd9Sstevel@tonic-gate static void sbd_board_destroy(sbd_board_t *sbp); 3907c478bd9Sstevel@tonic-gate static int sbd_check_unit_attached(sbd_board_t *sbp, 3917c478bd9Sstevel@tonic-gate dev_info_t *dip, int unit, 3927c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype, sbderror_t *ep); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate static sbd_state_t rstate_cvt(sbd_istate_t state); 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate /* 3977c478bd9Sstevel@tonic-gate * Autoconfiguration data structures 3987c478bd9Sstevel@tonic-gate */ 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate extern struct mod_ops mod_miscops; 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 4037c478bd9Sstevel@tonic-gate &mod_miscops, 404903a11ebSrh87107 "System Board DR" 4057c478bd9Sstevel@tonic-gate }; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 4087c478bd9Sstevel@tonic-gate MODREV_1, 4097c478bd9Sstevel@tonic-gate (void *)&modlmisc, 4107c478bd9Sstevel@tonic-gate NULL 4117c478bd9Sstevel@tonic-gate }; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate static int sbd_instances = 0; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * dr Global data elements 4177c478bd9Sstevel@tonic-gate */ 4187c478bd9Sstevel@tonic-gate sbd_global sbd_g; 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * We want to be able to unload the module when we wish to do so, but we don't 4227c478bd9Sstevel@tonic-gate * want anything else to unload it. Unloading cannot occur until 4237c478bd9Sstevel@tonic-gate * sbd_teardown_instance is called by an explicit IOCTL into the parent node. 4247c478bd9Sstevel@tonic-gate * This support is for debugging purposes and should it be expected to work 4257c478bd9Sstevel@tonic-gate * on the field, it should be enhanced: 4267c478bd9Sstevel@tonic-gate * Currently, there is still a window where sbd_teardow_instance gets called, 4277c478bd9Sstevel@tonic-gate * sbd_prevent_unloading now = 0, the driver doesn't get unloaded, and 4287c478bd9Sstevel@tonic-gate * sbd_setup_instance gets called. This may cause a panic. 4297c478bd9Sstevel@tonic-gate */ 4307c478bd9Sstevel@tonic-gate int sbd_prevent_unloading = 1; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * Driver entry points. 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate int 4367c478bd9Sstevel@tonic-gate _init(void) 4377c478bd9Sstevel@tonic-gate { 4387c478bd9Sstevel@tonic-gate int err; 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate /* 4417c478bd9Sstevel@tonic-gate * If you need to support multiple nodes (instances), then 4427c478bd9Sstevel@tonic-gate * whatever the maximum number of supported nodes is would 4437c478bd9Sstevel@tonic-gate * need to passed as the third parameter to ddi_soft_state_init(). 4447c478bd9Sstevel@tonic-gate * Alternative would be to dynamically fini and re-init the 4457c478bd9Sstevel@tonic-gate * soft state structure each time a node is attached. 4467c478bd9Sstevel@tonic-gate */ 4477c478bd9Sstevel@tonic-gate err = ddi_soft_state_init((void **)&sbd_g.softsp, 4487c478bd9Sstevel@tonic-gate sizeof (sbd_softstate_t), SBD_MAX_INSTANCES); 4497c478bd9Sstevel@tonic-gate if (err) 4507c478bd9Sstevel@tonic-gate return (err); 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if ((err = mod_install(&modlinkage)) != 0) { 4537c478bd9Sstevel@tonic-gate ddi_soft_state_fini((void **)&sbd_g.softsp); 4547c478bd9Sstevel@tonic-gate return (err); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate /* Get the array of names from platform helper routine */ 4587c478bd9Sstevel@tonic-gate sbd_devattr = sbdp_get_devattr(); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate return (err); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate int 4647c478bd9Sstevel@tonic-gate _fini(void) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate int err; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate if (sbd_prevent_unloading) 4697c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate ASSERT(sbd_instances == 0); 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate if ((err = mod_remove(&modlinkage)) != 0) 4747c478bd9Sstevel@tonic-gate return (err); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate ddi_soft_state_fini((void **)&sbd_g.softsp); 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate return (0); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate int 4827c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 4837c478bd9Sstevel@tonic-gate { 4847c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate int 4887c478bd9Sstevel@tonic-gate sbd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, char *event) 4897c478bd9Sstevel@tonic-gate { 4907c478bd9Sstevel@tonic-gate int rv = 0, instance; 4917c478bd9Sstevel@tonic-gate sbd_handle_t *hp; 4927c478bd9Sstevel@tonic-gate sbd_softstate_t *softsp; 4937c478bd9Sstevel@tonic-gate sbd_init_arg_t init_arg; 4947c478bd9Sstevel@tonic-gate static fn_t f = "sbd_ioctl"; 4957c478bd9Sstevel@tonic-gate int dr_avail; 4967c478bd9Sstevel@tonic-gate 49704580fdfSmathue PR_BYP("sbd_ioctl cmd=%x, arg=%lx\n", cmd, arg); 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* Note: this must also be changed in tandem with sbd_ioctl.h */ 5007c478bd9Sstevel@tonic-gate switch (cmd) { 5017c478bd9Sstevel@tonic-gate case SBD_CMD_ASSIGN: 5027c478bd9Sstevel@tonic-gate case SBD_CMD_UNASSIGN: 5037c478bd9Sstevel@tonic-gate case SBD_CMD_POWERON: 5047c478bd9Sstevel@tonic-gate case SBD_CMD_POWEROFF: 5057c478bd9Sstevel@tonic-gate case SBD_CMD_TEST: 5067c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: 5077c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: 5087c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: 5097c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: 5107c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 5117c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 5127c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 5137c478bd9Sstevel@tonic-gate break; 5147c478bd9Sstevel@tonic-gate default: 5157c478bd9Sstevel@tonic-gate return (ENOTTY); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate instance = SBD_GET_MINOR2INST(getminor(dev)); 5197c478bd9Sstevel@tonic-gate if ((softsp = (sbd_softstate_t *)GET_SOFTC(instance)) == NULL) { 5207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 5217c478bd9Sstevel@tonic-gate "sbd:%s:%d: module not yet attached", 5227c478bd9Sstevel@tonic-gate f, instance); 5237c478bd9Sstevel@tonic-gate return (ENXIO); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate init_arg.dev = dev; 5277c478bd9Sstevel@tonic-gate init_arg.cmd = cmd; 5287c478bd9Sstevel@tonic-gate init_arg.mode = mode; 5297c478bd9Sstevel@tonic-gate init_arg.ioargp = (sbd_ioctl_arg_t *)arg; 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate hp = sbd_get_handle(dev, softsp, arg, &init_arg); 5327c478bd9Sstevel@tonic-gate /* Check to see if we support dr */ 5337c478bd9Sstevel@tonic-gate dr_avail = sbdp_dr_avail(); 5347c478bd9Sstevel@tonic-gate if (dr_avail != 1) { 5357c478bd9Sstevel@tonic-gate switch (hp->h_cmd) { 5367c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 5377c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 5387c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 5397c478bd9Sstevel@tonic-gate break; 5407c478bd9Sstevel@tonic-gate default: 5417c478bd9Sstevel@tonic-gate sbd_release_handle(hp); 5427c478bd9Sstevel@tonic-gate return (ENOTSUP); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate switch (hp->h_cmd) { 5477c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 5487c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 5497c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 5507c478bd9Sstevel@tonic-gate /* no locks needed for these commands */ 5517c478bd9Sstevel@tonic-gate break; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate default: 5547c478bd9Sstevel@tonic-gate rw_enter(&sbd_grwlock, RW_WRITER); 5557c478bd9Sstevel@tonic-gate mutex_enter(&SBDH2BD(hp->h_sbd)->sb_mutex); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate /* 5587c478bd9Sstevel@tonic-gate * If we're dealing with memory at all, then we have 5597c478bd9Sstevel@tonic-gate * to keep the "exclusive" global lock held. This is 5607c478bd9Sstevel@tonic-gate * necessary since we will probably need to look at 5617c478bd9Sstevel@tonic-gate * multiple board structs. Otherwise, we only have 5627c478bd9Sstevel@tonic-gate * to deal with the board in question and so can drop 5637c478bd9Sstevel@tonic-gate * the global lock to "shared". 5647c478bd9Sstevel@tonic-gate */ 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * XXX This is incorrect. The sh_devset has not 5677c478bd9Sstevel@tonic-gate * been set at this point - it is 0. 5687c478bd9Sstevel@tonic-gate */ 5697c478bd9Sstevel@tonic-gate rv = DEVSET_IN_SET(HD2MACHHD(hp)->sh_devset, 5707c478bd9Sstevel@tonic-gate SBD_COMP_MEM, DEVSET_ANYUNIT); 5717c478bd9Sstevel@tonic-gate if (rv == 0) 5727c478bd9Sstevel@tonic-gate rw_downgrade(&sbd_grwlock); 5737c478bd9Sstevel@tonic-gate break; 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate /* 5777c478bd9Sstevel@tonic-gate * Before any operations happen, reset the event flag 5787c478bd9Sstevel@tonic-gate */ 5797c478bd9Sstevel@tonic-gate send_event = 0; 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate if (sbd_pre_op(hp) == 0) { 5827c478bd9Sstevel@tonic-gate sbd_exec_op(hp); 5837c478bd9Sstevel@tonic-gate sbd_post_op(hp); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate rv = SBD_GET_ERRNO(SBD_HD2ERR(hp)); 5877c478bd9Sstevel@tonic-gate *event = send_event; 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate /* undo locking, if any, done before sbd_pre_op */ 5907c478bd9Sstevel@tonic-gate switch (hp->h_cmd) { 5917c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 5927c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 5937c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 5947c478bd9Sstevel@tonic-gate break; 5957c478bd9Sstevel@tonic-gate default: 5967c478bd9Sstevel@tonic-gate mutex_exit(&SBDH2BD(hp->h_sbd)->sb_mutex); 5977c478bd9Sstevel@tonic-gate rw_exit(&sbd_grwlock); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate sbd_release_handle(hp); 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate return (rv); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate int 6067c478bd9Sstevel@tonic-gate sbd_setup_instance(int instance, dev_info_t *root, int max_boards, int wnode, 6077c478bd9Sstevel@tonic-gate caddr_t sbdp_arg) 6087c478bd9Sstevel@tonic-gate { 6097c478bd9Sstevel@tonic-gate int b; 6107c478bd9Sstevel@tonic-gate sbd_softstate_t *softsp; 6117c478bd9Sstevel@tonic-gate sbd_board_t *sbd_boardlist; 6127c478bd9Sstevel@tonic-gate static fn_t f = "sbd_setup_instance"; 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate sbd_instances++; 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate if (sbdp_setup_instance(sbdp_arg) != DDI_SUCCESS) { 6177c478bd9Sstevel@tonic-gate sbd_instances--; 6187c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate if (ALLOC_SOFTC(instance) != DDI_SUCCESS) { 6227c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 6237c478bd9Sstevel@tonic-gate "sbd:%s:%d: failed to alloc soft-state", 6247c478bd9Sstevel@tonic-gate f, instance); 62507d06da5SSurya Prakki (void) sbdp_teardown_instance(sbdp_arg); 6267c478bd9Sstevel@tonic-gate sbd_instances--; 6277c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate softsp = (sbd_softstate_t *)GET_SOFTC(instance); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate if (softsp == NULL) { 6337c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 6347c478bd9Sstevel@tonic-gate "sbd:%s:%d: failed to get soft-state instance", 6357c478bd9Sstevel@tonic-gate f, instance); 6367c478bd9Sstevel@tonic-gate goto exit; 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate sbd_boardlist = GETSTRUCT(sbd_board_t, max_boards); 6407c478bd9Sstevel@tonic-gate if (sbd_boardlist == NULL) { 6417c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 6427c478bd9Sstevel@tonic-gate "sbd:%s: failed to alloc board list %d", 6437c478bd9Sstevel@tonic-gate f, instance); 6447c478bd9Sstevel@tonic-gate goto exit; 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate softsp->sbd_boardlist = (void *)sbd_boardlist; 6497c478bd9Sstevel@tonic-gate softsp->max_boards = max_boards; 6507c478bd9Sstevel@tonic-gate softsp->wnode = wnode; 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate for (b = 0; b < max_boards; b++) { 6547c478bd9Sstevel@tonic-gate sbd_board_init(sbd_boardlist++, softsp, b, root, wnode); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 6597c478bd9Sstevel@tonic-gate exit: 6607c478bd9Sstevel@tonic-gate (void) sbdp_teardown_instance(sbdp_arg); 6617c478bd9Sstevel@tonic-gate FREE_SOFTC(instance); 6627c478bd9Sstevel@tonic-gate sbd_instances--; 6637c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate int 6677c478bd9Sstevel@tonic-gate sbd_teardown_instance(int instance, caddr_t sbdp_arg) 6687c478bd9Sstevel@tonic-gate { 6697c478bd9Sstevel@tonic-gate sbd_softstate_t *softsp; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (sbdp_teardown_instance(sbdp_arg) != DDI_SUCCESS) 6727c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate softsp = (sbd_softstate_t *)GET_SOFTC(instance); 6757c478bd9Sstevel@tonic-gate if (softsp == NULL) { 6767c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate (void) sbd_dealloc_instance((sbd_board_t *)softsp->sbd_boardlist, 6807c478bd9Sstevel@tonic-gate softsp->max_boards); 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate FREE_SOFTC(instance); 6837c478bd9Sstevel@tonic-gate sbd_instances--; 6847c478bd9Sstevel@tonic-gate sbd_prevent_unloading = 0; 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate static void 6907c478bd9Sstevel@tonic-gate sbd_exec_op(sbd_handle_t *hp) 6917c478bd9Sstevel@tonic-gate { 6927c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 6937c478bd9Sstevel@tonic-gate static fn_t f = "sbd_exec_op"; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate switch (hp->h_cmd) { 6967c478bd9Sstevel@tonic-gate int dev_canceled; 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: 6997c478bd9Sstevel@tonic-gate if (sbd_probe_board(hp)) 7007c478bd9Sstevel@tonic-gate break; 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate sbd_connect(hp); 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: 7067c478bd9Sstevel@tonic-gate sbd_dev_configure(hp); 7077c478bd9Sstevel@tonic-gate break; 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: 7107c478bd9Sstevel@tonic-gate if (((dev_canceled = sbd_dev_release(hp)) == 0) && 7117c478bd9Sstevel@tonic-gate (SBD_GET_ERRNO(SBD_HD2ERR(hp)) == 0 && 7127c478bd9Sstevel@tonic-gate SBD_GET_ERR(SBD_HD2ERR(hp)) == 0)) 7137c478bd9Sstevel@tonic-gate dev_canceled = sbd_dev_unconfigure(hp); 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate if (dev_canceled) 7167c478bd9Sstevel@tonic-gate sbd_cancel(hp); 7177c478bd9Sstevel@tonic-gate break; 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: 7207c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 7217c478bd9Sstevel@tonic-gate if (sbd_disconnect(hp) == 0) 7227c478bd9Sstevel@tonic-gate (void) sbd_deprobe_board(hp); 7237c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 7247c478bd9Sstevel@tonic-gate break; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 7277c478bd9Sstevel@tonic-gate sbd_status(hp); 7287c478bd9Sstevel@tonic-gate break; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 7317c478bd9Sstevel@tonic-gate sbd_get_ncm(hp); 7327c478bd9Sstevel@tonic-gate break; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate case SBD_CMD_ASSIGN: 7357c478bd9Sstevel@tonic-gate sbd_assign_board(hp); 7367c478bd9Sstevel@tonic-gate break; 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate case SBD_CMD_UNASSIGN: 7397c478bd9Sstevel@tonic-gate sbd_unassign_board(hp); 7407c478bd9Sstevel@tonic-gate break; 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate case SBD_CMD_POWEROFF: 7437c478bd9Sstevel@tonic-gate sbd_poweroff_board(hp); 7447c478bd9Sstevel@tonic-gate break; 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate case SBD_CMD_POWERON: 7477c478bd9Sstevel@tonic-gate sbd_poweron_board(hp); 7487c478bd9Sstevel@tonic-gate break; 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate case SBD_CMD_TEST: 7517c478bd9Sstevel@tonic-gate sbd_test_board(hp); 7527c478bd9Sstevel@tonic-gate break; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 7557c478bd9Sstevel@tonic-gate { 7567c478bd9Sstevel@tonic-gate int rv; 7577c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 7587c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 7597c478bd9Sstevel@tonic-gate sbdp_ioctl_arg_t ia, *iap; 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate iap = &ia; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate iap->h_dev = hp->h_dev; 7647c478bd9Sstevel@tonic-gate iap->h_cmd = hp->h_cmd; 7657c478bd9Sstevel@tonic-gate iap->h_iap = (intptr_t)hp->h_iap; 7667c478bd9Sstevel@tonic-gate iap->h_mode = hp->h_mode; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 7697c478bd9Sstevel@tonic-gate rv = sbdp_ioctl(hdp, iap); 7707c478bd9Sstevel@tonic-gate if (rv != 0) { 7717c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 7727c478bd9Sstevel@tonic-gate ep->e_errno = rv; 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 7757c478bd9Sstevel@tonic-gate break; 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate default: 7797c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), ENOTTY); 7807c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 7817c478bd9Sstevel@tonic-gate "sbd:%s: unknown command (%d)", 7827c478bd9Sstevel@tonic-gate f, hp->h_cmd); 7837c478bd9Sstevel@tonic-gate break; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(SBD_HD2ERR(hp))) 7887c478bd9Sstevel@tonic-gate PR_BYP("XXX e_code=%d", SBD_GET_ERR(SBD_HD2ERR(hp))); 7897c478bd9Sstevel@tonic-gate if (SBD_GET_ERRNO(SBD_HD2ERR(hp))) 7907c478bd9Sstevel@tonic-gate PR_BYP("XXX errno=%d", SBD_GET_ERRNO(SBD_HD2ERR(hp))); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate sbd_comp_type_t 7947c478bd9Sstevel@tonic-gate sbd_get_devtype(sbd_handle_t *hp, dev_info_t *dip) 7957c478bd9Sstevel@tonic-gate { 7967c478bd9Sstevel@tonic-gate sbd_board_t *sbp = hp ? SBDH2BD(hp->h_sbd) : NULL; 7977c478bd9Sstevel@tonic-gate sbd_istate_t bstate; 7987c478bd9Sstevel@tonic-gate dev_info_t **devlist; 7997c478bd9Sstevel@tonic-gate int i; 8007c478bd9Sstevel@tonic-gate char device[OBP_MAXDRVNAME]; 8017c478bd9Sstevel@tonic-gate int devicelen; 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate devicelen = sizeof (device); 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate bstate = sbp ? SBD_BOARD_STATE(sbp) : SBD_STATE_EMPTY; 8067c478bd9Sstevel@tonic-gate /* 8077c478bd9Sstevel@tonic-gate * if the board's connected or configured, search the 8087c478bd9Sstevel@tonic-gate * devlists. Otherwise check the device tree 8097c478bd9Sstevel@tonic-gate */ 8107c478bd9Sstevel@tonic-gate switch (bstate) { 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 8137c478bd9Sstevel@tonic-gate case SBD_STATE_CONFIGURED: 8147c478bd9Sstevel@tonic-gate case SBD_STATE_UNREFERENCED: 8157c478bd9Sstevel@tonic-gate case SBD_STATE_UNCONFIGURED: 8167c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(SBD_COMP_MEM)]; 8177c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) 8187c478bd9Sstevel@tonic-gate if (devlist[i] == dip) 8197c478bd9Sstevel@tonic-gate return (SBD_COMP_MEM); 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(SBD_COMP_CPU)]; 8227c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) 8237c478bd9Sstevel@tonic-gate if (devlist[i] == dip) 8247c478bd9Sstevel@tonic-gate return (SBD_COMP_CPU); 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(SBD_COMP_IO)]; 8277c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) 8287c478bd9Sstevel@tonic-gate if (devlist[i] == dip) 8297c478bd9Sstevel@tonic-gate return (SBD_COMP_IO); 8307c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate default: 8337c478bd9Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 8347c478bd9Sstevel@tonic-gate OBP_DEVICETYPE, (caddr_t)device, &devicelen)) 8357c478bd9Sstevel@tonic-gate break; 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate for (i = 0; SBD_COMP(i) != SBD_COMP_UNKNOWN; i++) { 8387c478bd9Sstevel@tonic-gate if (strcmp(device, SBD_OTYPE(i)) != 0) 8397c478bd9Sstevel@tonic-gate continue; 8407c478bd9Sstevel@tonic-gate return (SBD_COMP(i)); 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate break; 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate static void 8497c478bd9Sstevel@tonic-gate sbd_dev_configure(sbd_handle_t *hp) 8507c478bd9Sstevel@tonic-gate { 8517c478bd9Sstevel@tonic-gate int n, unit; 8527c478bd9Sstevel@tonic-gate int32_t pass, devnum; 8537c478bd9Sstevel@tonic-gate dev_info_t *dip; 8547c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist; 8557c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 8567c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 8577c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate pass = 1; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 8627c478bd9Sstevel@tonic-gate while ((devlist = sbd_get_attach_devlist(hp, &devnum, pass)) != NULL) { 8637c478bd9Sstevel@tonic-gate int err; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate err = sbd_pre_attach_devlist(hp, devlist, devnum); 8667c478bd9Sstevel@tonic-gate if (err < 0) { 8677c478bd9Sstevel@tonic-gate break; 8687c478bd9Sstevel@tonic-gate } else if (err > 0) { 8697c478bd9Sstevel@tonic-gate pass++; 8707c478bd9Sstevel@tonic-gate continue; 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate for (n = 0; n < devnum; n++) { 8747c478bd9Sstevel@tonic-gate sbderror_t *ep; 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate ep = &devlist[n].dv_error; 8777c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, 0); 8787c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, 0); 8797c478bd9Sstevel@tonic-gate dip = devlist[n].dv_dip; 8807c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 8837c478bd9Sstevel@tonic-gate if (unit < 0) { 8847c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 8857c478bd9Sstevel@tonic-gate break; 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate switch (nodetype) { 8897c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 8907c478bd9Sstevel@tonic-gate sbd_attach_mem(hp, ep); 8917c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) == ESBD_CPUONLINE) { 8927c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, 8937c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD); 8947c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 8957c478bd9Sstevel@tonic-gate return; 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate break; 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 9007c478bd9Sstevel@tonic-gate sbd_attach_cpu(hp, ep, dip, unit); 9017c478bd9Sstevel@tonic-gate break; 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 9047c478bd9Sstevel@tonic-gate sbd_attach_io(hp, ep, dip, unit); 9057c478bd9Sstevel@tonic-gate break; 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate default: 9087c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, ENOTTY); 9097c478bd9Sstevel@tonic-gate break; 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) 9137c478bd9Sstevel@tonic-gate continue; 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate err = sbd_post_attach_devlist(hp, devlist, devnum); 9177c478bd9Sstevel@tonic-gate if (err < 0) 9187c478bd9Sstevel@tonic-gate break; 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate pass++; 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate static int 9267c478bd9Sstevel@tonic-gate sbd_dev_release(sbd_handle_t *hp) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate int n, unit; 9297c478bd9Sstevel@tonic-gate int32_t pass, devnum; 9307c478bd9Sstevel@tonic-gate dev_info_t *dip; 9317c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 9327c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 9337c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist; 9347c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 9357c478bd9Sstevel@tonic-gate int err = 0; 9367c478bd9Sstevel@tonic-gate int dev_canceled; 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate pass = 1; 9397c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate sbp->sb_busy = 1; 9427c478bd9Sstevel@tonic-gate while ((devlist = 9437c478bd9Sstevel@tonic-gate sbd_get_release_devlist(hp, &devnum, pass)) != NULL) { 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate err = sbd_pre_release_devlist(hp, devlist, devnum); 9467c478bd9Sstevel@tonic-gate if (err < 0) { 9477c478bd9Sstevel@tonic-gate dev_canceled = 1; 9487c478bd9Sstevel@tonic-gate break; 9497c478bd9Sstevel@tonic-gate } else if (err > 0) { 9507c478bd9Sstevel@tonic-gate pass++; 9517c478bd9Sstevel@tonic-gate continue; 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate dev_canceled = 0; 9557c478bd9Sstevel@tonic-gate for (n = 0; n < devnum; n++) { 9567c478bd9Sstevel@tonic-gate dip = devlist[n].dv_dip; 9577c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 9607c478bd9Sstevel@tonic-gate if (unit < 0) { 9617c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 9627c478bd9Sstevel@tonic-gate break; 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate if ((nodetype == SBD_COMP_MEM) && 9667c478bd9Sstevel@tonic-gate sbd_release_mem(hp, dip, unit)) { 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate dev_canceled++; 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate sbd_release_done(hp, nodetype, dip); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate err = sbd_post_release_devlist(hp, devlist, devnum); 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate if (err < 0) 9777c478bd9Sstevel@tonic-gate break; 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate if (dev_canceled) 9807c478bd9Sstevel@tonic-gate break; 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate pass++; 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate sbp->sb_busy = 0; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate if (dev_canceled) 9897c478bd9Sstevel@tonic-gate return (dev_canceled); 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate return (err); 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate static int 9957c478bd9Sstevel@tonic-gate sbd_dev_unconfigure(sbd_handle_t *hp) 9967c478bd9Sstevel@tonic-gate { 9977c478bd9Sstevel@tonic-gate int n, unit; 9987c478bd9Sstevel@tonic-gate int32_t pass, devnum; 9997c478bd9Sstevel@tonic-gate dev_info_t *dip; 10007c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist; 10017c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 10027c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 10037c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 10047c478bd9Sstevel@tonic-gate int dev_canceled = 0; 10057c478bd9Sstevel@tonic-gate static fn_t f = "sbd_dev_unconfigure"; 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate pass = 1; 10107c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate while ((devlist = sbd_get_detach_devlist(hp, &devnum, pass)) != NULL) { 10137c478bd9Sstevel@tonic-gate int err, detach_err = 0; 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate err = sbd_pre_detach_devlist(hp, devlist, devnum); 10167c478bd9Sstevel@tonic-gate if (err) { 10177c478bd9Sstevel@tonic-gate /* 10187c478bd9Sstevel@tonic-gate * Only cancel the operation for memory in 10197c478bd9Sstevel@tonic-gate * case of failure. 10207c478bd9Sstevel@tonic-gate */ 10217c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 10227c478bd9Sstevel@tonic-gate if (nodetype == SBD_COMP_MEM) 10237c478bd9Sstevel@tonic-gate dev_canceled = 1; 10247c478bd9Sstevel@tonic-gate (void) sbd_post_detach_devlist(hp, devlist, devnum); 10257c478bd9Sstevel@tonic-gate break; 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate for (n = 0; n < devnum; n++) { 10297c478bd9Sstevel@tonic-gate sbderror_t *ep; 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate ep = &devlist[n].dv_error; 10327c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, 0); 10337c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, 0); 10347c478bd9Sstevel@tonic-gate dip = devlist[n].dv_dip; 10357c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 10387c478bd9Sstevel@tonic-gate if (unit < 0) { 10397c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 10407c478bd9Sstevel@tonic-gate break; 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate switch (nodetype) { 10447c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 10457c478bd9Sstevel@tonic-gate dev_canceled = sbd_detach_mem(hp, ep, unit); 10467c478bd9Sstevel@tonic-gate break; 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 10497c478bd9Sstevel@tonic-gate sbd_detach_cpu(hp, ep, dip, unit); 10507c478bd9Sstevel@tonic-gate break; 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 10537c478bd9Sstevel@tonic-gate sbd_detach_io(hp, ep, dip, unit); 10547c478bd9Sstevel@tonic-gate break; 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate default: 10577c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, ENOTTY); 10587c478bd9Sstevel@tonic-gate break; 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) { 10627c478bd9Sstevel@tonic-gate detach_err = -1; 10637c478bd9Sstevel@tonic-gate break; 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate err = sbd_post_detach_devlist(hp, devlist, devnum); 10687c478bd9Sstevel@tonic-gate if ((err < 0) || (detach_err < 0)) 10697c478bd9Sstevel@tonic-gate break; 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate pass++; 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 10757c478bd9Sstevel@tonic-gate return (dev_canceled); 10767c478bd9Sstevel@tonic-gate } 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate int 10797c478bd9Sstevel@tonic-gate sbd_errno2ecode(int error) 10807c478bd9Sstevel@tonic-gate { 10817c478bd9Sstevel@tonic-gate int rv; 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate switch (error) { 10847c478bd9Sstevel@tonic-gate case EBUSY: 10857c478bd9Sstevel@tonic-gate rv = ESBD_BUSY; 10867c478bd9Sstevel@tonic-gate break; 10877c478bd9Sstevel@tonic-gate case EINVAL: 10887c478bd9Sstevel@tonic-gate rv = ESBD_INVAL; 10897c478bd9Sstevel@tonic-gate break; 10907c478bd9Sstevel@tonic-gate case EALREADY: 10917c478bd9Sstevel@tonic-gate rv = ESBD_ALREADY; 10927c478bd9Sstevel@tonic-gate break; 10937c478bd9Sstevel@tonic-gate case ENODEV: 10947c478bd9Sstevel@tonic-gate rv = ESBD_NODEV; 10957c478bd9Sstevel@tonic-gate break; 10967c478bd9Sstevel@tonic-gate case ENOMEM: 10977c478bd9Sstevel@tonic-gate rv = ESBD_NOMEM; 10987c478bd9Sstevel@tonic-gate break; 10997c478bd9Sstevel@tonic-gate default: 11007c478bd9Sstevel@tonic-gate rv = ESBD_INVAL; 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate return (rv); 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate static void 11077c478bd9Sstevel@tonic-gate sbd_attach_cpu(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit) 11087c478bd9Sstevel@tonic-gate { 11097c478bd9Sstevel@tonic-gate int rv = 0; 11107c478bd9Sstevel@tonic-gate processorid_t cpuid; 11117c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 11127c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 11137c478bd9Sstevel@tonic-gate static fn_t f = "sbd_attach_cpu"; 11147c478bd9Sstevel@tonic-gate char *pathname; 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate ASSERT(dip); 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate /* 11217c478bd9Sstevel@tonic-gate * With the introduction of CMP devices, the CPU nodes 11227c478bd9Sstevel@tonic-gate * are no longer directly under the top node. Since 11237c478bd9Sstevel@tonic-gate * there is no plan to support CPU attach in the near 11247c478bd9Sstevel@tonic-gate * future, a branch configure operation is not required. 11257c478bd9Sstevel@tonic-gate */ 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 11287c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 11297c478bd9Sstevel@tonic-gate if (cpuid < 0) { 11307c478bd9Sstevel@tonic-gate rv = -1; 11317c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 11327c478bd9Sstevel@tonic-gate } else if ((rv = cpu_configure(cpuid)) != 0) { 11337c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 11347c478bd9Sstevel@tonic-gate "sbd:%s: cpu_configure for cpuid %d failed", 11357c478bd9Sstevel@tonic-gate f, cpuid); 11367c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, sbd_errno2ecode(rv)); 11377c478bd9Sstevel@tonic-gate } 11387c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate if (rv == 0) { 11417c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_cpupath[unit] != NULL); 11427c478bd9Sstevel@tonic-gate pathname = sbp->sb_cpupath[unit]; 11437c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, pathname); 11447c478bd9Sstevel@tonic-gate } 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate /* 11487c478bd9Sstevel@tonic-gate * translate errno 11497c478bd9Sstevel@tonic-gate */ 11507c478bd9Sstevel@tonic-gate void 11517c478bd9Sstevel@tonic-gate sbd_errno_decode(int err, sbderror_t *ep, dev_info_t *dip) 11527c478bd9Sstevel@tonic-gate { 11537c478bd9Sstevel@tonic-gate ASSERT(err != 0); 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate switch (err) { 11567c478bd9Sstevel@tonic-gate case ENOMEM: 11577c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NOMEM); 11587c478bd9Sstevel@tonic-gate break; 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate case EBUSY: 11617c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_BUSY); 11627c478bd9Sstevel@tonic-gate break; 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate case EIO: 11657c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_IO); 11667c478bd9Sstevel@tonic-gate break; 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate case ENXIO: 11697c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NODEV); 11707c478bd9Sstevel@tonic-gate break; 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate case EINVAL: 11737c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_INVAL); 11747c478bd9Sstevel@tonic-gate break; 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate case EFAULT: 11777c478bd9Sstevel@tonic-gate default: 11787c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_FAULT); 11797c478bd9Sstevel@tonic-gate break; 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, SBD_GET_ERRSTR(ep)); 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate static void 11867c478bd9Sstevel@tonic-gate sbd_detach_cpu(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit) 11877c478bd9Sstevel@tonic-gate { 11887c478bd9Sstevel@tonic-gate processorid_t cpuid; 11897c478bd9Sstevel@tonic-gate int rv; 11907c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 11917c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 11927c478bd9Sstevel@tonic-gate sbd_error_t *spe; 11937c478bd9Sstevel@tonic-gate static fn_t f = "sbd_detach_cpu"; 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate ASSERT(dip); 11987c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 11997c478bd9Sstevel@tonic-gate spe = hdp->h_err; 12007c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 12017c478bd9Sstevel@tonic-gate if (cpuid < 0) { 12027c478bd9Sstevel@tonic-gate SBD_GET_PERR(spe, ep); 12037c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 12047c478bd9Sstevel@tonic-gate return; 12057c478bd9Sstevel@tonic-gate } 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate if ((rv = cpu_unconfigure(cpuid)) != 0) { 12087c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, sbd_errno2ecode(rv)); 12097c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[unit]); 12107c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 12117c478bd9Sstevel@tonic-gate "sbd:%s: cpu_unconfigure for cpu %d failed", 12127c478bd9Sstevel@tonic-gate f, cpuid); 12137c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 12147c478bd9Sstevel@tonic-gate return; 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate /* 12197c478bd9Sstevel@tonic-gate * Since CPU nodes are no longer configured in CPU 12207c478bd9Sstevel@tonic-gate * attach, the corresponding branch unconfigure 12217c478bd9Sstevel@tonic-gate * operation that would be performed here is also 12227c478bd9Sstevel@tonic-gate * no longer required. 12237c478bd9Sstevel@tonic-gate */ 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate int 12287c478bd9Sstevel@tonic-gate sbd_detach_mem(sbd_handle_t *hp, sbderror_t *ep, int unit) 12297c478bd9Sstevel@tonic-gate { 12307c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 12317c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 12327c478bd9Sstevel@tonic-gate int i, rv; 12337c478bd9Sstevel@tonic-gate static fn_t f = "sbd_detach_mem"; 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, unit); 12367c478bd9Sstevel@tonic-gate 12377c478bd9Sstevel@tonic-gate if (sbd_detach_memory(hp, ep, mp, unit)) { 12387c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: detach fail", f); 12397c478bd9Sstevel@tonic-gate return (-1); 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate /* 12437c478bd9Sstevel@tonic-gate * Now detach mem devinfo nodes with status lock held. 12447c478bd9Sstevel@tonic-gate */ 12457c478bd9Sstevel@tonic-gate for (i = 0; i < SBD_NUM_MC_PER_BOARD; i++) { 12467c478bd9Sstevel@tonic-gate dev_info_t *fdip = NULL; 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate if (mp->sbm_dip[i] == NULL) 12497c478bd9Sstevel@tonic-gate continue; 12507c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(mp->sbm_dip[i])); 12517c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 12527c478bd9Sstevel@tonic-gate rv = e_ddi_branch_unconfigure(mp->sbm_dip[i], &fdip, 12537c478bd9Sstevel@tonic-gate DEVI_BRANCH_EVENT); 12547c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 12557c478bd9Sstevel@tonic-gate if (rv) { 12567c478bd9Sstevel@tonic-gate /* 12577c478bd9Sstevel@tonic-gate * If non-NULL, fdip is returned held and must be 12587c478bd9Sstevel@tonic-gate * released. 12597c478bd9Sstevel@tonic-gate */ 12607c478bd9Sstevel@tonic-gate if (fdip != NULL) { 12617c478bd9Sstevel@tonic-gate sbd_errno_decode(rv, ep, fdip); 12627c478bd9Sstevel@tonic-gate ddi_release_devi(fdip); 12637c478bd9Sstevel@tonic-gate } else { 12647c478bd9Sstevel@tonic-gate sbd_errno_decode(rv, ep, mp->sbm_dip[i]); 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate } 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate return (0); 12707c478bd9Sstevel@tonic-gate } 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate /* start beginning of sbd.c */ 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate /* 12757c478bd9Sstevel@tonic-gate * MDR memory support - somewhat disabled for now. 12767c478bd9Sstevel@tonic-gate * UNSAFE unsafe driver code - I don't think we want this. 12777c478bd9Sstevel@tonic-gate * need to check. 12787c478bd9Sstevel@tonic-gate * DEVNODE This driver creates attachment points for individual 12797c478bd9Sstevel@tonic-gate * components as well as boards. We only need board 12807c478bd9Sstevel@tonic-gate * support. 12817c478bd9Sstevel@tonic-gate * DEV2DEVSET Put only present devices in devset. 12827c478bd9Sstevel@tonic-gate */ 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate static sbd_state_t 12867c478bd9Sstevel@tonic-gate rstate_cvt(sbd_istate_t state) 12877c478bd9Sstevel@tonic-gate { 12887c478bd9Sstevel@tonic-gate sbd_state_t cs; 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate switch (state) { 12917c478bd9Sstevel@tonic-gate case SBD_STATE_EMPTY: 12927c478bd9Sstevel@tonic-gate cs = SBD_STAT_EMPTY; 12937c478bd9Sstevel@tonic-gate break; 12947c478bd9Sstevel@tonic-gate case SBD_STATE_OCCUPIED: 12957c478bd9Sstevel@tonic-gate case SBD_STATE_FATAL: 12967c478bd9Sstevel@tonic-gate cs = SBD_STAT_DISCONNECTED; 12977c478bd9Sstevel@tonic-gate break; 12987c478bd9Sstevel@tonic-gate case SBD_STATE_CONFIGURED: 12997c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 13007c478bd9Sstevel@tonic-gate case SBD_STATE_UNCONFIGURED: 13017c478bd9Sstevel@tonic-gate case SBD_STATE_PARTIAL: 13027c478bd9Sstevel@tonic-gate case SBD_STATE_RELEASE: 13037c478bd9Sstevel@tonic-gate case SBD_STATE_UNREFERENCED: 13047c478bd9Sstevel@tonic-gate cs = SBD_STAT_CONNECTED; 13057c478bd9Sstevel@tonic-gate break; 13067c478bd9Sstevel@tonic-gate default: 13077c478bd9Sstevel@tonic-gate cs = SBD_STAT_NONE; 13087c478bd9Sstevel@tonic-gate break; 13097c478bd9Sstevel@tonic-gate } 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate return (cs); 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate sbd_state_t 13167c478bd9Sstevel@tonic-gate ostate_cvt(sbd_istate_t state) 13177c478bd9Sstevel@tonic-gate { 13187c478bd9Sstevel@tonic-gate sbd_state_t cs; 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate switch (state) { 13217c478bd9Sstevel@tonic-gate case SBD_STATE_EMPTY: 13227c478bd9Sstevel@tonic-gate case SBD_STATE_OCCUPIED: 13237c478bd9Sstevel@tonic-gate case SBD_STATE_UNCONFIGURED: 13247c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 13257c478bd9Sstevel@tonic-gate case SBD_STATE_FATAL: 13267c478bd9Sstevel@tonic-gate cs = SBD_STAT_UNCONFIGURED; 13277c478bd9Sstevel@tonic-gate break; 13287c478bd9Sstevel@tonic-gate case SBD_STATE_PARTIAL: 13297c478bd9Sstevel@tonic-gate case SBD_STATE_CONFIGURED: 13307c478bd9Sstevel@tonic-gate case SBD_STATE_RELEASE: 13317c478bd9Sstevel@tonic-gate case SBD_STATE_UNREFERENCED: 13327c478bd9Sstevel@tonic-gate cs = SBD_STAT_CONFIGURED; 13337c478bd9Sstevel@tonic-gate break; 13347c478bd9Sstevel@tonic-gate default: 13357c478bd9Sstevel@tonic-gate cs = SBD_STAT_NONE; 13367c478bd9Sstevel@tonic-gate break; 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate return (cs); 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate int 13437c478bd9Sstevel@tonic-gate sbd_dealloc_instance(sbd_board_t *sbp, int max_boards) 13447c478bd9Sstevel@tonic-gate { 13457c478bd9Sstevel@tonic-gate int b; 13467c478bd9Sstevel@tonic-gate sbd_board_t *list = sbp; 13477c478bd9Sstevel@tonic-gate static fn_t f = "sbd_dealloc_instance"; 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate if (sbp == NULL) { 13527c478bd9Sstevel@tonic-gate return (-1); 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate for (b = 0; b < max_boards; b++) { 13567c478bd9Sstevel@tonic-gate sbd_board_destroy(sbp++); 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate FREESTRUCT(list, sbd_board_t, max_boards); 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate return (0); 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate static sbd_devset_t 13657c478bd9Sstevel@tonic-gate sbd_dev2devset(sbd_comp_id_t *cid) 13667c478bd9Sstevel@tonic-gate { 13677c478bd9Sstevel@tonic-gate static fn_t f = "sbd_dev2devset"; 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate sbd_devset_t devset; 13707c478bd9Sstevel@tonic-gate int unit = cid->c_unit; 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate switch (cid->c_type) { 13737c478bd9Sstevel@tonic-gate case SBD_COMP_NONE: 13747c478bd9Sstevel@tonic-gate devset = DEVSET(SBD_COMP_CPU, DEVSET_ANYUNIT); 13757c478bd9Sstevel@tonic-gate devset |= DEVSET(SBD_COMP_MEM, DEVSET_ANYUNIT); 13767c478bd9Sstevel@tonic-gate devset |= DEVSET(SBD_COMP_IO, DEVSET_ANYUNIT); 13777c478bd9Sstevel@tonic-gate break; 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 13807c478bd9Sstevel@tonic-gate if ((unit > MAX_CPU_UNITS_PER_BOARD) || (unit < 0)) { 13817c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid cpu unit# = %d", 13827c478bd9Sstevel@tonic-gate f, unit); 13837c478bd9Sstevel@tonic-gate devset = 0; 13847c478bd9Sstevel@tonic-gate } else 13857c478bd9Sstevel@tonic-gate /* 13867c478bd9Sstevel@tonic-gate * Generate a devset that includes all the 13877c478bd9Sstevel@tonic-gate * cores of a CMP device. If this is not a 13887c478bd9Sstevel@tonic-gate * CMP, the extra cores will be eliminated 13897c478bd9Sstevel@tonic-gate * later since they are not present. This is 13907c478bd9Sstevel@tonic-gate * also true for CMP devices that do not have 13917c478bd9Sstevel@tonic-gate * all cores active. 13927c478bd9Sstevel@tonic-gate */ 13937c478bd9Sstevel@tonic-gate devset = DEVSET(SBD_COMP_CMP, unit); 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate break; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate if ((unit > MAX_MEM_UNITS_PER_BOARD) || (unit < 0)) { 14007c478bd9Sstevel@tonic-gate #ifdef XXX_jeffco 14017c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid mem unit# = %d", 14027c478bd9Sstevel@tonic-gate f, unit); 14037c478bd9Sstevel@tonic-gate devset = 0; 14047c478bd9Sstevel@tonic-gate #endif 14057c478bd9Sstevel@tonic-gate devset = DEVSET(cid->c_type, 0); 14067c478bd9Sstevel@tonic-gate PR_ALL("%s: adjusted MEM devset = 0x%x\n", 14077c478bd9Sstevel@tonic-gate f, devset); 14087c478bd9Sstevel@tonic-gate } else 14097c478bd9Sstevel@tonic-gate devset = DEVSET(cid->c_type, unit); 14107c478bd9Sstevel@tonic-gate break; 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 14137c478bd9Sstevel@tonic-gate if ((unit > MAX_IO_UNITS_PER_BOARD) || (unit < 0)) { 14147c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid io unit# = %d", 14157c478bd9Sstevel@tonic-gate f, unit); 14167c478bd9Sstevel@tonic-gate devset = 0; 14177c478bd9Sstevel@tonic-gate } else 14187c478bd9Sstevel@tonic-gate devset = DEVSET(cid->c_type, unit); 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate break; 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate default: 14237c478bd9Sstevel@tonic-gate case SBD_COMP_UNKNOWN: 14247c478bd9Sstevel@tonic-gate devset = 0; 14257c478bd9Sstevel@tonic-gate break; 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate return (devset); 14297c478bd9Sstevel@tonic-gate } 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate /* 14327c478bd9Sstevel@tonic-gate * Simple mutex for covering handle list ops as it is only 14337c478bd9Sstevel@tonic-gate * used "infrequently". No need to add another mutex to the sbd_board_t. 14347c478bd9Sstevel@tonic-gate */ 14357c478bd9Sstevel@tonic-gate static kmutex_t sbd_handle_list_mutex; 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate static sbd_handle_t * 14387c478bd9Sstevel@tonic-gate sbd_get_handle(dev_t dev, sbd_softstate_t *softsp, intptr_t arg, 14397c478bd9Sstevel@tonic-gate sbd_init_arg_t *iap) 14407c478bd9Sstevel@tonic-gate { 14417c478bd9Sstevel@tonic-gate sbd_handle_t *hp; 14427c478bd9Sstevel@tonic-gate sbderror_t *ep; 14437c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp; 14447c478bd9Sstevel@tonic-gate sbd_board_t *sbp = softsp->sbd_boardlist; 14457c478bd9Sstevel@tonic-gate int board; 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate board = SBDGETSLOT(dev); 14487c478bd9Sstevel@tonic-gate ASSERT(board < softsp->max_boards); 14497c478bd9Sstevel@tonic-gate sbp += board; 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate /* 14527c478bd9Sstevel@tonic-gate * Brand-new handle. 14537c478bd9Sstevel@tonic-gate */ 14547c478bd9Sstevel@tonic-gate shp = kmem_zalloc(sizeof (sbd_priv_handle_t), KM_SLEEP); 14557c478bd9Sstevel@tonic-gate shp->sh_arg = (void *)arg; 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate hp = MACHHD2HD(shp); 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate ep = &shp->sh_err; 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate hp->h_err = ep; 14627c478bd9Sstevel@tonic-gate hp->h_sbd = (void *) sbp; 14637c478bd9Sstevel@tonic-gate hp->h_dev = iap->dev; 14647c478bd9Sstevel@tonic-gate hp->h_cmd = iap->cmd; 14657c478bd9Sstevel@tonic-gate hp->h_mode = iap->mode; 14667c478bd9Sstevel@tonic-gate sbd_init_err(ep); 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate mutex_enter(&sbd_handle_list_mutex); 14697c478bd9Sstevel@tonic-gate shp->sh_next = sbp->sb_handle; 14707c478bd9Sstevel@tonic-gate sbp->sb_handle = shp; 14717c478bd9Sstevel@tonic-gate mutex_exit(&sbd_handle_list_mutex); 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate return (hp); 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate void 14777c478bd9Sstevel@tonic-gate sbd_init_err(sbderror_t *ep) 14787c478bd9Sstevel@tonic-gate { 14797c478bd9Sstevel@tonic-gate ep->e_errno = 0; 14807c478bd9Sstevel@tonic-gate ep->e_code = 0; 14817c478bd9Sstevel@tonic-gate ep->e_rsc[0] = '\0'; 14827c478bd9Sstevel@tonic-gate } 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate int 14857c478bd9Sstevel@tonic-gate sbd_set_err_in_hdl(sbd_handle_t *hp, sbderror_t *ep) 14867c478bd9Sstevel@tonic-gate { 14877c478bd9Sstevel@tonic-gate sbderror_t *hep = SBD_HD2ERR(hp); 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate /* 14907c478bd9Sstevel@tonic-gate * If there is an error logged already, don't rewrite it 14917c478bd9Sstevel@tonic-gate */ 14927c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(hep) || SBD_GET_ERRNO(hep)) { 14937c478bd9Sstevel@tonic-gate return (0); 14947c478bd9Sstevel@tonic-gate } 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) || SBD_GET_ERRNO(ep)) { 14977c478bd9Sstevel@tonic-gate SBD_SET_ERR(hep, SBD_GET_ERR(ep)); 14987c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(hep, SBD_GET_ERRNO(ep)); 14997c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(hep, SBD_GET_ERRSTR(ep)); 15007c478bd9Sstevel@tonic-gate return (0); 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate return (-1); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate static void 15077c478bd9Sstevel@tonic-gate sbd_release_handle(sbd_handle_t *hp) 15087c478bd9Sstevel@tonic-gate { 15097c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp, **shpp; 15107c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 15117c478bd9Sstevel@tonic-gate static fn_t f = "sbd_release_handle"; 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate if (hp == NULL) 15147c478bd9Sstevel@tonic-gate return; 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate shp = HD2MACHHD(hp); 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate mutex_enter(&sbd_handle_list_mutex); 15217c478bd9Sstevel@tonic-gate /* 15227c478bd9Sstevel@tonic-gate * Locate the handle in the board's reference list. 15237c478bd9Sstevel@tonic-gate */ 15247c478bd9Sstevel@tonic-gate for (shpp = &sbp->sb_handle; (*shpp) && ((*shpp) != shp); 15257c478bd9Sstevel@tonic-gate shpp = &((*shpp)->sh_next)) 15267c478bd9Sstevel@tonic-gate /* empty */; 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate if (*shpp == NULL) { 15297c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, 15307c478bd9Sstevel@tonic-gate "sbd:%s: handle not found in board %d", 15317c478bd9Sstevel@tonic-gate f, sbp->sb_num); 15327c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 15337c478bd9Sstevel@tonic-gate } else { 15347c478bd9Sstevel@tonic-gate *shpp = shp->sh_next; 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate mutex_exit(&sbd_handle_list_mutex); 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate if (hp->h_opts.copts != NULL) { 15397c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_opts.copts, char, hp->h_opts.size); 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate FREESTRUCT(shp, sbd_priv_handle_t, 1); 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate sbdp_handle_t * 15467c478bd9Sstevel@tonic-gate sbd_get_sbdp_handle(sbd_board_t *sbp, sbd_handle_t *hp) 15477c478bd9Sstevel@tonic-gate { 15487c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate hdp = kmem_zalloc(sizeof (sbdp_handle_t), KM_SLEEP); 15517c478bd9Sstevel@tonic-gate hdp->h_err = kmem_zalloc(sizeof (sbd_error_t), KM_SLEEP); 15527c478bd9Sstevel@tonic-gate if (sbp == NULL) { 15537c478bd9Sstevel@tonic-gate hdp->h_board = -1; 15547c478bd9Sstevel@tonic-gate hdp->h_wnode = -1; 15557c478bd9Sstevel@tonic-gate } else { 15567c478bd9Sstevel@tonic-gate hdp->h_board = sbp->sb_num; 15577c478bd9Sstevel@tonic-gate hdp->h_wnode = sbp->sb_wnode; 15587c478bd9Sstevel@tonic-gate } 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate if (hp == NULL) { 15617c478bd9Sstevel@tonic-gate hdp->h_flags = 0; 15627c478bd9Sstevel@tonic-gate hdp->h_opts = NULL; 15637c478bd9Sstevel@tonic-gate } else { 15647c478bd9Sstevel@tonic-gate hdp->h_flags = SBD_2_SBDP_FLAGS(hp->h_flags); 15657c478bd9Sstevel@tonic-gate hdp->h_opts = &hp->h_opts; 15667c478bd9Sstevel@tonic-gate } 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate return (hdp); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate void 15727c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(sbdp_handle_t *hdp) 15737c478bd9Sstevel@tonic-gate { 15747c478bd9Sstevel@tonic-gate if (hdp == NULL) 15757c478bd9Sstevel@tonic-gate return; 15767c478bd9Sstevel@tonic-gate 15777c478bd9Sstevel@tonic-gate kmem_free(hdp->h_err, sizeof (sbd_error_t)); 15787c478bd9Sstevel@tonic-gate kmem_free(hdp, sizeof (sbdp_handle_t)); 15797c478bd9Sstevel@tonic-gate } 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate void 15827c478bd9Sstevel@tonic-gate sbd_reset_error_sbdph(sbdp_handle_t *hdp) 15837c478bd9Sstevel@tonic-gate { 15847c478bd9Sstevel@tonic-gate if ((hdp != NULL) && (hdp->h_err != NULL)) { 15857c478bd9Sstevel@tonic-gate bzero(hdp->h_err, sizeof (sbd_error_t)); 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate static int 15907c478bd9Sstevel@tonic-gate sbd_copyin_ioarg(sbd_handle_t *hp, int mode, int cmd, sbd_cmd_t *cmdp, 15917c478bd9Sstevel@tonic-gate sbd_ioctl_arg_t *iap) 15927c478bd9Sstevel@tonic-gate { 15937c478bd9Sstevel@tonic-gate static fn_t f = "sbd_copyin_ioarg"; 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate if (iap == NULL) 15967c478bd9Sstevel@tonic-gate return (EINVAL); 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate bzero((caddr_t)cmdp, sizeof (sbd_cmd_t)); 15997c478bd9Sstevel@tonic-gate 16007c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 16017c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 16027c478bd9Sstevel@tonic-gate sbd_cmd32_t scmd32; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate bzero((caddr_t)&scmd32, sizeof (sbd_cmd32_t)); 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)iap, (void *)&scmd32, 16077c478bd9Sstevel@tonic-gate sizeof (sbd_cmd32_t), mode)) { 16087c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 16097c478bd9Sstevel@tonic-gate "sbd:%s: (32bit) failed to copyin " 16107c478bd9Sstevel@tonic-gate "sbdcmd-struct", f); 16117c478bd9Sstevel@tonic-gate return (EFAULT); 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_type = scmd32.cmd_cm.c_id.c_type; 16147c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_unit = scmd32.cmd_cm.c_id.c_unit; 16157c478bd9Sstevel@tonic-gate bcopy(&scmd32.cmd_cm.c_id.c_name[0], 16167c478bd9Sstevel@tonic-gate &cmdp->cmd_cm.c_id.c_name[0], OBP_MAXPROPNAME); 16177c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_flags = scmd32.cmd_cm.c_flags; 16187c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_len = scmd32.cmd_cm.c_len; 161904580fdfSmathue cmdp->cmd_cm.c_opts = (caddr_t)(uintptr_t)scmd32.cmd_cm.c_opts; 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate if (cmd == SBD_CMD_PASSTHRU) { 1622903a11ebSrh87107 PR_BYP("passthru copyin: iap=%p, sz=%ld", (void *)iap, 16237c478bd9Sstevel@tonic-gate sizeof (sbd_cmd32_t)); 162404580fdfSmathue PR_BYP("passthru copyin: c_opts=%x, c_len=%d", 16257c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_opts, 16267c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_len); 16277c478bd9Sstevel@tonic-gate } 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate switch (cmd) { 16307c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 16317c478bd9Sstevel@tonic-gate cmdp->cmd_stat.s_nbytes = scmd32.cmd_stat.s_nbytes; 16327c478bd9Sstevel@tonic-gate cmdp->cmd_stat.s_statp = 163304580fdfSmathue (caddr_t)(uintptr_t)scmd32.cmd_stat.s_statp; 16347c478bd9Sstevel@tonic-gate break; 16357c478bd9Sstevel@tonic-gate default: 16367c478bd9Sstevel@tonic-gate break; 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate } 16397c478bd9Sstevel@tonic-gate } else 16407c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 16417c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)iap, (void *)cmdp, 16427c478bd9Sstevel@tonic-gate sizeof (sbd_cmd_t), mode) != 0) { 16437c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 16447c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyin sbd cmd_t struct", f); 16457c478bd9Sstevel@tonic-gate return (EFAULT); 16467c478bd9Sstevel@tonic-gate } 16477c478bd9Sstevel@tonic-gate /* 16487c478bd9Sstevel@tonic-gate * A user may set platform specific options so we need to 16497c478bd9Sstevel@tonic-gate * copy them in 16507c478bd9Sstevel@tonic-gate */ 16517c478bd9Sstevel@tonic-gate if ((cmd != SBD_CMD_STATUS) && ((hp->h_opts.size = cmdp->cmd_cm.c_len) 16527c478bd9Sstevel@tonic-gate > 0)) { 16537c478bd9Sstevel@tonic-gate hp->h_opts.size += 1; /* For null termination of string. */ 16547c478bd9Sstevel@tonic-gate hp->h_opts.copts = GETSTRUCT(char, hp->h_opts.size); 16557c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)cmdp->cmd_cm.c_opts, 16567c478bd9Sstevel@tonic-gate (void *)hp->h_opts.copts, 16577c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_len, hp->h_mode) != 0) { 16587c478bd9Sstevel@tonic-gate /* copts is freed in sbd_release_handle(). */ 16597c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 16607c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyin options", f); 16617c478bd9Sstevel@tonic-gate return (EFAULT); 16627c478bd9Sstevel@tonic-gate } 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate return (0); 16667c478bd9Sstevel@tonic-gate } 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate static int 16697c478bd9Sstevel@tonic-gate sbd_copyout_ioarg(int mode, int cmd, sbd_cmd_t *scp, sbd_ioctl_arg_t *iap) 16707c478bd9Sstevel@tonic-gate { 16717c478bd9Sstevel@tonic-gate static fn_t f = "sbd_copyout_ioarg"; 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate if ((iap == NULL) || (scp == NULL)) 16747c478bd9Sstevel@tonic-gate return (EINVAL); 16757c478bd9Sstevel@tonic-gate 16767c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 16777c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 16787c478bd9Sstevel@tonic-gate sbd_cmd32_t scmd32; 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_id.c_type = scp->cmd_cm.c_id.c_type; 16817c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_id.c_unit = scp->cmd_cm.c_id.c_unit; 16827c478bd9Sstevel@tonic-gate bcopy(scp->cmd_cm.c_id.c_name, 16837c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_id.c_name, OBP_MAXPROPNAME); 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_flags = scp->cmd_cm.c_flags; 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate switch (cmd) { 16887c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 16897c478bd9Sstevel@tonic-gate scmd32.cmd_getncm.g_ncm = scp->cmd_getncm.g_ncm; 16907c478bd9Sstevel@tonic-gate break; 16917c478bd9Sstevel@tonic-gate default: 16927c478bd9Sstevel@tonic-gate break; 16937c478bd9Sstevel@tonic-gate } 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)&scmd32, (void *)iap, 16967c478bd9Sstevel@tonic-gate sizeof (sbd_cmd32_t), mode)) { 16977c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 16987c478bd9Sstevel@tonic-gate "sbd:%s: (32bit) failed to copyout " 16997c478bd9Sstevel@tonic-gate "sbdcmd struct", f); 17007c478bd9Sstevel@tonic-gate return (EFAULT); 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate } else 17037c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 17047c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)scp, (void *)iap, 17057c478bd9Sstevel@tonic-gate sizeof (sbd_cmd_t), mode) != 0) { 17067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 17077c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout sbdcmd struct", f); 17087c478bd9Sstevel@tonic-gate return (EFAULT); 17097c478bd9Sstevel@tonic-gate } 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate return (0); 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate static int 17157c478bd9Sstevel@tonic-gate sbd_copyout_errs(int mode, sbd_ioctl_arg_t *iap, void *arg) 17167c478bd9Sstevel@tonic-gate { 17177c478bd9Sstevel@tonic-gate static fn_t f = "sbd_copyout_errs"; 17187c478bd9Sstevel@tonic-gate sbd_ioctl_arg_t *uap; 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate uap = (sbd_ioctl_arg_t *)arg; 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 17237c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 17247c478bd9Sstevel@tonic-gate sbd_error32_t err32; 17257c478bd9Sstevel@tonic-gate sbd_ioctl_arg32_t *uap32; 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate uap32 = (sbd_ioctl_arg32_t *)arg; 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate err32.e_code = iap->ie_code; 17307c478bd9Sstevel@tonic-gate (void) strcpy(err32.e_rsc, iap->ie_rsc); 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)&err32, (void *)&uap32->i_err, 17337c478bd9Sstevel@tonic-gate sizeof (sbd_error32_t), mode)) { 17347c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 17357c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout ioctl32 errs", 17367c478bd9Sstevel@tonic-gate f); 17377c478bd9Sstevel@tonic-gate return (EFAULT); 17387c478bd9Sstevel@tonic-gate } 17397c478bd9Sstevel@tonic-gate } else 17407c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 17417c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)&iap->i_err, (void *)&uap->i_err, 17427c478bd9Sstevel@tonic-gate sizeof (sbd_error_t), mode) != 0) { 17437c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 17447c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout ioctl errs", f); 17457c478bd9Sstevel@tonic-gate return (EFAULT); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate return (0); 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate /* 17527c478bd9Sstevel@tonic-gate * State transition policy is that if at least one 17537c478bd9Sstevel@tonic-gate * device cannot make the transition, then none of 17547c478bd9Sstevel@tonic-gate * the requested devices are allowed to transition. 17557c478bd9Sstevel@tonic-gate * 17567c478bd9Sstevel@tonic-gate * Returns the state that is in error, if any. 17577c478bd9Sstevel@tonic-gate */ 17587c478bd9Sstevel@tonic-gate static int 17597c478bd9Sstevel@tonic-gate sbd_check_transition(sbd_board_t *sbp, sbd_devset_t *devsetp, 17607c478bd9Sstevel@tonic-gate struct sbd_state_trans *transp) 17617c478bd9Sstevel@tonic-gate { 17627c478bd9Sstevel@tonic-gate int s, ut; 17637c478bd9Sstevel@tonic-gate int state_err = 0; 17647c478bd9Sstevel@tonic-gate sbd_devset_t devset; 17657c478bd9Sstevel@tonic-gate static fn_t f = "sbd_check_transition"; 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate devset = *devsetp; 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate if (!devset) { 17707c478bd9Sstevel@tonic-gate /* 17717c478bd9Sstevel@tonic-gate * Transition does not deal with any components. 17727c478bd9Sstevel@tonic-gate * This is the case for addboard/deleteboard. 17737c478bd9Sstevel@tonic-gate */ 17747c478bd9Sstevel@tonic-gate PR_ALL("%s: no devs: requested devset = 0x%x," 17757c478bd9Sstevel@tonic-gate " final devset = 0x%x\n", 17767c478bd9Sstevel@tonic-gate f, (uint_t)*devsetp, (uint_t)devset); 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate return (0); 17797c478bd9Sstevel@tonic-gate } 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) { 17827c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_MEM_UNITS_PER_BOARD; ut++) { 17837c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, ut) == 0) 17847c478bd9Sstevel@tonic-gate continue; 17857c478bd9Sstevel@tonic-gate s = (int)SBD_DEVICE_STATE(sbp, SBD_COMP_MEM, ut); 17867c478bd9Sstevel@tonic-gate if (transp->x_op[s].x_rv) { 17877c478bd9Sstevel@tonic-gate if (!state_err) 17887c478bd9Sstevel@tonic-gate state_err = s; 17897c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_MEM, ut); 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate } 17927c478bd9Sstevel@tonic-gate } 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) { 17957c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_CPU_UNITS_PER_BOARD; ut++) { 17967c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, ut) == 0) 17977c478bd9Sstevel@tonic-gate continue; 17987c478bd9Sstevel@tonic-gate s = (int)SBD_DEVICE_STATE(sbp, SBD_COMP_CPU, ut); 17997c478bd9Sstevel@tonic-gate if (transp->x_op[s].x_rv) { 18007c478bd9Sstevel@tonic-gate if (!state_err) 18017c478bd9Sstevel@tonic-gate state_err = s; 18027c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_CPU, ut); 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate } 18057c478bd9Sstevel@tonic-gate } 18067c478bd9Sstevel@tonic-gate 18077c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) { 18087c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_IO_UNITS_PER_BOARD; ut++) { 18097c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, ut) == 0) 18107c478bd9Sstevel@tonic-gate continue; 18117c478bd9Sstevel@tonic-gate s = (int)SBD_DEVICE_STATE(sbp, SBD_COMP_IO, ut); 18127c478bd9Sstevel@tonic-gate if (transp->x_op[s].x_rv) { 18137c478bd9Sstevel@tonic-gate if (!state_err) 18147c478bd9Sstevel@tonic-gate state_err = s; 18157c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_IO, ut); 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate } 18187c478bd9Sstevel@tonic-gate } 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate PR_ALL("%s: requested devset = 0x%x, final devset = 0x%x\n", 18217c478bd9Sstevel@tonic-gate f, (uint_t)*devsetp, (uint_t)devset); 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate *devsetp = devset; 18247c478bd9Sstevel@tonic-gate /* 18257c478bd9Sstevel@tonic-gate * If there are some remaining components for which 18267c478bd9Sstevel@tonic-gate * this state transition is valid, then allow them 18277c478bd9Sstevel@tonic-gate * through, otherwise if none are left then return 18287c478bd9Sstevel@tonic-gate * the state error. 18297c478bd9Sstevel@tonic-gate */ 18307c478bd9Sstevel@tonic-gate return (devset ? 0 : state_err); 18317c478bd9Sstevel@tonic-gate } 18327c478bd9Sstevel@tonic-gate 18337c478bd9Sstevel@tonic-gate /* 18347c478bd9Sstevel@tonic-gate * pre-op entry point must SET_ERRNO(), if needed. 18357c478bd9Sstevel@tonic-gate * Return value of non-zero indicates failure. 18367c478bd9Sstevel@tonic-gate */ 18377c478bd9Sstevel@tonic-gate static int 18387c478bd9Sstevel@tonic-gate sbd_pre_op(sbd_handle_t *hp) 18397c478bd9Sstevel@tonic-gate { 18407c478bd9Sstevel@tonic-gate int rv = 0, t; 18417c478bd9Sstevel@tonic-gate int cmd, serr = 0; 18427c478bd9Sstevel@tonic-gate sbd_devset_t devset; 18437c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 18447c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 18457c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 18467c478bd9Sstevel@tonic-gate sbd_cmd_t *cmdp; 18477c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_op"; 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate cmd = hp->h_cmd; 18507c478bd9Sstevel@tonic-gate devset = shp->sh_devset; 18517c478bd9Sstevel@tonic-gate 18527c478bd9Sstevel@tonic-gate switch (cmd) { 18537c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: 18547c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: 18557c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: 18567c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: 18577c478bd9Sstevel@tonic-gate case SBD_CMD_ASSIGN: 18587c478bd9Sstevel@tonic-gate case SBD_CMD_UNASSIGN: 18597c478bd9Sstevel@tonic-gate case SBD_CMD_POWERON: 18607c478bd9Sstevel@tonic-gate case SBD_CMD_POWEROFF: 18617c478bd9Sstevel@tonic-gate case SBD_CMD_TEST: 18627c478bd9Sstevel@tonic-gate /* ioctls allowed if caller has write permission */ 18637c478bd9Sstevel@tonic-gate if (!(hp->h_mode & FWRITE)) { 18647c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EPERM); 18657c478bd9Sstevel@tonic-gate return (-1); 18667c478bd9Sstevel@tonic-gate } 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate default: 18697c478bd9Sstevel@tonic-gate break; 18707c478bd9Sstevel@tonic-gate } 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate hp->h_iap = GETSTRUCT(sbd_ioctl_arg_t, 1); 18737c478bd9Sstevel@tonic-gate rv = sbd_copyin_ioarg(hp, hp->h_mode, cmd, 18747c478bd9Sstevel@tonic-gate (sbd_cmd_t *)hp->h_iap, shp->sh_arg); 18757c478bd9Sstevel@tonic-gate if (rv) { 18767c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, rv); 18777c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_iap, sbd_ioctl_arg_t, 1); 18787c478bd9Sstevel@tonic-gate hp->h_iap = NULL; 18797c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: copyin fail", f); 18807c478bd9Sstevel@tonic-gate return (-1); 18817c478bd9Sstevel@tonic-gate } else { 18827c478bd9Sstevel@tonic-gate cmdp = (sbd_cmd_t *)hp->h_iap; 18837c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_id.c_name[0] != '\0') { 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_type = SBD_COMP(sbd_name_to_idx( 18867c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_name)); 18877c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_id.c_type == SBD_COMP_MEM) { 18887c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_id.c_unit == -1) 18897c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_unit = 0; 18907c478bd9Sstevel@tonic-gate } 18917c478bd9Sstevel@tonic-gate } 18927c478bd9Sstevel@tonic-gate devset = shp->sh_orig_devset = shp->sh_devset = 18937c478bd9Sstevel@tonic-gate sbd_dev2devset(&cmdp->cmd_cm.c_id); 18947c478bd9Sstevel@tonic-gate if (devset == 0) { 18957c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EINVAL); 18967c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_iap, sbd_ioctl_arg_t, 1); 18977c478bd9Sstevel@tonic-gate hp->h_iap = NULL; 18987c478bd9Sstevel@tonic-gate return (-1); 18997c478bd9Sstevel@tonic-gate } 19007c478bd9Sstevel@tonic-gate } 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate /* 19037c478bd9Sstevel@tonic-gate * Always turn on these bits ala Sunfire DR. 19047c478bd9Sstevel@tonic-gate */ 19057c478bd9Sstevel@tonic-gate hp->h_flags |= SBD_FLAG_DEVI_FORCE; 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_flags & SBD_FLAG_FORCE) 19087c478bd9Sstevel@tonic-gate hp->h_flags |= SBD_IOCTL_FLAG_FORCE; 19097c478bd9Sstevel@tonic-gate 19107c478bd9Sstevel@tonic-gate /* 19117c478bd9Sstevel@tonic-gate * Check for valid state transitions. 19127c478bd9Sstevel@tonic-gate */ 19137c478bd9Sstevel@tonic-gate if (!serr && ((t = CMD2INDEX(cmd)) != -1)) { 19147c478bd9Sstevel@tonic-gate struct sbd_state_trans *transp; 19157c478bd9Sstevel@tonic-gate int state_err; 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate transp = &sbd_state_transition[t]; 19187c478bd9Sstevel@tonic-gate ASSERT(transp->x_cmd == cmd); 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate state_err = sbd_check_transition(sbp, &devset, transp); 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate if (state_err < 0) { 19237c478bd9Sstevel@tonic-gate /* 19247c478bd9Sstevel@tonic-gate * Invalidate device. 19257c478bd9Sstevel@tonic-gate */ 19267c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, ENOTTY); 19277c478bd9Sstevel@tonic-gate serr = -1; 19287c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid devset (0x%x)\n", 19297c478bd9Sstevel@tonic-gate f, (uint_t)devset); 19307c478bd9Sstevel@tonic-gate } else if (state_err != 0) { 19317c478bd9Sstevel@tonic-gate /* 19327c478bd9Sstevel@tonic-gate * State transition is not a valid one. 19337c478bd9Sstevel@tonic-gate */ 19347c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, transp->x_op[state_err].x_err); 19357c478bd9Sstevel@tonic-gate serr = transp->x_op[state_err].x_rv; 19367c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid state %s(%d) for cmd %s(%d)\n", 19377c478bd9Sstevel@tonic-gate f, sbd_state_str[state_err], state_err, 19387c478bd9Sstevel@tonic-gate SBD_CMD_STR(cmd), cmd); 19397c478bd9Sstevel@tonic-gate } 19407c478bd9Sstevel@tonic-gate if (serr && SBD_GET_ERRNO(ep) != 0) { 19417c478bd9Sstevel@tonic-gate /* 19427c478bd9Sstevel@tonic-gate * A state transition error occurred. 19437c478bd9Sstevel@tonic-gate */ 19447c478bd9Sstevel@tonic-gate if (serr < 0) { 19457c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_INVAL); 19467c478bd9Sstevel@tonic-gate } else { 19477c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_STATE); 19487c478bd9Sstevel@tonic-gate } 19497c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid state transition\n", f); 19507c478bd9Sstevel@tonic-gate } else { 19517c478bd9Sstevel@tonic-gate shp->sh_devset = devset; 19527c478bd9Sstevel@tonic-gate } 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate if (serr && !rv && hp->h_iap) { 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate /* 19587c478bd9Sstevel@tonic-gate * There was a state error. We successfully copied 19597c478bd9Sstevel@tonic-gate * in the ioctl argument, so let's fill in the 19607c478bd9Sstevel@tonic-gate * error and copy it back out. 19617c478bd9Sstevel@tonic-gate */ 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) && SBD_GET_ERRNO(ep) == 0) 19647c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EIO); 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate SBD_SET_IOCTL_ERR(&hp->h_iap->i_err, 19677c478bd9Sstevel@tonic-gate ep->e_code, 19687c478bd9Sstevel@tonic-gate ep->e_rsc); 19697c478bd9Sstevel@tonic-gate (void) sbd_copyout_errs(hp->h_mode, hp->h_iap, shp->sh_arg); 19707c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_iap, sbd_ioctl_arg_t, 1); 19717c478bd9Sstevel@tonic-gate hp->h_iap = NULL; 19727c478bd9Sstevel@tonic-gate rv = -1; 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate return (rv); 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate static void 19797c478bd9Sstevel@tonic-gate sbd_post_op(sbd_handle_t *hp) 19807c478bd9Sstevel@tonic-gate { 19817c478bd9Sstevel@tonic-gate int cmd; 19827c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 19837c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 19847c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate cmd = hp->h_cmd; 19877c478bd9Sstevel@tonic-gate 19887c478bd9Sstevel@tonic-gate switch (cmd) { 19897c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: 19907c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: 19917c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: 19927c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: 19937c478bd9Sstevel@tonic-gate sbp->sb_time = gethrestime_sec(); 19947c478bd9Sstevel@tonic-gate break; 19957c478bd9Sstevel@tonic-gate 19967c478bd9Sstevel@tonic-gate default: 19977c478bd9Sstevel@tonic-gate break; 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) && SBD_GET_ERRNO(ep) == 0) { 20017c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EIO); 20027c478bd9Sstevel@tonic-gate } 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate if (shp->sh_arg != NULL) { 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) != ESBD_NOERROR) { 20077c478bd9Sstevel@tonic-gate 20087c478bd9Sstevel@tonic-gate SBD_SET_IOCTL_ERR(&hp->h_iap->i_err, 20097c478bd9Sstevel@tonic-gate ep->e_code, 20107c478bd9Sstevel@tonic-gate ep->e_rsc); 20117c478bd9Sstevel@tonic-gate 20127c478bd9Sstevel@tonic-gate (void) sbd_copyout_errs(hp->h_mode, hp->h_iap, 20137c478bd9Sstevel@tonic-gate shp->sh_arg); 20147c478bd9Sstevel@tonic-gate } 20157c478bd9Sstevel@tonic-gate 20167c478bd9Sstevel@tonic-gate if (hp->h_iap != NULL) { 20177c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_iap, sbd_ioctl_arg_t, 1); 20187c478bd9Sstevel@tonic-gate hp->h_iap = NULL; 20197c478bd9Sstevel@tonic-gate } 20207c478bd9Sstevel@tonic-gate } 20217c478bd9Sstevel@tonic-gate } 20227c478bd9Sstevel@tonic-gate 20237c478bd9Sstevel@tonic-gate static int 20247c478bd9Sstevel@tonic-gate sbd_probe_board(sbd_handle_t *hp) 20257c478bd9Sstevel@tonic-gate { 20267c478bd9Sstevel@tonic-gate int rv; 20277c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 20287c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 20297c478bd9Sstevel@tonic-gate static fn_t f = "sbd_probe_board"; 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 20327c478bd9Sstevel@tonic-gate 20337c478bd9Sstevel@tonic-gate ASSERT(sbp != NULL); 20347c478bd9Sstevel@tonic-gate PR_ALL("%s for board %d", f, sbp->sb_num); 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate if ((rv = sbdp_connect_board(hdp)) != 0) { 20407c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 20417c478bd9Sstevel@tonic-gate 20427c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 20437c478bd9Sstevel@tonic-gate } 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate /* 20467c478bd9Sstevel@tonic-gate * We need to force a recache after the connect. The cached 20477c478bd9Sstevel@tonic-gate * info may be incorrect 20487c478bd9Sstevel@tonic-gate */ 20497c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_flags_mutex); 20507c478bd9Sstevel@tonic-gate sbp->sb_flags &= ~SBD_BOARD_STATUS_CACHED; 20517c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_flags_mutex); 20527c478bd9Sstevel@tonic-gate 20537c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_PROBE_BOARD_PSEUDO_ERR, hp->h_err, EIO, 20547c478bd9Sstevel@tonic-gate ESGT_PROBE, NULL); 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 20577c478bd9Sstevel@tonic-gate 20587c478bd9Sstevel@tonic-gate return (rv); 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate 20617c478bd9Sstevel@tonic-gate static int 20627c478bd9Sstevel@tonic-gate sbd_deprobe_board(sbd_handle_t *hp) 20637c478bd9Sstevel@tonic-gate { 20647c478bd9Sstevel@tonic-gate int rv; 20657c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 20667c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 20677c478bd9Sstevel@tonic-gate static fn_t f = "sbd_deprobe_board"; 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 20707c478bd9Sstevel@tonic-gate 20717c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 20747c478bd9Sstevel@tonic-gate 20757c478bd9Sstevel@tonic-gate if ((rv = sbdp_disconnect_board(hdp)) != 0) { 20767c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 20797c478bd9Sstevel@tonic-gate } 20807c478bd9Sstevel@tonic-gate 20817c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_flags_mutex); 20827c478bd9Sstevel@tonic-gate sbp->sb_flags &= ~SBD_BOARD_STATUS_CACHED; 20837c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_flags_mutex); 20847c478bd9Sstevel@tonic-gate 20857c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_DEPROBE_BOARD_PSEUDO_ERR, hp->h_err, EIO, 20867c478bd9Sstevel@tonic-gate ESGT_DEPROBE, NULL); 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 20897c478bd9Sstevel@tonic-gate return (rv); 20907c478bd9Sstevel@tonic-gate } 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate /* 20937c478bd9Sstevel@tonic-gate * Check if a CPU node is part of a CMP. 20947c478bd9Sstevel@tonic-gate */ 20957c478bd9Sstevel@tonic-gate int 20967c478bd9Sstevel@tonic-gate sbd_is_cmp_child(dev_info_t *dip) 20977c478bd9Sstevel@tonic-gate { 20987c478bd9Sstevel@tonic-gate dev_info_t *pdip; 20997c478bd9Sstevel@tonic-gate 21007c478bd9Sstevel@tonic-gate if (strcmp(ddi_node_name(dip), "cpu") != 0) { 21017c478bd9Sstevel@tonic-gate return (0); 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(dip); 21057c478bd9Sstevel@tonic-gate 21067c478bd9Sstevel@tonic-gate ASSERT(pdip); 21077c478bd9Sstevel@tonic-gate 21087c478bd9Sstevel@tonic-gate if (strcmp(ddi_node_name(pdip), "cmp") == 0) { 21097c478bd9Sstevel@tonic-gate return (1); 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate 21127c478bd9Sstevel@tonic-gate return (0); 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate /* 21167c478bd9Sstevel@tonic-gate * Returns the nodetype if dip is a top dip on the board of 21177c478bd9Sstevel@tonic-gate * interest or SBD_COMP_UNKNOWN otherwise 21187c478bd9Sstevel@tonic-gate */ 21197c478bd9Sstevel@tonic-gate static sbd_comp_type_t 21207c478bd9Sstevel@tonic-gate get_node_type(sbd_board_t *sbp, dev_info_t *dip, int *unitp) 21217c478bd9Sstevel@tonic-gate { 21227c478bd9Sstevel@tonic-gate int idx, unit; 21237c478bd9Sstevel@tonic-gate sbd_handle_t *hp; 21247c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 21257c478bd9Sstevel@tonic-gate char otype[OBP_MAXDRVNAME]; 21267c478bd9Sstevel@tonic-gate int otypelen; 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate ASSERT(sbp); 21297c478bd9Sstevel@tonic-gate 21307c478bd9Sstevel@tonic-gate if (unitp) 21317c478bd9Sstevel@tonic-gate *unitp = -1; 21327c478bd9Sstevel@tonic-gate 21337c478bd9Sstevel@tonic-gate hp = MACHBD2HD(sbp); 21347c478bd9Sstevel@tonic-gate 21357c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 21367c478bd9Sstevel@tonic-gate if (sbdp_get_board_num(hdp, dip) != sbp->sb_num) { 21377c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 21387c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 21397c478bd9Sstevel@tonic-gate } 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate /* 21427c478bd9Sstevel@tonic-gate * sbdp_get_unit_num will return (-1) for cmp as there 21437c478bd9Sstevel@tonic-gate * is no "device_type" property associated with cmp. 21447c478bd9Sstevel@tonic-gate * Therefore we will just skip getting unit number for 21457c478bd9Sstevel@tonic-gate * cmp. Callers of this function need to check the 21467c478bd9Sstevel@tonic-gate * value set in unitp before using it to dereference 21477c478bd9Sstevel@tonic-gate * an array. 21487c478bd9Sstevel@tonic-gate */ 21497c478bd9Sstevel@tonic-gate if (strcmp(ddi_node_name(dip), "cmp") == 0) { 21507c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 21517c478bd9Sstevel@tonic-gate return (SBD_COMP_CMP); 21527c478bd9Sstevel@tonic-gate } 21537c478bd9Sstevel@tonic-gate 21547c478bd9Sstevel@tonic-gate otypelen = sizeof (otype); 21557c478bd9Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 21567c478bd9Sstevel@tonic-gate OBP_DEVICETYPE, (caddr_t)otype, &otypelen)) { 21577c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 21587c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 21597c478bd9Sstevel@tonic-gate } 21607c478bd9Sstevel@tonic-gate 21617c478bd9Sstevel@tonic-gate idx = sbd_otype_to_idx(otype); 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate if (SBD_COMP(idx) == SBD_COMP_UNKNOWN) { 21647c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 21657c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 21667c478bd9Sstevel@tonic-gate } 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 21697c478bd9Sstevel@tonic-gate if (unit == -1) { 21707c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 21717c478bd9Sstevel@tonic-gate "get_node_type: %s unit fail %p", otype, (void *)dip); 21727c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 21737c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 21747c478bd9Sstevel@tonic-gate } 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate if (unitp) 21797c478bd9Sstevel@tonic-gate *unitp = unit; 21807c478bd9Sstevel@tonic-gate 21817c478bd9Sstevel@tonic-gate return (SBD_COMP(idx)); 21827c478bd9Sstevel@tonic-gate } 21837c478bd9Sstevel@tonic-gate 21847c478bd9Sstevel@tonic-gate typedef struct { 21857c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 21867c478bd9Sstevel@tonic-gate int nmc; 21877c478bd9Sstevel@tonic-gate int hold; 21887c478bd9Sstevel@tonic-gate } walk_tree_t; 21897c478bd9Sstevel@tonic-gate 21907c478bd9Sstevel@tonic-gate static int 21917c478bd9Sstevel@tonic-gate sbd_setup_devlists(dev_info_t *dip, void *arg) 21927c478bd9Sstevel@tonic-gate { 21937c478bd9Sstevel@tonic-gate walk_tree_t *wp; 21947c478bd9Sstevel@tonic-gate dev_info_t **devlist = NULL; 21957c478bd9Sstevel@tonic-gate char *pathname = NULL; 21967c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 21977c478bd9Sstevel@tonic-gate static fn_t f = "sbd_setup_devlists"; 21987c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 21997c478bd9Sstevel@tonic-gate int unit; 22007c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate ASSERT(dip); 22037c478bd9Sstevel@tonic-gate 22047c478bd9Sstevel@tonic-gate wp = (walk_tree_t *)arg; 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate if (wp == NULL) { 22077c478bd9Sstevel@tonic-gate PR_ALL("%s:bad arg\n", f); 22087c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 22097c478bd9Sstevel@tonic-gate } 22107c478bd9Sstevel@tonic-gate 22117c478bd9Sstevel@tonic-gate sbp = wp->sbp; 22127c478bd9Sstevel@tonic-gate 22137c478bd9Sstevel@tonic-gate nodetype = get_node_type(sbp, dip, &unit); 22147c478bd9Sstevel@tonic-gate 22157c478bd9Sstevel@tonic-gate switch (nodetype) { 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 22187c478bd9Sstevel@tonic-gate pathname = sbp->sb_cpupath[unit]; 22197c478bd9Sstevel@tonic-gate break; 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 22227c478bd9Sstevel@tonic-gate pathname = sbp->sb_mempath[unit]; 22237c478bd9Sstevel@tonic-gate break; 22247c478bd9Sstevel@tonic-gate 22257c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 22267c478bd9Sstevel@tonic-gate pathname = sbp->sb_iopath[unit]; 22277c478bd9Sstevel@tonic-gate break; 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate case SBD_COMP_CMP: 22307c478bd9Sstevel@tonic-gate case SBD_COMP_UNKNOWN: 22317c478bd9Sstevel@tonic-gate /* 22327c478bd9Sstevel@tonic-gate * This dip is not of interest to us 22337c478bd9Sstevel@tonic-gate */ 22347c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 22357c478bd9Sstevel@tonic-gate 22367c478bd9Sstevel@tonic-gate default: 22377c478bd9Sstevel@tonic-gate ASSERT(0); 22387c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 22397c478bd9Sstevel@tonic-gate } 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate /* 22427c478bd9Sstevel@tonic-gate * dip's parent is being held busy by ddi_walk_devs(), 22437c478bd9Sstevel@tonic-gate * so dip doesn't have to be held while calling ddi_pathname() 22447c478bd9Sstevel@tonic-gate */ 22457c478bd9Sstevel@tonic-gate if (pathname) { 22467c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, pathname); 22477c478bd9Sstevel@tonic-gate } 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(nodetype)]; 22507c478bd9Sstevel@tonic-gate 22517c478bd9Sstevel@tonic-gate /* 22527c478bd9Sstevel@tonic-gate * The branch rooted at dip should already be held, 22537c478bd9Sstevel@tonic-gate * unless we are dealing with a core of a CMP. 22547c478bd9Sstevel@tonic-gate */ 22557c478bd9Sstevel@tonic-gate ASSERT(sbd_is_cmp_child(dip) || e_ddi_branch_held(dip)); 22567c478bd9Sstevel@tonic-gate devlist[unit] = dip; 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate /* 22597c478bd9Sstevel@tonic-gate * This test is required if multiple devices are considered 22607c478bd9Sstevel@tonic-gate * as one. This is the case for memory-controller nodes. 22617c478bd9Sstevel@tonic-gate */ 22627c478bd9Sstevel@tonic-gate if (!SBD_DEV_IS_PRESENT(sbp, nodetype, unit)) { 22637c478bd9Sstevel@tonic-gate sbp->sb_ndev++; 22647c478bd9Sstevel@tonic-gate SBD_DEV_SET_PRESENT(sbp, nodetype, unit); 22657c478bd9Sstevel@tonic-gate } 22667c478bd9Sstevel@tonic-gate 22677c478bd9Sstevel@tonic-gate if (nodetype == SBD_COMP_MEM) { 22687c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, unit); 22697c478bd9Sstevel@tonic-gate ASSERT(wp->nmc < SBD_NUM_MC_PER_BOARD); 22707c478bd9Sstevel@tonic-gate mp->sbm_dip[wp->nmc++] = dip; 22717c478bd9Sstevel@tonic-gate } 22727c478bd9Sstevel@tonic-gate 22737c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 22747c478bd9Sstevel@tonic-gate } 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate /* 22777c478bd9Sstevel@tonic-gate * This routine is used to construct the memory devlist. 22787c478bd9Sstevel@tonic-gate * In Starcat and Serengeti platforms, a system board can contain up to 22797c478bd9Sstevel@tonic-gate * four memory controllers (MC). The MCs have been programmed by POST for 22807c478bd9Sstevel@tonic-gate * optimum memory interleaving amongst their peers on the same board. 22817c478bd9Sstevel@tonic-gate * This DR driver does not support deinterleaving. Therefore, the smallest 22827c478bd9Sstevel@tonic-gate * unit of memory that can be manipulated by this driver is all of the 22837c478bd9Sstevel@tonic-gate * memory on a board. Because of this restriction, a board's memory devlist 22847c478bd9Sstevel@tonic-gate * is populated with only one of the four (possible) MC dnodes on that board. 22857c478bd9Sstevel@tonic-gate * Care must be taken to ensure that the selected MC dnode represents the 22867c478bd9Sstevel@tonic-gate * lowest physical address to which memory on the board will respond to. 22877c478bd9Sstevel@tonic-gate * This is required in order to preserve the semantics of 22887c478bd9Sstevel@tonic-gate * sbdp_get_base_physaddr() when applied to a MC dnode stored in the 22897c478bd9Sstevel@tonic-gate * memory devlist. 22907c478bd9Sstevel@tonic-gate */ 22917c478bd9Sstevel@tonic-gate static void 22927c478bd9Sstevel@tonic-gate sbd_init_mem_devlists(sbd_board_t *sbp) 22937c478bd9Sstevel@tonic-gate { 22947c478bd9Sstevel@tonic-gate dev_info_t **devlist; 22957c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 22967c478bd9Sstevel@tonic-gate dev_info_t *mc_dip; 22977c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 22987c478bd9Sstevel@tonic-gate uint64_t mc_pa, lowest_pa; 22997c478bd9Sstevel@tonic-gate int i; 23007c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(SBD_COMP_MEM)]; 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, 0); 23057c478bd9Sstevel@tonic-gate 23067c478bd9Sstevel@tonic-gate mc_dip = mp->sbm_dip[0]; 23077c478bd9Sstevel@tonic-gate if (mc_dip == NULL) 23087c478bd9Sstevel@tonic-gate return; /* No MC dips found for this board */ 23097c478bd9Sstevel@tonic-gate 23107c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 23117c478bd9Sstevel@tonic-gate 23127c478bd9Sstevel@tonic-gate if (sbdphw_get_base_physaddr(hdp, mc_dip, &mc_pa)) { 23137c478bd9Sstevel@tonic-gate /* TODO: log complaint about dnode */ 23147c478bd9Sstevel@tonic-gate 23157c478bd9Sstevel@tonic-gate pretend_no_mem: 23167c478bd9Sstevel@tonic-gate /* 23177c478bd9Sstevel@tonic-gate * We are here because sbdphw_get_base_physaddr() failed. 23187c478bd9Sstevel@tonic-gate * Although it is very unlikely to happen, it did. Lucky us. 23197c478bd9Sstevel@tonic-gate * Since we can no longer examine _all_ of the MCs on this 23207c478bd9Sstevel@tonic-gate * board to determine which one is programmed to the lowest 23217c478bd9Sstevel@tonic-gate * physical address, we cannot involve any of the MCs on 23227c478bd9Sstevel@tonic-gate * this board in DR operations. To ensure this, we pretend 23237c478bd9Sstevel@tonic-gate * that this board does not contain any memory. 23247c478bd9Sstevel@tonic-gate * 23257c478bd9Sstevel@tonic-gate * Paranoia: clear the dev_present mask. 23267c478bd9Sstevel@tonic-gate */ 23277c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_MEM, 0)) { 23287c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_ndev != 0); 23297c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_MEM, 0); 23307c478bd9Sstevel@tonic-gate sbp->sb_ndev--; 23317c478bd9Sstevel@tonic-gate } 23327c478bd9Sstevel@tonic-gate 23337c478bd9Sstevel@tonic-gate for (i = 0; i < SBD_NUM_MC_PER_BOARD; i++) { 23347c478bd9Sstevel@tonic-gate mp->sbm_dip[i] = NULL; 23357c478bd9Sstevel@tonic-gate } 23367c478bd9Sstevel@tonic-gate 23377c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 23387c478bd9Sstevel@tonic-gate return; 23397c478bd9Sstevel@tonic-gate } 23407c478bd9Sstevel@tonic-gate 23417c478bd9Sstevel@tonic-gate /* assume this one will win. */ 23427c478bd9Sstevel@tonic-gate devlist[0] = mc_dip; 23437c478bd9Sstevel@tonic-gate mp->sbm_cm.sbdev_dip = mc_dip; 23447c478bd9Sstevel@tonic-gate lowest_pa = mc_pa; 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate /* 23477c478bd9Sstevel@tonic-gate * We know the base physical address of one of the MC devices. Now 23487c478bd9Sstevel@tonic-gate * we will enumerate through all of the remaining MC devices on 23497c478bd9Sstevel@tonic-gate * the board to find which of them is programmed to the lowest 23507c478bd9Sstevel@tonic-gate * physical address. 23517c478bd9Sstevel@tonic-gate */ 23527c478bd9Sstevel@tonic-gate for (i = 1; i < SBD_NUM_MC_PER_BOARD; i++) { 23537c478bd9Sstevel@tonic-gate mc_dip = mp->sbm_dip[i]; 23547c478bd9Sstevel@tonic-gate if (mc_dip == NULL) { 23557c478bd9Sstevel@tonic-gate break; 23567c478bd9Sstevel@tonic-gate } 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate if (sbdphw_get_base_physaddr(hdp, mc_dip, &mc_pa)) { 23597c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "No mem on board %d unit %d", 23607c478bd9Sstevel@tonic-gate sbp->sb_num, i); 23617c478bd9Sstevel@tonic-gate break; 23627c478bd9Sstevel@tonic-gate } 23637c478bd9Sstevel@tonic-gate if (mc_pa < lowest_pa) { 23647c478bd9Sstevel@tonic-gate mp->sbm_cm.sbdev_dip = mc_dip; 23657c478bd9Sstevel@tonic-gate devlist[0] = mc_dip; 23667c478bd9Sstevel@tonic-gate lowest_pa = mc_pa; 23677c478bd9Sstevel@tonic-gate } 23687c478bd9Sstevel@tonic-gate } 23697c478bd9Sstevel@tonic-gate 23707c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 23717c478bd9Sstevel@tonic-gate } 23727c478bd9Sstevel@tonic-gate 23737c478bd9Sstevel@tonic-gate static int 23747c478bd9Sstevel@tonic-gate sbd_name_to_idx(char *name) 23757c478bd9Sstevel@tonic-gate { 23767c478bd9Sstevel@tonic-gate int idx; 23777c478bd9Sstevel@tonic-gate 23787c478bd9Sstevel@tonic-gate for (idx = 0; SBD_COMP(idx) != SBD_COMP_UNKNOWN; idx++) { 23797c478bd9Sstevel@tonic-gate if (strcmp(name, SBD_DEVNAME(idx)) == 0) { 23807c478bd9Sstevel@tonic-gate break; 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate 23847c478bd9Sstevel@tonic-gate return (idx); 23857c478bd9Sstevel@tonic-gate } 23867c478bd9Sstevel@tonic-gate 23877c478bd9Sstevel@tonic-gate static int 23887c478bd9Sstevel@tonic-gate sbd_otype_to_idx(char *otype) 23897c478bd9Sstevel@tonic-gate { 23907c478bd9Sstevel@tonic-gate int idx; 23917c478bd9Sstevel@tonic-gate 23927c478bd9Sstevel@tonic-gate for (idx = 0; SBD_COMP(idx) != SBD_COMP_UNKNOWN; idx++) { 23937c478bd9Sstevel@tonic-gate 23947c478bd9Sstevel@tonic-gate if (strcmp(otype, SBD_OTYPE(idx)) == 0) { 23957c478bd9Sstevel@tonic-gate break; 23967c478bd9Sstevel@tonic-gate } 23977c478bd9Sstevel@tonic-gate } 23987c478bd9Sstevel@tonic-gate 23997c478bd9Sstevel@tonic-gate return (idx); 24007c478bd9Sstevel@tonic-gate } 24017c478bd9Sstevel@tonic-gate 24027c478bd9Sstevel@tonic-gate static int 24037c478bd9Sstevel@tonic-gate sbd_init_devlists(sbd_board_t *sbp) 24047c478bd9Sstevel@tonic-gate { 24057c478bd9Sstevel@tonic-gate int i; 24067c478bd9Sstevel@tonic-gate sbd_dev_unit_t *dp; 24077c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 24087c478bd9Sstevel@tonic-gate walk_tree_t *wp, walk = {0}; 24097c478bd9Sstevel@tonic-gate dev_info_t *pdip; 24107c478bd9Sstevel@tonic-gate static fn_t f = "sbd_init_devlists"; 24117c478bd9Sstevel@tonic-gate 24127c478bd9Sstevel@tonic-gate PR_ALL("%s (board = %d)...\n", f, sbp->sb_num); 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate wp = &walk; 24157c478bd9Sstevel@tonic-gate 24167c478bd9Sstevel@tonic-gate SBD_DEVS_DISCONNECT(sbp, (uint_t)-1); 24177c478bd9Sstevel@tonic-gate 24187c478bd9Sstevel@tonic-gate /* 24197c478bd9Sstevel@tonic-gate * Clear out old entries, if any. 24207c478bd9Sstevel@tonic-gate */ 24217c478bd9Sstevel@tonic-gate 24227c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 24237c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_MEM)][i] = NULL; 24247c478bd9Sstevel@tonic-gate dp = (sbd_dev_unit_t *)SBD_GET_BOARD_MEMUNIT(sbp, i); 24257c478bd9Sstevel@tonic-gate dp->u_common.sbdev_sbp = sbp; 24267c478bd9Sstevel@tonic-gate dp->u_common.sbdev_unum = i; 24277c478bd9Sstevel@tonic-gate dp->u_common.sbdev_type = SBD_COMP_MEM; 24287c478bd9Sstevel@tonic-gate } 24297c478bd9Sstevel@tonic-gate 24307c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, 0); 24317c478bd9Sstevel@tonic-gate ASSERT(mp != NULL); 24327c478bd9Sstevel@tonic-gate for (i = 0; i < SBD_NUM_MC_PER_BOARD; i++) { 24337c478bd9Sstevel@tonic-gate mp->sbm_dip[i] = NULL; 24347c478bd9Sstevel@tonic-gate } 24357c478bd9Sstevel@tonic-gate 24367c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 24377c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_CPU)][i] = NULL; 24387c478bd9Sstevel@tonic-gate dp = (sbd_dev_unit_t *)SBD_GET_BOARD_CPUUNIT(sbp, i); 24397c478bd9Sstevel@tonic-gate dp->u_common.sbdev_sbp = sbp; 24407c478bd9Sstevel@tonic-gate dp->u_common.sbdev_unum = i; 24417c478bd9Sstevel@tonic-gate dp->u_common.sbdev_type = SBD_COMP_CPU; 24427c478bd9Sstevel@tonic-gate } 24437c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 24447c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_IO)][i] = NULL; 24457c478bd9Sstevel@tonic-gate dp = (sbd_dev_unit_t *)SBD_GET_BOARD_IOUNIT(sbp, i); 24467c478bd9Sstevel@tonic-gate dp->u_common.sbdev_sbp = sbp; 24477c478bd9Sstevel@tonic-gate dp->u_common.sbdev_unum = i; 24487c478bd9Sstevel@tonic-gate dp->u_common.sbdev_type = SBD_COMP_IO; 24497c478bd9Sstevel@tonic-gate } 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate wp->sbp = sbp; 24527c478bd9Sstevel@tonic-gate wp->nmc = 0; 24537c478bd9Sstevel@tonic-gate sbp->sb_ndev = 0; 24547c478bd9Sstevel@tonic-gate 24557c478bd9Sstevel@tonic-gate /* 24567c478bd9Sstevel@tonic-gate * ddi_walk_devs() requires that topdip's parent be held. 24577c478bd9Sstevel@tonic-gate */ 24587c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(sbp->sb_topdip); 24597c478bd9Sstevel@tonic-gate if (pdip) { 24607c478bd9Sstevel@tonic-gate ndi_hold_devi(pdip); 24617c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &i); 24627c478bd9Sstevel@tonic-gate } 24637c478bd9Sstevel@tonic-gate ddi_walk_devs(sbp->sb_topdip, sbd_setup_devlists, (void *) wp); 24647c478bd9Sstevel@tonic-gate if (pdip) { 24657c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, i); 24667c478bd9Sstevel@tonic-gate ndi_rele_devi(pdip); 24677c478bd9Sstevel@tonic-gate } 24687c478bd9Sstevel@tonic-gate 24697c478bd9Sstevel@tonic-gate /* 24707c478bd9Sstevel@tonic-gate * There is no point checking all the components if there 24717c478bd9Sstevel@tonic-gate * are no devices. 24727c478bd9Sstevel@tonic-gate */ 24737c478bd9Sstevel@tonic-gate if (sbp->sb_ndev == 0) { 24747c478bd9Sstevel@tonic-gate sbp->sb_memaccess_ok = 0; 24757c478bd9Sstevel@tonic-gate return (sbp->sb_ndev); 24767c478bd9Sstevel@tonic-gate } 24777c478bd9Sstevel@tonic-gate 24787c478bd9Sstevel@tonic-gate /* 24797c478bd9Sstevel@tonic-gate * Initialize cpu sections before calling sbd_init_mem_devlists 24807c478bd9Sstevel@tonic-gate * which will access the mmus. 24817c478bd9Sstevel@tonic-gate */ 24827c478bd9Sstevel@tonic-gate sbp->sb_memaccess_ok = 1; 24837c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 24847c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_CPU, i)) { 24857c478bd9Sstevel@tonic-gate sbd_init_cpu_unit(sbp, i); 24867c478bd9Sstevel@tonic-gate if (sbd_connect_cpu(sbp, i)) { 24877c478bd9Sstevel@tonic-gate SBD_SET_ERR(HD2MACHERR(MACHBD2HD(sbp)), 24887c478bd9Sstevel@tonic-gate ESBD_CPUSTART); 24897c478bd9Sstevel@tonic-gate } 24907c478bd9Sstevel@tonic-gate 24917c478bd9Sstevel@tonic-gate } 24927c478bd9Sstevel@tonic-gate } 24937c478bd9Sstevel@tonic-gate 24947c478bd9Sstevel@tonic-gate if (sbp->sb_memaccess_ok) { 24957c478bd9Sstevel@tonic-gate sbd_init_mem_devlists(sbp); 24967c478bd9Sstevel@tonic-gate } else { 24977c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "unable to access memory on board %d", 24987c478bd9Sstevel@tonic-gate sbp->sb_num); 24997c478bd9Sstevel@tonic-gate } 25007c478bd9Sstevel@tonic-gate 25017c478bd9Sstevel@tonic-gate return (sbp->sb_ndev); 25027c478bd9Sstevel@tonic-gate } 25037c478bd9Sstevel@tonic-gate 25047c478bd9Sstevel@tonic-gate static void 25057c478bd9Sstevel@tonic-gate sbd_init_cpu_unit(sbd_board_t *sbp, int unit) 25067c478bd9Sstevel@tonic-gate { 25077c478bd9Sstevel@tonic-gate sbd_istate_t new_state; 25087c478bd9Sstevel@tonic-gate sbd_cpu_unit_t *cp; 25097c478bd9Sstevel@tonic-gate int cpuid; 25107c478bd9Sstevel@tonic-gate dev_info_t *dip; 25117c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 25127c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 25137c478bd9Sstevel@tonic-gate extern kmutex_t cpu_lock; 25147c478bd9Sstevel@tonic-gate 25157c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_ATTACHED(sbp, SBD_COMP_CPU, unit)) { 25167c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONFIGURED; 25177c478bd9Sstevel@tonic-gate } else if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_CPU, unit)) { 25187c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONNECTED; 25197c478bd9Sstevel@tonic-gate } else { 25207c478bd9Sstevel@tonic-gate new_state = SBD_STATE_EMPTY; 25217c478bd9Sstevel@tonic-gate } 25227c478bd9Sstevel@tonic-gate 25237c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_CPU)][unit]; 25247c478bd9Sstevel@tonic-gate 25257c478bd9Sstevel@tonic-gate cp = SBD_GET_BOARD_CPUUNIT(sbp, unit); 25267c478bd9Sstevel@tonic-gate 25277c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 25287c478bd9Sstevel@tonic-gate 25297c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 25307c478bd9Sstevel@tonic-gate 25317c478bd9Sstevel@tonic-gate cp->sbc_cpu_id = cpuid; 25327c478bd9Sstevel@tonic-gate 25337c478bd9Sstevel@tonic-gate if (&sbdp_cpu_get_impl) 25347c478bd9Sstevel@tonic-gate cp->sbc_cpu_impl = sbdp_cpu_get_impl(hdp, dip); 25357c478bd9Sstevel@tonic-gate else 25367c478bd9Sstevel@tonic-gate cp->sbc_cpu_impl = -1; 25377c478bd9Sstevel@tonic-gate 25387c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 25397c478bd9Sstevel@tonic-gate if ((cpuid >= 0) && cpu[cpuid]) 25407c478bd9Sstevel@tonic-gate cp->sbc_cpu_flags = cpu[cpuid]->cpu_flags; 25417c478bd9Sstevel@tonic-gate else 25427c478bd9Sstevel@tonic-gate cp->sbc_cpu_flags = CPU_OFFLINE | CPU_POWEROFF; 25437c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 25447c478bd9Sstevel@tonic-gate 25457c478bd9Sstevel@tonic-gate sbd_cpu_set_prop(cp, dip); 25467c478bd9Sstevel@tonic-gate 25477c478bd9Sstevel@tonic-gate cp->sbc_cm.sbdev_cond = sbd_get_comp_cond(dip); 25487c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 25497c478bd9Sstevel@tonic-gate 25507c478bd9Sstevel@tonic-gate /* 25517c478bd9Sstevel@tonic-gate * Any changes to the cpu should be performed above 25527c478bd9Sstevel@tonic-gate * this call to ensure the cpu is fully initialized 25537c478bd9Sstevel@tonic-gate * before transitioning to the new state. 25547c478bd9Sstevel@tonic-gate */ 25557c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, unit, new_state); 25567c478bd9Sstevel@tonic-gate } 25577c478bd9Sstevel@tonic-gate 25587c478bd9Sstevel@tonic-gate /* 25597c478bd9Sstevel@tonic-gate * Only do work if called to operate on an entire board 25607c478bd9Sstevel@tonic-gate * which doesn't already have components present. 25617c478bd9Sstevel@tonic-gate */ 25627c478bd9Sstevel@tonic-gate static void 25637c478bd9Sstevel@tonic-gate sbd_connect(sbd_handle_t *hp) 25647c478bd9Sstevel@tonic-gate { 25657c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 25667c478bd9Sstevel@tonic-gate sbderror_t *ep; 25677c478bd9Sstevel@tonic-gate static fn_t f = "sbd_connect"; 25687c478bd9Sstevel@tonic-gate 25697c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate PR_ALL("%s board %d\n", f, sbp->sb_num); 25727c478bd9Sstevel@tonic-gate 25737c478bd9Sstevel@tonic-gate ep = HD2MACHERR(hp); 25747c478bd9Sstevel@tonic-gate 25757c478bd9Sstevel@tonic-gate if (SBD_DEVS_PRESENT(sbp)) { 25767c478bd9Sstevel@tonic-gate /* 25777c478bd9Sstevel@tonic-gate * Board already has devices present. 25787c478bd9Sstevel@tonic-gate */ 25797c478bd9Sstevel@tonic-gate PR_ALL("%s: devices already present (0x%x)\n", 25807c478bd9Sstevel@tonic-gate f, SBD_DEVS_PRESENT(sbp)); 25817c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EINVAL); 25827c478bd9Sstevel@tonic-gate return; 25837c478bd9Sstevel@tonic-gate } 25847c478bd9Sstevel@tonic-gate 25857c478bd9Sstevel@tonic-gate if (sbd_init_devlists(sbp) == 0) { 25867c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: no devices present on board %d", 25877c478bd9Sstevel@tonic-gate f, sbp->sb_num); 25887c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NODEV); 25897c478bd9Sstevel@tonic-gate return; 25907c478bd9Sstevel@tonic-gate } else { 25917c478bd9Sstevel@tonic-gate int i; 25927c478bd9Sstevel@tonic-gate 25937c478bd9Sstevel@tonic-gate /* 25947c478bd9Sstevel@tonic-gate * Initialize mem-unit section of board structure. 25957c478bd9Sstevel@tonic-gate */ 25967c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) 25977c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_MEM, i)) 25987c478bd9Sstevel@tonic-gate sbd_init_mem_unit(sbp, i, SBD_HD2ERR(hp)); 25997c478bd9Sstevel@tonic-gate 26007c478bd9Sstevel@tonic-gate /* 26017c478bd9Sstevel@tonic-gate * Initialize sb_io sections. 26027c478bd9Sstevel@tonic-gate */ 26037c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) 26047c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_IO, i)) 26057c478bd9Sstevel@tonic-gate sbd_init_io_unit(sbp, i); 26067c478bd9Sstevel@tonic-gate 26077c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONNECTED); 26087c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_CONNECTED; 26097c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_UNCONFIGURED; 26107c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 26117c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_CONNECT_BOARD_PSEUDO_ERR, hp->h_err, EIO, 26127c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 26137c478bd9Sstevel@tonic-gate } 26147c478bd9Sstevel@tonic-gate } 26157c478bd9Sstevel@tonic-gate 26167c478bd9Sstevel@tonic-gate static int 26177c478bd9Sstevel@tonic-gate sbd_disconnect(sbd_handle_t *hp) 26187c478bd9Sstevel@tonic-gate { 26197c478bd9Sstevel@tonic-gate int i; 26207c478bd9Sstevel@tonic-gate sbd_devset_t devset; 26217c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 26227c478bd9Sstevel@tonic-gate static fn_t f = "sbd_disconnect it"; 26237c478bd9Sstevel@tonic-gate 26247c478bd9Sstevel@tonic-gate PR_ALL("%s ...\n", f); 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 26277c478bd9Sstevel@tonic-gate 26287c478bd9Sstevel@tonic-gate /* 26297c478bd9Sstevel@tonic-gate * Only devices which are present, but 26307c478bd9Sstevel@tonic-gate * unattached can be disconnected. 26317c478bd9Sstevel@tonic-gate */ 26327c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset & SBD_DEVS_PRESENT(sbp) & 26337c478bd9Sstevel@tonic-gate SBD_DEVS_UNATTACHED(sbp); 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate ASSERT((SBD_DEVS_ATTACHED(sbp) & devset) == 0); 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate /* 26387c478bd9Sstevel@tonic-gate * Update per-device state transitions. 26397c478bd9Sstevel@tonic-gate */ 26407c478bd9Sstevel@tonic-gate 26417c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) 26427c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, i)) { 26437c478bd9Sstevel@tonic-gate if (sbd_disconnect_mem(hp, i) == 0) { 26447c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_MEM, i, 26457c478bd9Sstevel@tonic-gate SBD_STATE_EMPTY); 26467c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_MEM, i); 26477c478bd9Sstevel@tonic-gate } 26487c478bd9Sstevel@tonic-gate } 26497c478bd9Sstevel@tonic-gate 26507c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) 26517c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, i)) { 26527c478bd9Sstevel@tonic-gate if (sbd_disconnect_cpu(hp, i) == 0) { 26537c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, i, 26547c478bd9Sstevel@tonic-gate SBD_STATE_EMPTY); 26557c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_CPU, i); 26567c478bd9Sstevel@tonic-gate } 26577c478bd9Sstevel@tonic-gate } 26587c478bd9Sstevel@tonic-gate 26597c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) 26607c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, i)) { 26617c478bd9Sstevel@tonic-gate if (sbd_disconnect_io(hp, i) == 0) { 26627c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, i, 26637c478bd9Sstevel@tonic-gate SBD_STATE_EMPTY); 26647c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_IO, i); 26657c478bd9Sstevel@tonic-gate } 26667c478bd9Sstevel@tonic-gate } 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate /* 26697c478bd9Sstevel@tonic-gate * Once all the components on a board have been disconnect 26707c478bd9Sstevel@tonic-gate * the board's state can transition to disconnected and 26717c478bd9Sstevel@tonic-gate * we can allow the deprobe to take place. 26727c478bd9Sstevel@tonic-gate */ 26737c478bd9Sstevel@tonic-gate if (SBD_DEVS_PRESENT(sbp) == 0) { 26747c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_OCCUPIED); 26757c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_DISCONNECTED; 26767c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_UNCONFIGURED; 26777c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 26787c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_DISCONNECT_BOARD_PSEUDO_ERR, hp->h_err, EIO, 26797c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 26807c478bd9Sstevel@tonic-gate return (0); 26817c478bd9Sstevel@tonic-gate } else { 26827c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: could not disconnect devices on board %d", 26837c478bd9Sstevel@tonic-gate f, sbp->sb_num); 26847c478bd9Sstevel@tonic-gate return (-1); 26857c478bd9Sstevel@tonic-gate } 26867c478bd9Sstevel@tonic-gate } 26877c478bd9Sstevel@tonic-gate 26887c478bd9Sstevel@tonic-gate static void 26897c478bd9Sstevel@tonic-gate sbd_test_board(sbd_handle_t *hp) 26907c478bd9Sstevel@tonic-gate { 26917c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 26927c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 26937c478bd9Sstevel@tonic-gate 26947c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 26957c478bd9Sstevel@tonic-gate 26967c478bd9Sstevel@tonic-gate PR_ALL("sbd_test_board: board %d\n", sbp->sb_num); 26977c478bd9Sstevel@tonic-gate 26987c478bd9Sstevel@tonic-gate 26997c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 27007c478bd9Sstevel@tonic-gate 27017c478bd9Sstevel@tonic-gate if (sbdp_test_board(hdp, &hp->h_opts) != 0) { 27027c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 27037c478bd9Sstevel@tonic-gate 27047c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 27057c478bd9Sstevel@tonic-gate } 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_TEST_BOARD_PSEUDO_ERR, hp->h_err, EIO, 27087c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 27097c478bd9Sstevel@tonic-gate 27107c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 27117c478bd9Sstevel@tonic-gate } 27127c478bd9Sstevel@tonic-gate 27137c478bd9Sstevel@tonic-gate static void 27147c478bd9Sstevel@tonic-gate sbd_assign_board(sbd_handle_t *hp) 27157c478bd9Sstevel@tonic-gate { 27167c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 27177c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 27187c478bd9Sstevel@tonic-gate 27197c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 27207c478bd9Sstevel@tonic-gate 27217c478bd9Sstevel@tonic-gate PR_ALL("sbd_assign_board: board %d\n", sbp->sb_num); 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 27247c478bd9Sstevel@tonic-gate 27257c478bd9Sstevel@tonic-gate if (sbdp_assign_board(hdp) != 0) { 27267c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 27277c478bd9Sstevel@tonic-gate 27287c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 27297c478bd9Sstevel@tonic-gate } 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_ASSIGN_BOARD_PSEUDO_ERR, hp->h_err, EIO, 27327c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 27337c478bd9Sstevel@tonic-gate 27347c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 27357c478bd9Sstevel@tonic-gate } 27367c478bd9Sstevel@tonic-gate 27377c478bd9Sstevel@tonic-gate static void 27387c478bd9Sstevel@tonic-gate sbd_unassign_board(sbd_handle_t *hp) 27397c478bd9Sstevel@tonic-gate { 27407c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 27417c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 27447c478bd9Sstevel@tonic-gate 27457c478bd9Sstevel@tonic-gate PR_ALL("sbd_unassign_board: board %d\n", sbp->sb_num); 27467c478bd9Sstevel@tonic-gate 27477c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 27487c478bd9Sstevel@tonic-gate 27497c478bd9Sstevel@tonic-gate if (sbdp_unassign_board(hdp) != 0) { 27507c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 27517c478bd9Sstevel@tonic-gate 27527c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 27537c478bd9Sstevel@tonic-gate } 27547c478bd9Sstevel@tonic-gate 27557c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_ASSIGN_BOARD_PSEUDO_ERR, hp->h_err, EIO, 27567c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 27597c478bd9Sstevel@tonic-gate } 27607c478bd9Sstevel@tonic-gate 27617c478bd9Sstevel@tonic-gate static void 27627c478bd9Sstevel@tonic-gate sbd_poweron_board(sbd_handle_t *hp) 27637c478bd9Sstevel@tonic-gate { 27647c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 27657c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 27667c478bd9Sstevel@tonic-gate 27677c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 27687c478bd9Sstevel@tonic-gate 27697c478bd9Sstevel@tonic-gate PR_ALL("sbd_poweron_board: %d\n", sbp->sb_num); 27707c478bd9Sstevel@tonic-gate 27717c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 27727c478bd9Sstevel@tonic-gate 27737c478bd9Sstevel@tonic-gate if (sbdp_poweron_board(hdp) != 0) { 27747c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 27757c478bd9Sstevel@tonic-gate 27767c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 27777c478bd9Sstevel@tonic-gate } 27787c478bd9Sstevel@tonic-gate 27797c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_POWERON_BOARD_PSEUDO_ERR, hp->h_err, EIO, 27807c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 27817c478bd9Sstevel@tonic-gate 27827c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 27837c478bd9Sstevel@tonic-gate } 27847c478bd9Sstevel@tonic-gate 27857c478bd9Sstevel@tonic-gate static void 27867c478bd9Sstevel@tonic-gate sbd_poweroff_board(sbd_handle_t *hp) 27877c478bd9Sstevel@tonic-gate { 27887c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 27897c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 27907c478bd9Sstevel@tonic-gate 27917c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 27927c478bd9Sstevel@tonic-gate 27937c478bd9Sstevel@tonic-gate PR_ALL("sbd_poweroff_board: %d\n", sbp->sb_num); 27947c478bd9Sstevel@tonic-gate 27957c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 27967c478bd9Sstevel@tonic-gate 27977c478bd9Sstevel@tonic-gate if (sbdp_poweroff_board(hdp) != 0) { 27987c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 27997c478bd9Sstevel@tonic-gate 28007c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 28017c478bd9Sstevel@tonic-gate } 28027c478bd9Sstevel@tonic-gate 28037c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_POWEROFF_BOARD_PSEUDO_ERR, hp->h_err, EIO, 28047c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 28057c478bd9Sstevel@tonic-gate 28067c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 28077c478bd9Sstevel@tonic-gate } 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate 28107c478bd9Sstevel@tonic-gate /* 28117c478bd9Sstevel@tonic-gate * Return a list of the dip's of devices that are 28127c478bd9Sstevel@tonic-gate * either present and attached, or present only but 28137c478bd9Sstevel@tonic-gate * not yet attached for the given board. 28147c478bd9Sstevel@tonic-gate */ 28157c478bd9Sstevel@tonic-gate sbd_devlist_t * 28167c478bd9Sstevel@tonic-gate sbd_get_devlist(sbd_handle_t *hp, sbd_board_t *sbp, sbd_comp_type_t nodetype, 28177c478bd9Sstevel@tonic-gate int max_units, uint_t uset, int *count, int present_only) 28187c478bd9Sstevel@tonic-gate { 28197c478bd9Sstevel@tonic-gate int i, ix; 28207c478bd9Sstevel@tonic-gate sbd_devlist_t *ret_devlist; 28217c478bd9Sstevel@tonic-gate dev_info_t **devlist; 28227c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 28237c478bd9Sstevel@tonic-gate 28247c478bd9Sstevel@tonic-gate *count = 0; 28257c478bd9Sstevel@tonic-gate ret_devlist = GETSTRUCT(sbd_devlist_t, max_units); 28267c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(nodetype)]; 28277c478bd9Sstevel@tonic-gate /* 28287c478bd9Sstevel@tonic-gate * Turn into binary value since we're going 28297c478bd9Sstevel@tonic-gate * to be using XOR for a comparison. 28307c478bd9Sstevel@tonic-gate * if (present_only) then 28317c478bd9Sstevel@tonic-gate * dev must be PRESENT, but NOT ATTACHED. 28327c478bd9Sstevel@tonic-gate * else 28337c478bd9Sstevel@tonic-gate * dev must be PRESENT AND ATTACHED. 28347c478bd9Sstevel@tonic-gate * endif 28357c478bd9Sstevel@tonic-gate */ 28367c478bd9Sstevel@tonic-gate if (present_only) 28377c478bd9Sstevel@tonic-gate present_only = 1; 28387c478bd9Sstevel@tonic-gate 28397c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 28407c478bd9Sstevel@tonic-gate 28417c478bd9Sstevel@tonic-gate for (i = ix = 0; (i < max_units) && uset; i++) { 28427c478bd9Sstevel@tonic-gate int ut, is_present, is_attached; 28437c478bd9Sstevel@tonic-gate dev_info_t *dip; 28447c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 28457c478bd9Sstevel@tonic-gate int nunits, distance, j; 28467c478bd9Sstevel@tonic-gate 28477c478bd9Sstevel@tonic-gate /* 28487c478bd9Sstevel@tonic-gate * For CMPs, we would like to perform DR operation on 28497c478bd9Sstevel@tonic-gate * all the cores before moving onto the next chip. 28507c478bd9Sstevel@tonic-gate * Therefore, when constructing the devlist, we process 28517c478bd9Sstevel@tonic-gate * all the cores together. 28527c478bd9Sstevel@tonic-gate */ 28537c478bd9Sstevel@tonic-gate if (nodetype == SBD_COMP_CPU) { 28547c478bd9Sstevel@tonic-gate /* 28557c478bd9Sstevel@tonic-gate * Number of units to process in the inner loop 28567c478bd9Sstevel@tonic-gate */ 28577c478bd9Sstevel@tonic-gate nunits = MAX_CORES_PER_CMP; 28587c478bd9Sstevel@tonic-gate /* 28597c478bd9Sstevel@tonic-gate * The distance between the units in the 28607c478bd9Sstevel@tonic-gate * board's sb_devlist structure. 28617c478bd9Sstevel@tonic-gate */ 28627c478bd9Sstevel@tonic-gate distance = MAX_CMP_UNITS_PER_BOARD; 28637c478bd9Sstevel@tonic-gate } else { 28647c478bd9Sstevel@tonic-gate nunits = 1; 28657c478bd9Sstevel@tonic-gate distance = 0; 28667c478bd9Sstevel@tonic-gate } 28677c478bd9Sstevel@tonic-gate 28687c478bd9Sstevel@tonic-gate for (j = 0; j < nunits; j++) { 28697c478bd9Sstevel@tonic-gate if ((dip = devlist[i + j * distance]) == NULL) 28707c478bd9Sstevel@tonic-gate continue; 28717c478bd9Sstevel@tonic-gate 28727c478bd9Sstevel@tonic-gate ut = sbdp_get_unit_num(hdp, dip); 28737c478bd9Sstevel@tonic-gate 28747c478bd9Sstevel@tonic-gate if (ut == -1) { 28757c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 28767c478bd9Sstevel@tonic-gate PR_ALL("sbd_get_devlist bad unit %d" 28777c478bd9Sstevel@tonic-gate " code %d errno %d", 28787c478bd9Sstevel@tonic-gate i, ep->e_code, ep->e_errno); 28797c478bd9Sstevel@tonic-gate } 28807c478bd9Sstevel@tonic-gate 28817c478bd9Sstevel@tonic-gate if ((uset & (1 << ut)) == 0) 28827c478bd9Sstevel@tonic-gate continue; 28837c478bd9Sstevel@tonic-gate uset &= ~(1 << ut); 28847c478bd9Sstevel@tonic-gate is_present = SBD_DEV_IS_PRESENT(sbp, nodetype, ut) ? 28857c478bd9Sstevel@tonic-gate 1 : 0; 28867c478bd9Sstevel@tonic-gate is_attached = SBD_DEV_IS_ATTACHED(sbp, nodetype, ut) ? 28877c478bd9Sstevel@tonic-gate 1 : 0; 28887c478bd9Sstevel@tonic-gate 28897c478bd9Sstevel@tonic-gate if (is_present && (present_only ^ is_attached)) { 28907c478bd9Sstevel@tonic-gate ret_devlist[ix].dv_dip = dip; 28917c478bd9Sstevel@tonic-gate sbd_init_err(&ret_devlist[ix].dv_error); 28927c478bd9Sstevel@tonic-gate ix++; 28937c478bd9Sstevel@tonic-gate } 28947c478bd9Sstevel@tonic-gate } 28957c478bd9Sstevel@tonic-gate } 28967c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 28977c478bd9Sstevel@tonic-gate 28987c478bd9Sstevel@tonic-gate if ((*count = ix) == 0) { 28997c478bd9Sstevel@tonic-gate FREESTRUCT(ret_devlist, sbd_devlist_t, max_units); 29007c478bd9Sstevel@tonic-gate ret_devlist = NULL; 29017c478bd9Sstevel@tonic-gate } 29027c478bd9Sstevel@tonic-gate 29037c478bd9Sstevel@tonic-gate return (ret_devlist); 29047c478bd9Sstevel@tonic-gate } 29057c478bd9Sstevel@tonic-gate 29067c478bd9Sstevel@tonic-gate static sbd_devlist_t * 29077c478bd9Sstevel@tonic-gate sbd_get_attach_devlist(sbd_handle_t *hp, int32_t *devnump, int32_t pass) 29087c478bd9Sstevel@tonic-gate { 29097c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 29107c478bd9Sstevel@tonic-gate uint_t uset; 29117c478bd9Sstevel@tonic-gate sbd_devset_t devset; 29127c478bd9Sstevel@tonic-gate sbd_devlist_t *attach_devlist; 29137c478bd9Sstevel@tonic-gate static int next_pass = 1; 29147c478bd9Sstevel@tonic-gate static fn_t f = "sbd_get_attach_devlist"; 29157c478bd9Sstevel@tonic-gate 29167c478bd9Sstevel@tonic-gate PR_ALL("%s (pass = %d)...\n", f, pass); 29177c478bd9Sstevel@tonic-gate 29187c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 29197c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset; 29207c478bd9Sstevel@tonic-gate 29217c478bd9Sstevel@tonic-gate *devnump = 0; 29227c478bd9Sstevel@tonic-gate attach_devlist = NULL; 29237c478bd9Sstevel@tonic-gate 29247c478bd9Sstevel@tonic-gate /* 29257c478bd9Sstevel@tonic-gate * We switch on next_pass for the cases where a board 29267c478bd9Sstevel@tonic-gate * does not contain a particular type of component. 29277c478bd9Sstevel@tonic-gate * In these situations we don't want to return NULL 29287c478bd9Sstevel@tonic-gate * prematurely. We need to check other devices and 29297c478bd9Sstevel@tonic-gate * we don't want to check the same type multiple times. 29307c478bd9Sstevel@tonic-gate * For example, if there were no cpus, then on pass 1 29317c478bd9Sstevel@tonic-gate * we would drop through and return the memory nodes. 29327c478bd9Sstevel@tonic-gate * However, on pass 2 we would switch back to the memory 29337c478bd9Sstevel@tonic-gate * nodes thereby returning them twice! Using next_pass 29347c478bd9Sstevel@tonic-gate * forces us down to the end (or next item). 29357c478bd9Sstevel@tonic-gate */ 29367c478bd9Sstevel@tonic-gate if (pass == 1) 29377c478bd9Sstevel@tonic-gate next_pass = 1; 29387c478bd9Sstevel@tonic-gate 29397c478bd9Sstevel@tonic-gate switch (next_pass) { 29407c478bd9Sstevel@tonic-gate case 1: 29417c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) { 29427c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_CPU); 29437c478bd9Sstevel@tonic-gate 29447c478bd9Sstevel@tonic-gate attach_devlist = sbd_get_devlist(hp, sbp, SBD_COMP_CPU, 29457c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD, 29467c478bd9Sstevel@tonic-gate uset, devnump, 1); 29477c478bd9Sstevel@tonic-gate 29487c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_CPU, DEVSET_ANYUNIT); 29497c478bd9Sstevel@tonic-gate if (!devset || attach_devlist) { 29507c478bd9Sstevel@tonic-gate next_pass = 2; 29517c478bd9Sstevel@tonic-gate return (attach_devlist); 29527c478bd9Sstevel@tonic-gate } 29537c478bd9Sstevel@tonic-gate /* 29547c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 29557c478bd9Sstevel@tonic-gate * board, but there aren't any cpus, then just 29567c478bd9Sstevel@tonic-gate * fall through to check for the next component. 29577c478bd9Sstevel@tonic-gate */ 29587c478bd9Sstevel@tonic-gate } 29597c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 29607c478bd9Sstevel@tonic-gate 29617c478bd9Sstevel@tonic-gate case 2: 29627c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) { 29637c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_MEM); 29647c478bd9Sstevel@tonic-gate 29657c478bd9Sstevel@tonic-gate attach_devlist = sbd_get_devlist(hp, sbp, SBD_COMP_MEM, 29667c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD, 29677c478bd9Sstevel@tonic-gate uset, devnump, 1); 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_MEM, DEVSET_ANYUNIT); 29707c478bd9Sstevel@tonic-gate if (!devset || attach_devlist) { 29717c478bd9Sstevel@tonic-gate next_pass = 3; 29727c478bd9Sstevel@tonic-gate return (attach_devlist); 29737c478bd9Sstevel@tonic-gate } 29747c478bd9Sstevel@tonic-gate /* 29757c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 29767c478bd9Sstevel@tonic-gate * board, but there isn't any memory, then 29777c478bd9Sstevel@tonic-gate * just fall through to next component. 29787c478bd9Sstevel@tonic-gate */ 29797c478bd9Sstevel@tonic-gate } 29807c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 29817c478bd9Sstevel@tonic-gate 29827c478bd9Sstevel@tonic-gate 29837c478bd9Sstevel@tonic-gate case 3: 29847c478bd9Sstevel@tonic-gate next_pass = -1; 29857c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) { 29867c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_IO); 29877c478bd9Sstevel@tonic-gate 29887c478bd9Sstevel@tonic-gate attach_devlist = sbd_get_devlist(hp, sbp, SBD_COMP_IO, 29897c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD, 29907c478bd9Sstevel@tonic-gate uset, devnump, 1); 29917c478bd9Sstevel@tonic-gate 29927c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_IO, DEVSET_ANYUNIT); 29937c478bd9Sstevel@tonic-gate if (!devset || attach_devlist) { 29947c478bd9Sstevel@tonic-gate next_pass = 4; 29957c478bd9Sstevel@tonic-gate return (attach_devlist); 29967c478bd9Sstevel@tonic-gate } 29977c478bd9Sstevel@tonic-gate } 29987c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 29997c478bd9Sstevel@tonic-gate 30007c478bd9Sstevel@tonic-gate default: 30017c478bd9Sstevel@tonic-gate *devnump = 0; 30027c478bd9Sstevel@tonic-gate return (NULL); 30037c478bd9Sstevel@tonic-gate } 30047c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 30057c478bd9Sstevel@tonic-gate } 30067c478bd9Sstevel@tonic-gate 30077c478bd9Sstevel@tonic-gate static int 30087c478bd9Sstevel@tonic-gate sbd_pre_attach_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 30097c478bd9Sstevel@tonic-gate int32_t devnum) 30107c478bd9Sstevel@tonic-gate { 30117c478bd9Sstevel@tonic-gate int max_units = 0, rv = 0; 30127c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 30137c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_attach_devlist"; 30147c478bd9Sstevel@tonic-gate 30157c478bd9Sstevel@tonic-gate /* 30167c478bd9Sstevel@tonic-gate * In this driver, all entries in a devlist[] are 30177c478bd9Sstevel@tonic-gate * of the same nodetype. 30187c478bd9Sstevel@tonic-gate */ 30197c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 30207c478bd9Sstevel@tonic-gate 30217c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 30227c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 30237c478bd9Sstevel@tonic-gate 30247c478bd9Sstevel@tonic-gate switch (nodetype) { 30257c478bd9Sstevel@tonic-gate 30267c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 30277c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 30287c478bd9Sstevel@tonic-gate rv = sbd_pre_attach_mem(hp, devlist, devnum); 30297c478bd9Sstevel@tonic-gate break; 30307c478bd9Sstevel@tonic-gate 30317c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 30327c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 30337c478bd9Sstevel@tonic-gate rv = sbd_pre_attach_cpu(hp, devlist, devnum); 30347c478bd9Sstevel@tonic-gate break; 30357c478bd9Sstevel@tonic-gate 30367c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 30377c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 30387c478bd9Sstevel@tonic-gate break; 30397c478bd9Sstevel@tonic-gate 30407c478bd9Sstevel@tonic-gate default: 30417c478bd9Sstevel@tonic-gate rv = -1; 30427c478bd9Sstevel@tonic-gate break; 30437c478bd9Sstevel@tonic-gate } 30447c478bd9Sstevel@tonic-gate 30457c478bd9Sstevel@tonic-gate if (rv && max_units) { 30467c478bd9Sstevel@tonic-gate int i; 30477c478bd9Sstevel@tonic-gate /* 30487c478bd9Sstevel@tonic-gate * Need to clean up devlist 30497c478bd9Sstevel@tonic-gate * if pre-op is going to fail. 30507c478bd9Sstevel@tonic-gate */ 30517c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 30527c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 30537c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 30547c478bd9Sstevel@tonic-gate } else { 30557c478bd9Sstevel@tonic-gate break; 30567c478bd9Sstevel@tonic-gate } 30577c478bd9Sstevel@tonic-gate } 30587c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 30597c478bd9Sstevel@tonic-gate } 30607c478bd9Sstevel@tonic-gate 30617c478bd9Sstevel@tonic-gate /* 30627c478bd9Sstevel@tonic-gate * If an error occurred, return "continue" 30637c478bd9Sstevel@tonic-gate * indication so that we can continue attaching 30647c478bd9Sstevel@tonic-gate * as much as possible. 30657c478bd9Sstevel@tonic-gate */ 30667c478bd9Sstevel@tonic-gate return (rv ? -1 : 0); 30677c478bd9Sstevel@tonic-gate } 30687c478bd9Sstevel@tonic-gate 30697c478bd9Sstevel@tonic-gate static int 30707c478bd9Sstevel@tonic-gate sbd_post_attach_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 30717c478bd9Sstevel@tonic-gate int32_t devnum) 30727c478bd9Sstevel@tonic-gate { 30737c478bd9Sstevel@tonic-gate int i, max_units = 0, rv = 0; 30747c478bd9Sstevel@tonic-gate sbd_devset_t devs_unattached, devs_present; 30757c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 30767c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 30777c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 30787c478bd9Sstevel@tonic-gate static fn_t f = "sbd_post_attach_devlist"; 30797c478bd9Sstevel@tonic-gate 30807c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 30817c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 30827c478bd9Sstevel@tonic-gate 30837c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 30847c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 30857c478bd9Sstevel@tonic-gate 30867c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 30877c478bd9Sstevel@tonic-gate 30887c478bd9Sstevel@tonic-gate /* 30897c478bd9Sstevel@tonic-gate * Need to free up devlist[] created earlier in 30907c478bd9Sstevel@tonic-gate * sbd_get_attach_devlist(). 30917c478bd9Sstevel@tonic-gate */ 30927c478bd9Sstevel@tonic-gate switch (nodetype) { 30937c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 30947c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 30957c478bd9Sstevel@tonic-gate rv = sbd_post_attach_cpu(hp, devlist, devnum); 30967c478bd9Sstevel@tonic-gate break; 30977c478bd9Sstevel@tonic-gate 30987c478bd9Sstevel@tonic-gate 30997c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 31007c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 31017c478bd9Sstevel@tonic-gate 31027c478bd9Sstevel@tonic-gate rv = sbd_post_attach_mem(hp, devlist, devnum); 31037c478bd9Sstevel@tonic-gate break; 31047c478bd9Sstevel@tonic-gate 31057c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 31067c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 31077c478bd9Sstevel@tonic-gate break; 31087c478bd9Sstevel@tonic-gate 31097c478bd9Sstevel@tonic-gate default: 31107c478bd9Sstevel@tonic-gate rv = -1; 31117c478bd9Sstevel@tonic-gate break; 31127c478bd9Sstevel@tonic-gate } 31137c478bd9Sstevel@tonic-gate 31147c478bd9Sstevel@tonic-gate 31157c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 31167c478bd9Sstevel@tonic-gate int unit; 31177c478bd9Sstevel@tonic-gate dev_info_t *dip; 31187c478bd9Sstevel@tonic-gate sbderror_t *ep; 31197c478bd9Sstevel@tonic-gate 31207c478bd9Sstevel@tonic-gate ep = &devlist[i].dv_error; 31217c478bd9Sstevel@tonic-gate 31227c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) 31237c478bd9Sstevel@tonic-gate continue; 31247c478bd9Sstevel@tonic-gate 31257c478bd9Sstevel@tonic-gate dip = devlist[i].dv_dip; 31267c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 31277c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 31287c478bd9Sstevel@tonic-gate 31297c478bd9Sstevel@tonic-gate if (unit == -1) { 31307c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 31317c478bd9Sstevel@tonic-gate continue; 31327c478bd9Sstevel@tonic-gate } 31337c478bd9Sstevel@tonic-gate 31347c478bd9Sstevel@tonic-gate unit = sbd_check_unit_attached(sbp, dip, unit, nodetype, ep); 31357c478bd9Sstevel@tonic-gate 31367c478bd9Sstevel@tonic-gate if (unit == -1) { 31377c478bd9Sstevel@tonic-gate PR_ALL("%s: ERROR (nt=%s, b=%d, u=%d) not attached\n", 31387c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], sbp->sb_num, i); 31397c478bd9Sstevel@tonic-gate continue; 31407c478bd9Sstevel@tonic-gate } 31417c478bd9Sstevel@tonic-gate 31427c478bd9Sstevel@tonic-gate SBD_DEV_SET_ATTACHED(sbp, nodetype, unit); 31437c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, nodetype, unit, 31447c478bd9Sstevel@tonic-gate SBD_STATE_CONFIGURED); 31457c478bd9Sstevel@tonic-gate } 31467c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 31477c478bd9Sstevel@tonic-gate 31487c478bd9Sstevel@tonic-gate if (rv) { 31497c478bd9Sstevel@tonic-gate PR_ALL("%s: errno %d, ecode %d during attach\n", 31507c478bd9Sstevel@tonic-gate f, SBD_GET_ERRNO(SBD_HD2ERR(hp)), 31517c478bd9Sstevel@tonic-gate SBD_GET_ERR(HD2MACHERR(hp))); 31527c478bd9Sstevel@tonic-gate } 31537c478bd9Sstevel@tonic-gate 31547c478bd9Sstevel@tonic-gate devs_present = SBD_DEVS_PRESENT(sbp); 31557c478bd9Sstevel@tonic-gate devs_unattached = SBD_DEVS_UNATTACHED(sbp); 31567c478bd9Sstevel@tonic-gate 31577c478bd9Sstevel@tonic-gate switch (SBD_BOARD_STATE(sbp)) { 31587c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 31597c478bd9Sstevel@tonic-gate case SBD_STATE_UNCONFIGURED: 31607c478bd9Sstevel@tonic-gate ASSERT(devs_present); 31617c478bd9Sstevel@tonic-gate 31627c478bd9Sstevel@tonic-gate if (devs_unattached == 0) { 31637c478bd9Sstevel@tonic-gate /* 31647c478bd9Sstevel@tonic-gate * All devices finally attached. 31657c478bd9Sstevel@tonic-gate */ 31667c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONFIGURED); 31677c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_CONNECTED; 31687c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_CONFIGURED; 31697c478bd9Sstevel@tonic-gate } else if (devs_present != devs_unattached) { 31707c478bd9Sstevel@tonic-gate /* 31717c478bd9Sstevel@tonic-gate * Only some devices are fully attached. 31727c478bd9Sstevel@tonic-gate */ 31737c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_PARTIAL); 31747c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_CONNECTED; 31757c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_UNCONFIGURED; 31767c478bd9Sstevel@tonic-gate } 31777c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 31787c478bd9Sstevel@tonic-gate break; 31797c478bd9Sstevel@tonic-gate 31807c478bd9Sstevel@tonic-gate case SBD_STATE_PARTIAL: 31817c478bd9Sstevel@tonic-gate ASSERT(devs_present); 31827c478bd9Sstevel@tonic-gate /* 31837c478bd9Sstevel@tonic-gate * All devices finally attached. 31847c478bd9Sstevel@tonic-gate */ 31857c478bd9Sstevel@tonic-gate if (devs_unattached == 0) { 31867c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONFIGURED); 31877c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_CONNECTED; 31887c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_CONFIGURED; 31897c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 31907c478bd9Sstevel@tonic-gate } 31917c478bd9Sstevel@tonic-gate break; 31927c478bd9Sstevel@tonic-gate 31937c478bd9Sstevel@tonic-gate default: 31947c478bd9Sstevel@tonic-gate break; 31957c478bd9Sstevel@tonic-gate } 31967c478bd9Sstevel@tonic-gate 31977c478bd9Sstevel@tonic-gate if (max_units && devlist) { 31987c478bd9Sstevel@tonic-gate int i; 31997c478bd9Sstevel@tonic-gate 32007c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 32017c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 32027c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 32037c478bd9Sstevel@tonic-gate } else { 32047c478bd9Sstevel@tonic-gate break; 32057c478bd9Sstevel@tonic-gate } 32067c478bd9Sstevel@tonic-gate } 32077c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 32087c478bd9Sstevel@tonic-gate } 32097c478bd9Sstevel@tonic-gate 32107c478bd9Sstevel@tonic-gate /* 32117c478bd9Sstevel@tonic-gate * Our policy is to attach all components that are 32127c478bd9Sstevel@tonic-gate * possible, thus we always return "success" on the 32137c478bd9Sstevel@tonic-gate * pre and post operations. 32147c478bd9Sstevel@tonic-gate */ 32157c478bd9Sstevel@tonic-gate return (0); 32167c478bd9Sstevel@tonic-gate } 32177c478bd9Sstevel@tonic-gate 32187c478bd9Sstevel@tonic-gate /* 32197c478bd9Sstevel@tonic-gate * We only need to "release" cpu and memory devices. 32207c478bd9Sstevel@tonic-gate */ 32217c478bd9Sstevel@tonic-gate static sbd_devlist_t * 32227c478bd9Sstevel@tonic-gate sbd_get_release_devlist(sbd_handle_t *hp, int32_t *devnump, int32_t pass) 32237c478bd9Sstevel@tonic-gate { 32247c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 32257c478bd9Sstevel@tonic-gate uint_t uset; 32267c478bd9Sstevel@tonic-gate sbd_devset_t devset; 32277c478bd9Sstevel@tonic-gate sbd_devlist_t *release_devlist; 32287c478bd9Sstevel@tonic-gate static int next_pass = 1; 32297c478bd9Sstevel@tonic-gate static fn_t f = "sbd_get_release_devlist"; 32307c478bd9Sstevel@tonic-gate 32317c478bd9Sstevel@tonic-gate PR_ALL("%s (pass = %d)...\n", f, pass); 32327c478bd9Sstevel@tonic-gate 32337c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 32347c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset; 32357c478bd9Sstevel@tonic-gate 32367c478bd9Sstevel@tonic-gate *devnump = 0; 32377c478bd9Sstevel@tonic-gate release_devlist = NULL; 32387c478bd9Sstevel@tonic-gate 32397c478bd9Sstevel@tonic-gate /* 32407c478bd9Sstevel@tonic-gate * We switch on next_pass for the cases where a board 32417c478bd9Sstevel@tonic-gate * does not contain a particular type of component. 32427c478bd9Sstevel@tonic-gate * In these situations we don't want to return NULL 32437c478bd9Sstevel@tonic-gate * prematurely. We need to check other devices and 32447c478bd9Sstevel@tonic-gate * we don't want to check the same type multiple times. 32457c478bd9Sstevel@tonic-gate * For example, if there were no cpus, then on pass 1 32467c478bd9Sstevel@tonic-gate * we would drop through and return the memory nodes. 32477c478bd9Sstevel@tonic-gate * However, on pass 2 we would switch back to the memory 32487c478bd9Sstevel@tonic-gate * nodes thereby returning them twice! Using next_pass 32497c478bd9Sstevel@tonic-gate * forces us down to the end (or next item). 32507c478bd9Sstevel@tonic-gate */ 32517c478bd9Sstevel@tonic-gate if (pass == 1) 32527c478bd9Sstevel@tonic-gate next_pass = 1; 32537c478bd9Sstevel@tonic-gate 32547c478bd9Sstevel@tonic-gate switch (next_pass) { 32557c478bd9Sstevel@tonic-gate case 1: 32567c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) { 32577c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_MEM); 32587c478bd9Sstevel@tonic-gate 32597c478bd9Sstevel@tonic-gate release_devlist = sbd_get_devlist(hp, sbp, 32607c478bd9Sstevel@tonic-gate SBD_COMP_MEM, 32617c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD, 32627c478bd9Sstevel@tonic-gate uset, devnump, 0); 32637c478bd9Sstevel@tonic-gate 32647c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_MEM, DEVSET_ANYUNIT); 32657c478bd9Sstevel@tonic-gate if (!devset || release_devlist) { 32667c478bd9Sstevel@tonic-gate next_pass = 2; 32677c478bd9Sstevel@tonic-gate return (release_devlist); 32687c478bd9Sstevel@tonic-gate } 32697c478bd9Sstevel@tonic-gate /* 32707c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 32717c478bd9Sstevel@tonic-gate * board, but there isn't any memory, then 32727c478bd9Sstevel@tonic-gate * just fall through to next component. 32737c478bd9Sstevel@tonic-gate */ 32747c478bd9Sstevel@tonic-gate } 32757c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 32767c478bd9Sstevel@tonic-gate 32777c478bd9Sstevel@tonic-gate 32787c478bd9Sstevel@tonic-gate case 2: 32797c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) { 32807c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_CPU); 32817c478bd9Sstevel@tonic-gate 32827c478bd9Sstevel@tonic-gate release_devlist = sbd_get_devlist(hp, sbp, 32837c478bd9Sstevel@tonic-gate SBD_COMP_CPU, 32847c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD, 32857c478bd9Sstevel@tonic-gate uset, devnump, 0); 32867c478bd9Sstevel@tonic-gate 32877c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_CPU, DEVSET_ANYUNIT); 32887c478bd9Sstevel@tonic-gate if (!devset || release_devlist) { 32897c478bd9Sstevel@tonic-gate next_pass = 3; 32907c478bd9Sstevel@tonic-gate return (release_devlist); 32917c478bd9Sstevel@tonic-gate } 32927c478bd9Sstevel@tonic-gate /* 32937c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 32947c478bd9Sstevel@tonic-gate * board, but there aren't any cpus, then just 32957c478bd9Sstevel@tonic-gate * fall through to check for the next component. 32967c478bd9Sstevel@tonic-gate */ 32977c478bd9Sstevel@tonic-gate } 32987c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 32997c478bd9Sstevel@tonic-gate 33007c478bd9Sstevel@tonic-gate 33017c478bd9Sstevel@tonic-gate case 3: 33027c478bd9Sstevel@tonic-gate next_pass = -1; 33037c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) { 33047c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_IO); 33057c478bd9Sstevel@tonic-gate 33067c478bd9Sstevel@tonic-gate release_devlist = sbd_get_devlist(hp, sbp, 33077c478bd9Sstevel@tonic-gate SBD_COMP_IO, 33087c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD, 33097c478bd9Sstevel@tonic-gate uset, devnump, 0); 33107c478bd9Sstevel@tonic-gate 33117c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_IO, DEVSET_ANYUNIT); 33127c478bd9Sstevel@tonic-gate if (!devset || release_devlist) { 33137c478bd9Sstevel@tonic-gate next_pass = 4; 33147c478bd9Sstevel@tonic-gate return (release_devlist); 33157c478bd9Sstevel@tonic-gate } 33167c478bd9Sstevel@tonic-gate } 33177c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 33187c478bd9Sstevel@tonic-gate 33197c478bd9Sstevel@tonic-gate default: 33207c478bd9Sstevel@tonic-gate *devnump = 0; 33217c478bd9Sstevel@tonic-gate return (NULL); 33227c478bd9Sstevel@tonic-gate } 33237c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 33247c478bd9Sstevel@tonic-gate } 33257c478bd9Sstevel@tonic-gate 33267c478bd9Sstevel@tonic-gate static int 33277c478bd9Sstevel@tonic-gate sbd_pre_release_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 33287c478bd9Sstevel@tonic-gate int32_t devnum) 33297c478bd9Sstevel@tonic-gate { 33307c478bd9Sstevel@tonic-gate int max_units = 0, rv = 0; 33317c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 33327c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_release_devlist"; 33337c478bd9Sstevel@tonic-gate 33347c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 33377c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 33387c478bd9Sstevel@tonic-gate 33397c478bd9Sstevel@tonic-gate switch (nodetype) { 33407c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: { 33417c478bd9Sstevel@tonic-gate int i, mem_present = 0; 33427c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 33437c478bd9Sstevel@tonic-gate sbd_devset_t devset; 33447c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 33457c478bd9Sstevel@tonic-gate 33467c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 33477c478bd9Sstevel@tonic-gate 33487c478bd9Sstevel@tonic-gate devset = shp->sh_orig_devset; 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 33517c478bd9Sstevel@tonic-gate /* 33527c478bd9Sstevel@tonic-gate * if client also requested to unconfigure memory 33537c478bd9Sstevel@tonic-gate * the we allow the operation. Therefore 33547c478bd9Sstevel@tonic-gate * we need to warranty that memory gets unconfig 33557c478bd9Sstevel@tonic-gate * before cpus 33567c478bd9Sstevel@tonic-gate */ 33577c478bd9Sstevel@tonic-gate 33587c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, i)) { 33597c478bd9Sstevel@tonic-gate continue; 33607c478bd9Sstevel@tonic-gate } 33617c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_ATTACHED(sbp, SBD_COMP_MEM, i)) { 33627c478bd9Sstevel@tonic-gate mem_present = 1; 33637c478bd9Sstevel@tonic-gate break; 33647c478bd9Sstevel@tonic-gate } 33657c478bd9Sstevel@tonic-gate } 33667c478bd9Sstevel@tonic-gate if (mem_present) { 33677c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 33687c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_MEMONLINE); 33697c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_mempath[i]); 33707c478bd9Sstevel@tonic-gate rv = -1; 33717c478bd9Sstevel@tonic-gate } else { 33727c478bd9Sstevel@tonic-gate rv = sbd_pre_release_cpu(hp, devlist, devnum); 33737c478bd9Sstevel@tonic-gate } 33747c478bd9Sstevel@tonic-gate 33757c478bd9Sstevel@tonic-gate break; 33767c478bd9Sstevel@tonic-gate 33777c478bd9Sstevel@tonic-gate } 33787c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 33797c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 33807c478bd9Sstevel@tonic-gate rv = sbd_pre_release_mem(hp, devlist, devnum); 33817c478bd9Sstevel@tonic-gate break; 33827c478bd9Sstevel@tonic-gate 33837c478bd9Sstevel@tonic-gate 33847c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 33857c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 33867c478bd9Sstevel@tonic-gate rv = sbd_pre_release_io(hp, devlist, devnum); 33877c478bd9Sstevel@tonic-gate break; 33887c478bd9Sstevel@tonic-gate 33897c478bd9Sstevel@tonic-gate default: 33907c478bd9Sstevel@tonic-gate rv = -1; 33917c478bd9Sstevel@tonic-gate break; 33927c478bd9Sstevel@tonic-gate } 33937c478bd9Sstevel@tonic-gate 33947c478bd9Sstevel@tonic-gate if (rv && max_units) { 33957c478bd9Sstevel@tonic-gate int i; 33967c478bd9Sstevel@tonic-gate 33977c478bd9Sstevel@tonic-gate /* 33987c478bd9Sstevel@tonic-gate * the individual pre_release component routines should 33997c478bd9Sstevel@tonic-gate * have set the error in the handle. No need to set it 34007c478bd9Sstevel@tonic-gate * here 34017c478bd9Sstevel@tonic-gate * 34027c478bd9Sstevel@tonic-gate * Need to clean up dynamically allocated devlist 34037c478bd9Sstevel@tonic-gate * if pre-op is going to fail. 34047c478bd9Sstevel@tonic-gate */ 34057c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 34067c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 34077c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 34087c478bd9Sstevel@tonic-gate } else { 34097c478bd9Sstevel@tonic-gate break; 34107c478bd9Sstevel@tonic-gate } 34117c478bd9Sstevel@tonic-gate } 34127c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 34137c478bd9Sstevel@tonic-gate } 34147c478bd9Sstevel@tonic-gate 34157c478bd9Sstevel@tonic-gate return (rv ? -1 : 0); 34167c478bd9Sstevel@tonic-gate } 34177c478bd9Sstevel@tonic-gate 34187c478bd9Sstevel@tonic-gate static int 34197c478bd9Sstevel@tonic-gate sbd_post_release_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 34207c478bd9Sstevel@tonic-gate int32_t devnum) 34217c478bd9Sstevel@tonic-gate { 34227c478bd9Sstevel@tonic-gate int i, max_units = 0; 34237c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 34247c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 34257c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 34267c478bd9Sstevel@tonic-gate sbd_error_t *spe; 34277c478bd9Sstevel@tonic-gate static fn_t f = "sbd_post_release_devlist"; 34287c478bd9Sstevel@tonic-gate 34297c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 34307c478bd9Sstevel@tonic-gate ASSERT(nodetype >= SBD_COMP_CPU && nodetype <= SBD_COMP_IO); 34317c478bd9Sstevel@tonic-gate 34327c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 34337c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 34347c478bd9Sstevel@tonic-gate 34357c478bd9Sstevel@tonic-gate /* 34367c478bd9Sstevel@tonic-gate * Need to free up devlist[] created earlier in 34377c478bd9Sstevel@tonic-gate * sbd_get_release_devlist(). 34387c478bd9Sstevel@tonic-gate */ 34397c478bd9Sstevel@tonic-gate switch (nodetype) { 34407c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 34417c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 34427c478bd9Sstevel@tonic-gate break; 34437c478bd9Sstevel@tonic-gate 34447c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 34457c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 34467c478bd9Sstevel@tonic-gate break; 34477c478bd9Sstevel@tonic-gate 34487c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 34497c478bd9Sstevel@tonic-gate /* 34507c478bd9Sstevel@tonic-gate * Need to check if specific I/O is referenced and 34517c478bd9Sstevel@tonic-gate * fail post-op. 34527c478bd9Sstevel@tonic-gate */ 34537c478bd9Sstevel@tonic-gate 34547c478bd9Sstevel@tonic-gate if (sbd_check_io_refs(hp, devlist, devnum) > 0) { 34557c478bd9Sstevel@tonic-gate PR_IO("%s: error - I/O devices ref'd\n", f); 34567c478bd9Sstevel@tonic-gate } 34577c478bd9Sstevel@tonic-gate 34587c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 34597c478bd9Sstevel@tonic-gate break; 34607c478bd9Sstevel@tonic-gate 34617c478bd9Sstevel@tonic-gate default: 34627c478bd9Sstevel@tonic-gate { 34637c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: invalid nodetype (%d)", 34647c478bd9Sstevel@tonic-gate f, (int)nodetype); 34657c478bd9Sstevel@tonic-gate SBD_SET_ERR(HD2MACHERR(hp), ESBD_INVAL); 34667c478bd9Sstevel@tonic-gate } 34677c478bd9Sstevel@tonic-gate break; 34687c478bd9Sstevel@tonic-gate } 34697c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 34707c478bd9Sstevel@tonic-gate spe = hdp->h_err; 34717c478bd9Sstevel@tonic-gate 34727c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 34737c478bd9Sstevel@tonic-gate int unit; 34747c478bd9Sstevel@tonic-gate sbderror_t *ep; 34757c478bd9Sstevel@tonic-gate 34767c478bd9Sstevel@tonic-gate ep = &devlist[i].dv_error; 34777c478bd9Sstevel@tonic-gate 34787c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) { 34797c478bd9Sstevel@tonic-gate continue; 34807c478bd9Sstevel@tonic-gate } 34817c478bd9Sstevel@tonic-gate 34827c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, devlist[i].dv_dip); 34837c478bd9Sstevel@tonic-gate if (unit == -1) { 34847c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 34857c478bd9Sstevel@tonic-gate PR_ALL("%s bad unit num: %d code %d", 34867c478bd9Sstevel@tonic-gate f, unit, spe->e_code); 34877c478bd9Sstevel@tonic-gate continue; 34887c478bd9Sstevel@tonic-gate } 34897c478bd9Sstevel@tonic-gate } 34907c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 34917c478bd9Sstevel@tonic-gate 34927c478bd9Sstevel@tonic-gate if (SBD_GET_ERRNO(SBD_HD2ERR(hp))) { 34937c478bd9Sstevel@tonic-gate PR_ALL("%s: errno %d, ecode %d during release\n", 34947c478bd9Sstevel@tonic-gate f, SBD_GET_ERRNO(SBD_HD2ERR(hp)), 34957c478bd9Sstevel@tonic-gate SBD_GET_ERR(SBD_HD2ERR(hp))); 34967c478bd9Sstevel@tonic-gate } 34977c478bd9Sstevel@tonic-gate 34987c478bd9Sstevel@tonic-gate if (max_units && devlist) { 34997c478bd9Sstevel@tonic-gate int i; 35007c478bd9Sstevel@tonic-gate 35017c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 35027c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 35037c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 35047c478bd9Sstevel@tonic-gate } else { 35057c478bd9Sstevel@tonic-gate break; 35067c478bd9Sstevel@tonic-gate } 35077c478bd9Sstevel@tonic-gate } 35087c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 35097c478bd9Sstevel@tonic-gate } 35107c478bd9Sstevel@tonic-gate 35117c478bd9Sstevel@tonic-gate return (SBD_GET_ERRNO(SBD_HD2ERR(hp)) ? -1 : 0); 35127c478bd9Sstevel@tonic-gate } 35137c478bd9Sstevel@tonic-gate 35147c478bd9Sstevel@tonic-gate static void 35157c478bd9Sstevel@tonic-gate sbd_release_dev_done(sbd_board_t *sbp, sbd_comp_type_t nodetype, int unit) 35167c478bd9Sstevel@tonic-gate { 35177c478bd9Sstevel@tonic-gate SBD_DEV_SET_UNREFERENCED(sbp, nodetype, unit); 35187c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, nodetype, unit, SBD_STATE_UNREFERENCED); 35197c478bd9Sstevel@tonic-gate } 35207c478bd9Sstevel@tonic-gate 35217c478bd9Sstevel@tonic-gate static void 35227c478bd9Sstevel@tonic-gate sbd_release_done(sbd_handle_t *hp, sbd_comp_type_t nodetype, dev_info_t *dip) 35237c478bd9Sstevel@tonic-gate { 35247c478bd9Sstevel@tonic-gate int unit; 35257c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 35267c478bd9Sstevel@tonic-gate sbderror_t *ep; 35277c478bd9Sstevel@tonic-gate static fn_t f = "sbd_release_done"; 35287c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 35297c478bd9Sstevel@tonic-gate 35307c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 35317c478bd9Sstevel@tonic-gate 35327c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 35337c478bd9Sstevel@tonic-gate ep = SBD_HD2ERR(hp); 35347c478bd9Sstevel@tonic-gate 35357c478bd9Sstevel@tonic-gate if ((unit = sbdp_get_unit_num(hdp, dip)) < 0) { 35367c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 35377c478bd9Sstevel@tonic-gate "sbd:%s: unable to get unit for dip (0x%p)", 35387c478bd9Sstevel@tonic-gate f, (void *)dip); 35397c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 35407c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 35417c478bd9Sstevel@tonic-gate return; 35427c478bd9Sstevel@tonic-gate } 35437c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 35447c478bd9Sstevel@tonic-gate 35457c478bd9Sstevel@tonic-gate /* 35467c478bd9Sstevel@tonic-gate * Transfer the device which just completed its release 35477c478bd9Sstevel@tonic-gate * to the UNREFERENCED state. 35487c478bd9Sstevel@tonic-gate */ 35497c478bd9Sstevel@tonic-gate switch (nodetype) { 35507c478bd9Sstevel@tonic-gate 35517c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 35527c478bd9Sstevel@tonic-gate sbd_release_mem_done((void *)hp, unit); 35537c478bd9Sstevel@tonic-gate break; 35547c478bd9Sstevel@tonic-gate 35557c478bd9Sstevel@tonic-gate default: 35567c478bd9Sstevel@tonic-gate sbd_release_dev_done(sbp, nodetype, unit); 35577c478bd9Sstevel@tonic-gate break; 35587c478bd9Sstevel@tonic-gate } 35597c478bd9Sstevel@tonic-gate 35607c478bd9Sstevel@tonic-gate /* 35617c478bd9Sstevel@tonic-gate * If the entire board was released and all components 35627c478bd9Sstevel@tonic-gate * unreferenced then transfer it to the UNREFERENCED state. 35637c478bd9Sstevel@tonic-gate */ 35647c478bd9Sstevel@tonic-gate if (SBD_DEVS_RELEASED(sbp) == SBD_DEVS_UNREFERENCED(sbp)) { 35657c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_UNREFERENCED); 35667c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 35677c478bd9Sstevel@tonic-gate } 35687c478bd9Sstevel@tonic-gate } 35697c478bd9Sstevel@tonic-gate 35707c478bd9Sstevel@tonic-gate static sbd_devlist_t * 35717c478bd9Sstevel@tonic-gate sbd_get_detach_devlist(sbd_handle_t *hp, int32_t *devnump, int32_t pass) 35727c478bd9Sstevel@tonic-gate { 35737c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 35747c478bd9Sstevel@tonic-gate uint_t uset; 35757c478bd9Sstevel@tonic-gate sbd_devset_t devset; 35767c478bd9Sstevel@tonic-gate sbd_devlist_t *detach_devlist; 35777c478bd9Sstevel@tonic-gate static int next_pass = 1; 35787c478bd9Sstevel@tonic-gate static fn_t f = "sbd_get_detach_devlist"; 35797c478bd9Sstevel@tonic-gate 35807c478bd9Sstevel@tonic-gate PR_ALL("%s (pass = %d)...\n", f, pass); 35817c478bd9Sstevel@tonic-gate 35827c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 35837c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset; 35847c478bd9Sstevel@tonic-gate 35857c478bd9Sstevel@tonic-gate *devnump = 0; 35867c478bd9Sstevel@tonic-gate detach_devlist = NULL; 35877c478bd9Sstevel@tonic-gate 35887c478bd9Sstevel@tonic-gate /* 35897c478bd9Sstevel@tonic-gate * We switch on next_pass for the cases where a board 35907c478bd9Sstevel@tonic-gate * does not contain a particular type of component. 35917c478bd9Sstevel@tonic-gate * In these situations we don't want to return NULL 35927c478bd9Sstevel@tonic-gate * prematurely. We need to check other devices and 35937c478bd9Sstevel@tonic-gate * we don't want to check the same type multiple times. 35947c478bd9Sstevel@tonic-gate * For example, if there were no cpus, then on pass 1 35957c478bd9Sstevel@tonic-gate * we would drop through and return the memory nodes. 35967c478bd9Sstevel@tonic-gate * However, on pass 2 we would switch back to the memory 35977c478bd9Sstevel@tonic-gate * nodes thereby returning them twice! Using next_pass 35987c478bd9Sstevel@tonic-gate * forces us down to the end (or next item). 35997c478bd9Sstevel@tonic-gate */ 36007c478bd9Sstevel@tonic-gate if (pass == 1) 36017c478bd9Sstevel@tonic-gate next_pass = 1; 36027c478bd9Sstevel@tonic-gate 36037c478bd9Sstevel@tonic-gate switch (next_pass) { 36047c478bd9Sstevel@tonic-gate case 1: 36057c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) { 36067c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_MEM); 36077c478bd9Sstevel@tonic-gate 36087c478bd9Sstevel@tonic-gate detach_devlist = sbd_get_devlist(hp, sbp, 36097c478bd9Sstevel@tonic-gate SBD_COMP_MEM, 36107c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD, 36117c478bd9Sstevel@tonic-gate uset, devnump, 0); 36127c478bd9Sstevel@tonic-gate 36137c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_MEM, DEVSET_ANYUNIT); 36147c478bd9Sstevel@tonic-gate if (!devset || detach_devlist) { 36157c478bd9Sstevel@tonic-gate next_pass = 2; 36167c478bd9Sstevel@tonic-gate return (detach_devlist); 36177c478bd9Sstevel@tonic-gate } 36187c478bd9Sstevel@tonic-gate /* 36197c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 36207c478bd9Sstevel@tonic-gate * board, but there isn't any memory, then 36217c478bd9Sstevel@tonic-gate * just fall through to next component. 36227c478bd9Sstevel@tonic-gate */ 36237c478bd9Sstevel@tonic-gate } 36247c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 36257c478bd9Sstevel@tonic-gate 36267c478bd9Sstevel@tonic-gate case 2: 36277c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) { 36287c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_CPU); 36297c478bd9Sstevel@tonic-gate 36307c478bd9Sstevel@tonic-gate detach_devlist = sbd_get_devlist(hp, sbp, 36317c478bd9Sstevel@tonic-gate SBD_COMP_CPU, 36327c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD, 36337c478bd9Sstevel@tonic-gate uset, devnump, 0); 36347c478bd9Sstevel@tonic-gate 36357c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_CPU, DEVSET_ANYUNIT); 36367c478bd9Sstevel@tonic-gate if (!devset || detach_devlist) { 36377c478bd9Sstevel@tonic-gate next_pass = 2; 36387c478bd9Sstevel@tonic-gate return (detach_devlist); 36397c478bd9Sstevel@tonic-gate } 36407c478bd9Sstevel@tonic-gate /* 36417c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 36427c478bd9Sstevel@tonic-gate * board, but there aren't any cpus, then just 36437c478bd9Sstevel@tonic-gate * fall through to check for the next component. 36447c478bd9Sstevel@tonic-gate */ 36457c478bd9Sstevel@tonic-gate } 36467c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 36477c478bd9Sstevel@tonic-gate 36487c478bd9Sstevel@tonic-gate case 3: 36497c478bd9Sstevel@tonic-gate next_pass = -1; 36507c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) { 36517c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_IO); 36527c478bd9Sstevel@tonic-gate 36537c478bd9Sstevel@tonic-gate detach_devlist = sbd_get_devlist(hp, sbp, 36547c478bd9Sstevel@tonic-gate SBD_COMP_IO, 36557c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD, 36567c478bd9Sstevel@tonic-gate uset, devnump, 0); 36577c478bd9Sstevel@tonic-gate 36587c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_IO, DEVSET_ANYUNIT); 36597c478bd9Sstevel@tonic-gate if (!devset || detach_devlist) { 36607c478bd9Sstevel@tonic-gate next_pass = 4; 36617c478bd9Sstevel@tonic-gate return (detach_devlist); 36627c478bd9Sstevel@tonic-gate } 36637c478bd9Sstevel@tonic-gate } 36647c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 36657c478bd9Sstevel@tonic-gate 36667c478bd9Sstevel@tonic-gate default: 36677c478bd9Sstevel@tonic-gate *devnump = 0; 36687c478bd9Sstevel@tonic-gate return (NULL); 36697c478bd9Sstevel@tonic-gate } 36707c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 36717c478bd9Sstevel@tonic-gate } 36727c478bd9Sstevel@tonic-gate 36737c478bd9Sstevel@tonic-gate static int 36747c478bd9Sstevel@tonic-gate sbd_pre_detach_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 36757c478bd9Sstevel@tonic-gate int32_t devnum) 36767c478bd9Sstevel@tonic-gate { 36777c478bd9Sstevel@tonic-gate int rv = 0; 36787c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 36797c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_detach_devlist"; 36807c478bd9Sstevel@tonic-gate 36817c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 36827c478bd9Sstevel@tonic-gate 36837c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 36847c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 36857c478bd9Sstevel@tonic-gate 36867c478bd9Sstevel@tonic-gate switch (nodetype) { 36877c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 36887c478bd9Sstevel@tonic-gate rv = sbd_pre_detach_cpu(hp, devlist, devnum); 36897c478bd9Sstevel@tonic-gate break; 36907c478bd9Sstevel@tonic-gate 36917c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 36927c478bd9Sstevel@tonic-gate rv = sbd_pre_detach_mem(hp, devlist, devnum); 36937c478bd9Sstevel@tonic-gate break; 36947c478bd9Sstevel@tonic-gate 36957c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 36967c478bd9Sstevel@tonic-gate rv = sbd_pre_detach_io(hp, devlist, devnum); 36977c478bd9Sstevel@tonic-gate break; 36987c478bd9Sstevel@tonic-gate 36997c478bd9Sstevel@tonic-gate default: 37007c478bd9Sstevel@tonic-gate rv = -1; 37017c478bd9Sstevel@tonic-gate break; 37027c478bd9Sstevel@tonic-gate } 37037c478bd9Sstevel@tonic-gate 37047c478bd9Sstevel@tonic-gate /* 37057c478bd9Sstevel@tonic-gate * We want to continue attempting to detach 37067c478bd9Sstevel@tonic-gate * other components. 37077c478bd9Sstevel@tonic-gate */ 37087c478bd9Sstevel@tonic-gate return (rv); 37097c478bd9Sstevel@tonic-gate } 37107c478bd9Sstevel@tonic-gate 37117c478bd9Sstevel@tonic-gate static int 37127c478bd9Sstevel@tonic-gate sbd_post_detach_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 37137c478bd9Sstevel@tonic-gate int32_t devnum) 37147c478bd9Sstevel@tonic-gate { 37157c478bd9Sstevel@tonic-gate int i, max_units = 0, rv = 0; 37167c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 37177c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 37187c478bd9Sstevel@tonic-gate sbd_istate_t bstate; 37197c478bd9Sstevel@tonic-gate static fn_t f = "sbd_post_detach_devlist"; 37207c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 37217c478bd9Sstevel@tonic-gate 37227c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 37237c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 37247c478bd9Sstevel@tonic-gate 37257c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 37267c478bd9Sstevel@tonic-gate 37277c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 37287c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 37297c478bd9Sstevel@tonic-gate 37307c478bd9Sstevel@tonic-gate /* 37317c478bd9Sstevel@tonic-gate * Need to free up devlist[] created earlier in 37327c478bd9Sstevel@tonic-gate * sbd_get_detach_devlist(). 37337c478bd9Sstevel@tonic-gate */ 37347c478bd9Sstevel@tonic-gate switch (nodetype) { 37357c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 37367c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 37377c478bd9Sstevel@tonic-gate rv = sbd_post_detach_cpu(hp, devlist, devnum); 37387c478bd9Sstevel@tonic-gate break; 37397c478bd9Sstevel@tonic-gate 37407c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 37417c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 37427c478bd9Sstevel@tonic-gate rv = sbd_post_detach_mem(hp, devlist, devnum); 37437c478bd9Sstevel@tonic-gate break; 37447c478bd9Sstevel@tonic-gate 37457c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 37467c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 37477c478bd9Sstevel@tonic-gate rv = sbd_post_detach_io(hp, devlist, devnum); 37487c478bd9Sstevel@tonic-gate break; 37497c478bd9Sstevel@tonic-gate 37507c478bd9Sstevel@tonic-gate default: 37517c478bd9Sstevel@tonic-gate rv = -1; 37527c478bd9Sstevel@tonic-gate break; 37537c478bd9Sstevel@tonic-gate } 37547c478bd9Sstevel@tonic-gate 37557c478bd9Sstevel@tonic-gate 37567c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 37577c478bd9Sstevel@tonic-gate int unit; 37587c478bd9Sstevel@tonic-gate sbderror_t *ep; 37597c478bd9Sstevel@tonic-gate dev_info_t *dip; 37607c478bd9Sstevel@tonic-gate 37617c478bd9Sstevel@tonic-gate ep = &devlist[i].dv_error; 37627c478bd9Sstevel@tonic-gate 37637c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) 37647c478bd9Sstevel@tonic-gate continue; 37657c478bd9Sstevel@tonic-gate 37667c478bd9Sstevel@tonic-gate dip = devlist[i].dv_dip; 37677c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 37687c478bd9Sstevel@tonic-gate if (unit == -1) { 37697c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) 37707c478bd9Sstevel@tonic-gate continue; 37717c478bd9Sstevel@tonic-gate else { 37727c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 37737c478bd9Sstevel@tonic-gate break; 37747c478bd9Sstevel@tonic-gate } 37757c478bd9Sstevel@tonic-gate } 37767c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 37777c478bd9Sstevel@tonic-gate 37787c478bd9Sstevel@tonic-gate if (sbd_check_unit_attached(sbp, dip, unit, nodetype, 37797c478bd9Sstevel@tonic-gate ep) >= 0) { 37807c478bd9Sstevel@tonic-gate /* 37817c478bd9Sstevel@tonic-gate * Device is still attached probably due 37827c478bd9Sstevel@tonic-gate * to an error. Need to keep track of it. 37837c478bd9Sstevel@tonic-gate */ 37847c478bd9Sstevel@tonic-gate PR_ALL("%s: ERROR (nt=%s, b=%d, u=%d) not detached\n", 37857c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], sbp->sb_num, 37867c478bd9Sstevel@tonic-gate unit); 37877c478bd9Sstevel@tonic-gate continue; 37887c478bd9Sstevel@tonic-gate } 37897c478bd9Sstevel@tonic-gate 37907c478bd9Sstevel@tonic-gate SBD_DEV_CLR_ATTACHED(sbp, nodetype, unit); 37917c478bd9Sstevel@tonic-gate SBD_DEV_CLR_RELEASED(sbp, nodetype, unit); 37927c478bd9Sstevel@tonic-gate SBD_DEV_CLR_UNREFERENCED(sbp, nodetype, unit); 37937c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, nodetype, unit, 37947c478bd9Sstevel@tonic-gate SBD_STATE_UNCONFIGURED); 37957c478bd9Sstevel@tonic-gate } 37967c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 37977c478bd9Sstevel@tonic-gate 37987c478bd9Sstevel@tonic-gate bstate = SBD_BOARD_STATE(sbp); 37997c478bd9Sstevel@tonic-gate if (bstate != SBD_STATE_UNCONFIGURED) { 38007c478bd9Sstevel@tonic-gate if (SBD_DEVS_PRESENT(sbp) == SBD_DEVS_UNATTACHED(sbp)) { 38017c478bd9Sstevel@tonic-gate /* 38027c478bd9Sstevel@tonic-gate * All devices are finally detached. 38037c478bd9Sstevel@tonic-gate */ 38047c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_UNCONFIGURED); 38057c478bd9Sstevel@tonic-gate } else if ((SBD_BOARD_STATE(sbp) != SBD_STATE_PARTIAL) && 38067c478bd9Sstevel@tonic-gate SBD_DEVS_ATTACHED(sbp)) { 38077c478bd9Sstevel@tonic-gate /* 38087c478bd9Sstevel@tonic-gate * Some devices remain attached. 38097c478bd9Sstevel@tonic-gate */ 38107c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_PARTIAL); 38117c478bd9Sstevel@tonic-gate } 38127c478bd9Sstevel@tonic-gate } 38137c478bd9Sstevel@tonic-gate 38147c478bd9Sstevel@tonic-gate if (rv) { 38157c478bd9Sstevel@tonic-gate PR_ALL("%s: errno %d, ecode %d during detach\n", 38167c478bd9Sstevel@tonic-gate f, SBD_GET_ERRNO(SBD_HD2ERR(hp)), 38177c478bd9Sstevel@tonic-gate SBD_GET_ERR(HD2MACHERR(hp))); 38187c478bd9Sstevel@tonic-gate } 38197c478bd9Sstevel@tonic-gate 38207c478bd9Sstevel@tonic-gate if (max_units && devlist) { 38217c478bd9Sstevel@tonic-gate int i; 38227c478bd9Sstevel@tonic-gate 38237c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 38247c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 38257c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 38267c478bd9Sstevel@tonic-gate } else { 38277c478bd9Sstevel@tonic-gate break; 38287c478bd9Sstevel@tonic-gate } 38297c478bd9Sstevel@tonic-gate } 38307c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 38317c478bd9Sstevel@tonic-gate } 38327c478bd9Sstevel@tonic-gate 38337c478bd9Sstevel@tonic-gate return (SBD_GET_ERRNO(SBD_HD2ERR(hp)) ? -1 : 0); 38347c478bd9Sstevel@tonic-gate } 38357c478bd9Sstevel@tonic-gate 38367c478bd9Sstevel@tonic-gate /* 38377c478bd9Sstevel@tonic-gate * Return the unit number of the respective dip if 38387c478bd9Sstevel@tonic-gate * it's found to be attached. 38397c478bd9Sstevel@tonic-gate */ 38407c478bd9Sstevel@tonic-gate static int 38417c478bd9Sstevel@tonic-gate sbd_check_unit_attached(sbd_board_t *sbp, dev_info_t *dip, int unit, 38427c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype, sbderror_t *ep) 38437c478bd9Sstevel@tonic-gate { 38447c478bd9Sstevel@tonic-gate int rv = -1; 38457c478bd9Sstevel@tonic-gate processorid_t cpuid; 38467c478bd9Sstevel@tonic-gate uint64_t basepa, endpa; 38477c478bd9Sstevel@tonic-gate struct memlist *ml; 38487c478bd9Sstevel@tonic-gate extern struct memlist *phys_install; 38497c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 38507c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 38517c478bd9Sstevel@tonic-gate static fn_t f = "sbd_check_unit_attached"; 38527c478bd9Sstevel@tonic-gate 38537c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 38547c478bd9Sstevel@tonic-gate 38557c478bd9Sstevel@tonic-gate switch (nodetype) { 38567c478bd9Sstevel@tonic-gate 38577c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 38587c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 38597c478bd9Sstevel@tonic-gate if (cpuid < 0) { 38607c478bd9Sstevel@tonic-gate break; 38617c478bd9Sstevel@tonic-gate } 38627c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 38637c478bd9Sstevel@tonic-gate if (cpu_get(cpuid) != NULL) 38647c478bd9Sstevel@tonic-gate rv = unit; 38657c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 38667c478bd9Sstevel@tonic-gate break; 38677c478bd9Sstevel@tonic-gate 38687c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 38697c478bd9Sstevel@tonic-gate if (sbdphw_get_base_physaddr(hdp, dip, &basepa)) { 38707c478bd9Sstevel@tonic-gate break; 38717c478bd9Sstevel@tonic-gate } 38727c478bd9Sstevel@tonic-gate if (sbdp_get_mem_alignment(hdp, dip, &endpa)) { 38737c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s sbdp_get_mem_alignment fail", f); 38747c478bd9Sstevel@tonic-gate break; 38757c478bd9Sstevel@tonic-gate } 38767c478bd9Sstevel@tonic-gate 38777c478bd9Sstevel@tonic-gate basepa &= ~(endpa - 1); 38787c478bd9Sstevel@tonic-gate endpa += basepa; 38797c478bd9Sstevel@tonic-gate /* 38807c478bd9Sstevel@tonic-gate * Check if base address is in phys_install. 38817c478bd9Sstevel@tonic-gate */ 38827c478bd9Sstevel@tonic-gate memlist_read_lock(); 3883*56f33205SJonathan Adams for (ml = phys_install; ml; ml = ml->ml_next) 3884*56f33205SJonathan Adams if ((endpa <= ml->ml_address) || 3885*56f33205SJonathan Adams (basepa >= (ml->ml_address + ml->ml_size))) 38867c478bd9Sstevel@tonic-gate continue; 38877c478bd9Sstevel@tonic-gate else 38887c478bd9Sstevel@tonic-gate break; 38897c478bd9Sstevel@tonic-gate memlist_read_unlock(); 38907c478bd9Sstevel@tonic-gate if (ml != NULL) 38917c478bd9Sstevel@tonic-gate rv = unit; 38927c478bd9Sstevel@tonic-gate break; 38937c478bd9Sstevel@tonic-gate 38947c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 38957c478bd9Sstevel@tonic-gate { 38967c478bd9Sstevel@tonic-gate dev_info_t *tdip, *pdip; 38977c478bd9Sstevel@tonic-gate 38987c478bd9Sstevel@tonic-gate tdip = dip; 38997c478bd9Sstevel@tonic-gate 39007c478bd9Sstevel@tonic-gate /* 39017c478bd9Sstevel@tonic-gate * ddi_walk_devs() requires that topdip's parent be held. 39027c478bd9Sstevel@tonic-gate */ 39037c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(sbp->sb_topdip); 39047c478bd9Sstevel@tonic-gate if (pdip) { 39057c478bd9Sstevel@tonic-gate ndi_hold_devi(pdip); 39067c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &rv); 39077c478bd9Sstevel@tonic-gate } 39087c478bd9Sstevel@tonic-gate ddi_walk_devs(sbp->sb_topdip, sbd_check_io_attached, 39097c478bd9Sstevel@tonic-gate (void *)&tdip); 39107c478bd9Sstevel@tonic-gate if (pdip) { 39117c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, rv); 39127c478bd9Sstevel@tonic-gate ndi_rele_devi(pdip); 39137c478bd9Sstevel@tonic-gate } 39147c478bd9Sstevel@tonic-gate 39157c478bd9Sstevel@tonic-gate if (tdip == NULL) 39167c478bd9Sstevel@tonic-gate rv = unit; 39177c478bd9Sstevel@tonic-gate else 39187c478bd9Sstevel@tonic-gate rv = -1; 39197c478bd9Sstevel@tonic-gate break; 39207c478bd9Sstevel@tonic-gate } 39217c478bd9Sstevel@tonic-gate 39227c478bd9Sstevel@tonic-gate default: 39237c478bd9Sstevel@tonic-gate PR_ALL("%s: unexpected nodetype(%d) for dip 0x%p\n", 39247c478bd9Sstevel@tonic-gate f, nodetype, (void *)dip); 39257c478bd9Sstevel@tonic-gate rv = -1; 39267c478bd9Sstevel@tonic-gate break; 39277c478bd9Sstevel@tonic-gate } 39287c478bd9Sstevel@tonic-gate 39297c478bd9Sstevel@tonic-gate /* 39307c478bd9Sstevel@tonic-gate * Save the error that sbdp sent us and report it 39317c478bd9Sstevel@tonic-gate */ 39327c478bd9Sstevel@tonic-gate if (rv == -1) 39337c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 39347c478bd9Sstevel@tonic-gate 39357c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 39367c478bd9Sstevel@tonic-gate 39377c478bd9Sstevel@tonic-gate return (rv); 39387c478bd9Sstevel@tonic-gate } 39397c478bd9Sstevel@tonic-gate 39407c478bd9Sstevel@tonic-gate /* 39417c478bd9Sstevel@tonic-gate * Return memhandle, if in fact, this memunit is the owner of 39427c478bd9Sstevel@tonic-gate * a scheduled memory delete. 39437c478bd9Sstevel@tonic-gate */ 39447c478bd9Sstevel@tonic-gate int 39457c478bd9Sstevel@tonic-gate sbd_get_memhandle(sbd_handle_t *hp, dev_info_t *dip, memhandle_t *mhp) 39467c478bd9Sstevel@tonic-gate { 39477c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 39487c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 39497c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 39507c478bd9Sstevel@tonic-gate int unit; 39517c478bd9Sstevel@tonic-gate static fn_t f = "sbd_get_memhandle"; 39527c478bd9Sstevel@tonic-gate 39537c478bd9Sstevel@tonic-gate PR_MEM("%s...\n", f); 39547c478bd9Sstevel@tonic-gate 39557c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 39567c478bd9Sstevel@tonic-gate 39577c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 39587c478bd9Sstevel@tonic-gate if (unit == -1) { 39597c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 39607c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 39617c478bd9Sstevel@tonic-gate return (-1); 39627c478bd9Sstevel@tonic-gate } 39637c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 39647c478bd9Sstevel@tonic-gate 39657c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, unit); 39667c478bd9Sstevel@tonic-gate 39677c478bd9Sstevel@tonic-gate if (mp->sbm_flags & SBD_MFLAG_RELOWNER) { 39687c478bd9Sstevel@tonic-gate *mhp = mp->sbm_memhandle; 39697c478bd9Sstevel@tonic-gate return (0); 39707c478bd9Sstevel@tonic-gate } else { 39717c478bd9Sstevel@tonic-gate SBD_SET_ERR(SBD_HD2ERR(hp), ESBD_INTERNAL); 39727c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(SBD_HD2ERR(hp), sbp->sb_mempath[unit]); 39737c478bd9Sstevel@tonic-gate return (-1); 39747c478bd9Sstevel@tonic-gate } 39757c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 39767c478bd9Sstevel@tonic-gate } 39777c478bd9Sstevel@tonic-gate 39787c478bd9Sstevel@tonic-gate 39797c478bd9Sstevel@tonic-gate static int 39807c478bd9Sstevel@tonic-gate sbd_cpu_cnt(sbd_handle_t *hp, sbd_devset_t devset) 39817c478bd9Sstevel@tonic-gate { 39827c478bd9Sstevel@tonic-gate int c, cix; 39837c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 39847c478bd9Sstevel@tonic-gate 39857c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 39867c478bd9Sstevel@tonic-gate 39877c478bd9Sstevel@tonic-gate /* 39887c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 39897c478bd9Sstevel@tonic-gate */ 39907c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 39917c478bd9Sstevel@tonic-gate 39927c478bd9Sstevel@tonic-gate for (c = cix = 0; c < MAX_CMP_UNITS_PER_BOARD; c++) { 39937c478bd9Sstevel@tonic-gate /* 39947c478bd9Sstevel@tonic-gate * Index for core 1 , if exists. 39957c478bd9Sstevel@tonic-gate * With the current implementation it is 39967c478bd9Sstevel@tonic-gate * MAX_CMP_UNITS_PER_BOARD off from core 0. 39977c478bd9Sstevel@tonic-gate * The calculation will need to change if 39987c478bd9Sstevel@tonic-gate * the assumption is no longer true. 39997c478bd9Sstevel@tonic-gate */ 40007c478bd9Sstevel@tonic-gate int c1 = c + MAX_CMP_UNITS_PER_BOARD; 40017c478bd9Sstevel@tonic-gate 40027c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CMP, c) == 0) { 40037c478bd9Sstevel@tonic-gate continue; 40047c478bd9Sstevel@tonic-gate } 40057c478bd9Sstevel@tonic-gate 40067c478bd9Sstevel@tonic-gate /* 40077c478bd9Sstevel@tonic-gate * Check to see if the dip(s) exist for this chip 40087c478bd9Sstevel@tonic-gate */ 40097c478bd9Sstevel@tonic-gate if ((sbp->sb_devlist[NIX(SBD_COMP_CMP)][c] == NULL) && 40107c478bd9Sstevel@tonic-gate (sbp->sb_devlist[NIX(SBD_COMP_CMP)][c1] == NULL)) 40117c478bd9Sstevel@tonic-gate continue; 40127c478bd9Sstevel@tonic-gate 40137c478bd9Sstevel@tonic-gate cix++; 40147c478bd9Sstevel@tonic-gate } 40157c478bd9Sstevel@tonic-gate 40167c478bd9Sstevel@tonic-gate return (cix); 40177c478bd9Sstevel@tonic-gate } 40187c478bd9Sstevel@tonic-gate 40197c478bd9Sstevel@tonic-gate static int 40207c478bd9Sstevel@tonic-gate sbd_mem_cnt(sbd_handle_t *hp, sbd_devset_t devset) 40217c478bd9Sstevel@tonic-gate { 40227c478bd9Sstevel@tonic-gate int i, ix; 40237c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 40247c478bd9Sstevel@tonic-gate 40257c478bd9Sstevel@tonic-gate /* 40267c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 40277c478bd9Sstevel@tonic-gate */ 40287c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 40297c478bd9Sstevel@tonic-gate 40307c478bd9Sstevel@tonic-gate for (i = ix = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 40317c478bd9Sstevel@tonic-gate dev_info_t *dip; 40327c478bd9Sstevel@tonic-gate 40337c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, i) == 0) { 40347c478bd9Sstevel@tonic-gate continue; 40357c478bd9Sstevel@tonic-gate } 40367c478bd9Sstevel@tonic-gate 40377c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_MEM)][i]; 40387c478bd9Sstevel@tonic-gate if (dip == NULL) 40397c478bd9Sstevel@tonic-gate continue; 40407c478bd9Sstevel@tonic-gate 40417c478bd9Sstevel@tonic-gate ix++; 40427c478bd9Sstevel@tonic-gate } 40437c478bd9Sstevel@tonic-gate 40447c478bd9Sstevel@tonic-gate return (ix); 40457c478bd9Sstevel@tonic-gate } 40467c478bd9Sstevel@tonic-gate 40477c478bd9Sstevel@tonic-gate /* 40487c478bd9Sstevel@tonic-gate * NOTE: This routine is only partially smart about multiple 40497c478bd9Sstevel@tonic-gate * mem-units. Need to make mem-status structure smart 40507c478bd9Sstevel@tonic-gate * about them also. 40517c478bd9Sstevel@tonic-gate */ 40527c478bd9Sstevel@tonic-gate static int 40537c478bd9Sstevel@tonic-gate sbd_mem_status(sbd_handle_t *hp, sbd_devset_t devset, sbd_dev_stat_t *dsp) 40547c478bd9Sstevel@tonic-gate { 40557c478bd9Sstevel@tonic-gate int m, mix, rv; 40567c478bd9Sstevel@tonic-gate memdelstat_t mdst; 40577c478bd9Sstevel@tonic-gate memquery_t mq; 40587c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 40597c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 40607c478bd9Sstevel@tonic-gate sbd_mem_stat_t *msp; 40617c478bd9Sstevel@tonic-gate extern int kcage_on; 40627c478bd9Sstevel@tonic-gate int i; 40637c478bd9Sstevel@tonic-gate static fn_t f = "sbd_mem_status"; 40647c478bd9Sstevel@tonic-gate 40657c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 40667c478bd9Sstevel@tonic-gate 40677c478bd9Sstevel@tonic-gate /* 40687c478bd9Sstevel@tonic-gate * Check the present devset and access the dip with 40697c478bd9Sstevel@tonic-gate * status lock held to protect agains a concurrent 40707c478bd9Sstevel@tonic-gate * unconfigure or disconnect thread. 40717c478bd9Sstevel@tonic-gate */ 40727c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 40737c478bd9Sstevel@tonic-gate 40747c478bd9Sstevel@tonic-gate /* 40757c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 40767c478bd9Sstevel@tonic-gate */ 40777c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 40787c478bd9Sstevel@tonic-gate 40797c478bd9Sstevel@tonic-gate for (m = mix = 0; m < MAX_MEM_UNITS_PER_BOARD; m++) { 40807c478bd9Sstevel@tonic-gate dev_info_t *dip; 40817c478bd9Sstevel@tonic-gate 40827c478bd9Sstevel@tonic-gate 40837c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, m) == 0) 40847c478bd9Sstevel@tonic-gate continue; 40857c478bd9Sstevel@tonic-gate 40867c478bd9Sstevel@tonic-gate /* 40877c478bd9Sstevel@tonic-gate * Check to make sure the memory unit is in a state 40887c478bd9Sstevel@tonic-gate * where its fully initialized. 40897c478bd9Sstevel@tonic-gate */ 40907c478bd9Sstevel@tonic-gate if (SBD_DEVICE_STATE(sbp, SBD_COMP_MEM, m) == SBD_STATE_EMPTY) 40917c478bd9Sstevel@tonic-gate continue; 40927c478bd9Sstevel@tonic-gate 40937c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_MEM)][m]; 40947c478bd9Sstevel@tonic-gate if (dip == NULL) 40957c478bd9Sstevel@tonic-gate continue; 40967c478bd9Sstevel@tonic-gate 40977c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, m); 40987c478bd9Sstevel@tonic-gate 40997c478bd9Sstevel@tonic-gate msp = &dsp->d_mem; 41007c478bd9Sstevel@tonic-gate 41017c478bd9Sstevel@tonic-gate bzero((caddr_t)msp, sizeof (*msp)); 41027c478bd9Sstevel@tonic-gate msp->ms_type = SBD_COMP_MEM; 41037c478bd9Sstevel@tonic-gate 41047c478bd9Sstevel@tonic-gate /* 41057c478bd9Sstevel@tonic-gate * The plugin expects -1 for the mem unit 41067c478bd9Sstevel@tonic-gate */ 41077c478bd9Sstevel@tonic-gate msp->ms_cm.c_id.c_unit = -1; 41087c478bd9Sstevel@tonic-gate 41097c478bd9Sstevel@tonic-gate /* 41107c478bd9Sstevel@tonic-gate * Get the memory name from what sbdp gave us 41117c478bd9Sstevel@tonic-gate */ 41127c478bd9Sstevel@tonic-gate for (i = 0; SBD_COMP(i) != SBD_COMP_UNKNOWN; i++) { 41137c478bd9Sstevel@tonic-gate if (SBD_COMP(i) == SBD_COMP_MEM) { 41147c478bd9Sstevel@tonic-gate (void) strcpy(msp->ms_name, SBD_DEVNAME(i)); 41157c478bd9Sstevel@tonic-gate } 41167c478bd9Sstevel@tonic-gate } 41177c478bd9Sstevel@tonic-gate msp->ms_cm.c_cond = mp->sbm_cm.sbdev_cond; 41187c478bd9Sstevel@tonic-gate msp->ms_cm.c_busy = mp->sbm_cm.sbdev_busy; 41197c478bd9Sstevel@tonic-gate msp->ms_cm.c_time = mp->sbm_cm.sbdev_time; 41207c478bd9Sstevel@tonic-gate 41217c478bd9Sstevel@tonic-gate /* XXX revisit this after memory conversion */ 41227c478bd9Sstevel@tonic-gate msp->ms_ostate = ostate_cvt(SBD_DEVICE_STATE( 41237c478bd9Sstevel@tonic-gate sbp, SBD_COMP_MEM, m)); 41247c478bd9Sstevel@tonic-gate 41257c478bd9Sstevel@tonic-gate msp->ms_basepfn = mp->sbm_basepfn; 41267c478bd9Sstevel@tonic-gate msp->ms_pageslost = mp->sbm_pageslost; 41277c478bd9Sstevel@tonic-gate msp->ms_cage_enabled = kcage_on; 41287c478bd9Sstevel@tonic-gate msp->ms_interleave = mp->sbm_interleave; 41297c478bd9Sstevel@tonic-gate 41307c478bd9Sstevel@tonic-gate if (mp->sbm_flags & SBD_MFLAG_RELOWNER) 41317c478bd9Sstevel@tonic-gate rv = kphysm_del_status(mp->sbm_memhandle, &mdst); 41327c478bd9Sstevel@tonic-gate else 41337c478bd9Sstevel@tonic-gate rv = KPHYSM_EHANDLE; /* force 'if' to fail */ 41347c478bd9Sstevel@tonic-gate 41357c478bd9Sstevel@tonic-gate if (rv == KPHYSM_OK) { 41367c478bd9Sstevel@tonic-gate msp->ms_totpages += mdst.phys_pages; 41377c478bd9Sstevel@tonic-gate 41387c478bd9Sstevel@tonic-gate /* 41397c478bd9Sstevel@tonic-gate * Any pages above managed is "free", 41407c478bd9Sstevel@tonic-gate * i.e. it's collected. 41417c478bd9Sstevel@tonic-gate */ 41427c478bd9Sstevel@tonic-gate msp->ms_detpages += (uint_t)(mdst.collected + 41437c478bd9Sstevel@tonic-gate mdst.phys_pages - 41447c478bd9Sstevel@tonic-gate mdst.managed); 41457c478bd9Sstevel@tonic-gate } else { 41467c478bd9Sstevel@tonic-gate msp->ms_totpages += (uint_t)mp->sbm_npages; 41477c478bd9Sstevel@tonic-gate 41487c478bd9Sstevel@tonic-gate /* 41497c478bd9Sstevel@tonic-gate * If we're UNREFERENCED or UNCONFIGURED, 41507c478bd9Sstevel@tonic-gate * then the number of detached pages is 41517c478bd9Sstevel@tonic-gate * however many pages are on the board. 41527c478bd9Sstevel@tonic-gate * I.e. detached = not in use by OS. 41537c478bd9Sstevel@tonic-gate */ 41547c478bd9Sstevel@tonic-gate switch (msp->ms_cm.c_ostate) { 41557c478bd9Sstevel@tonic-gate /* 41567c478bd9Sstevel@tonic-gate * changed to use cfgadm states 41577c478bd9Sstevel@tonic-gate * 41587c478bd9Sstevel@tonic-gate * was: 41597c478bd9Sstevel@tonic-gate * case SFDR_STATE_UNREFERENCED: 41607c478bd9Sstevel@tonic-gate * case SFDR_STATE_UNCONFIGURED: 41617c478bd9Sstevel@tonic-gate */ 41627c478bd9Sstevel@tonic-gate case SBD_STAT_UNCONFIGURED: 41637c478bd9Sstevel@tonic-gate msp->ms_detpages = msp->ms_totpages; 41647c478bd9Sstevel@tonic-gate break; 41657c478bd9Sstevel@tonic-gate 41667c478bd9Sstevel@tonic-gate default: 41677c478bd9Sstevel@tonic-gate break; 41687c478bd9Sstevel@tonic-gate } 41697c478bd9Sstevel@tonic-gate } 41707c478bd9Sstevel@tonic-gate 41717c478bd9Sstevel@tonic-gate rv = kphysm_del_span_query(mp->sbm_basepfn, 41727c478bd9Sstevel@tonic-gate mp->sbm_npages, &mq); 41737c478bd9Sstevel@tonic-gate if (rv == KPHYSM_OK) { 41747c478bd9Sstevel@tonic-gate msp->ms_managed_pages = mq.managed; 41757c478bd9Sstevel@tonic-gate msp->ms_noreloc_pages = mq.nonrelocatable; 41767c478bd9Sstevel@tonic-gate msp->ms_noreloc_first = mq.first_nonrelocatable; 41777c478bd9Sstevel@tonic-gate msp->ms_noreloc_last = mq.last_nonrelocatable; 41787c478bd9Sstevel@tonic-gate msp->ms_cm.c_sflags = 0; 41797c478bd9Sstevel@tonic-gate if (mq.nonrelocatable) { 41807c478bd9Sstevel@tonic-gate SBD_SET_SUSPEND(SBD_CMD_UNCONFIGURE, 41817c478bd9Sstevel@tonic-gate dsp->ds_suspend); 41827c478bd9Sstevel@tonic-gate } 41837c478bd9Sstevel@tonic-gate } else { 41847c478bd9Sstevel@tonic-gate PR_MEM("%s: kphysm_del_span_query() = %d\n", f, rv); 41857c478bd9Sstevel@tonic-gate } 41867c478bd9Sstevel@tonic-gate 41877c478bd9Sstevel@tonic-gate mix++; 41887c478bd9Sstevel@tonic-gate dsp++; 41897c478bd9Sstevel@tonic-gate } 41907c478bd9Sstevel@tonic-gate 41917c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 41927c478bd9Sstevel@tonic-gate 41937c478bd9Sstevel@tonic-gate return (mix); 41947c478bd9Sstevel@tonic-gate } 41957c478bd9Sstevel@tonic-gate 41967c478bd9Sstevel@tonic-gate static void 41977c478bd9Sstevel@tonic-gate sbd_cancel(sbd_handle_t *hp) 41987c478bd9Sstevel@tonic-gate { 41997c478bd9Sstevel@tonic-gate int i; 42007c478bd9Sstevel@tonic-gate sbd_devset_t devset; 42017c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 42027c478bd9Sstevel@tonic-gate static fn_t f = "sbd_cancel"; 42037c478bd9Sstevel@tonic-gate int rv; 42047c478bd9Sstevel@tonic-gate 42057c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 42067c478bd9Sstevel@tonic-gate 42077c478bd9Sstevel@tonic-gate /* 42087c478bd9Sstevel@tonic-gate * Only devices which have been "released" are 42097c478bd9Sstevel@tonic-gate * subject to cancellation. 42107c478bd9Sstevel@tonic-gate */ 42117c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset & SBD_DEVS_UNREFERENCED(sbp); 42127c478bd9Sstevel@tonic-gate 42137c478bd9Sstevel@tonic-gate /* 42147c478bd9Sstevel@tonic-gate * Nothing to do for CPUs or IO other than change back 42157c478bd9Sstevel@tonic-gate * their state. 42167c478bd9Sstevel@tonic-gate */ 42177c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 42187c478bd9Sstevel@tonic-gate if (!DEVSET_IN_SET(devset, SBD_COMP_CPU, i)) 42197c478bd9Sstevel@tonic-gate continue; 42207c478bd9Sstevel@tonic-gate if (sbd_cancel_cpu(hp, i) != SBD_CPUERR_FATAL) { 42217c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, i, 42227c478bd9Sstevel@tonic-gate SBD_STATE_CONFIGURED); 42237c478bd9Sstevel@tonic-gate } else { 42247c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, i, 42257c478bd9Sstevel@tonic-gate SBD_STATE_FATAL); 42267c478bd9Sstevel@tonic-gate } 42277c478bd9Sstevel@tonic-gate } 42287c478bd9Sstevel@tonic-gate 42297c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 42307c478bd9Sstevel@tonic-gate if (!DEVSET_IN_SET(devset, SBD_COMP_IO, i)) 42317c478bd9Sstevel@tonic-gate continue; 42327c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, i, 42337c478bd9Sstevel@tonic-gate SBD_STATE_CONFIGURED); 42347c478bd9Sstevel@tonic-gate } 42357c478bd9Sstevel@tonic-gate 42367c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 42377c478bd9Sstevel@tonic-gate if (!DEVSET_IN_SET(devset, SBD_COMP_MEM, i)) 42387c478bd9Sstevel@tonic-gate continue; 42397c478bd9Sstevel@tonic-gate if ((rv = sbd_cancel_mem(hp, i)) == 0) { 42407c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_MEM, i, 42417c478bd9Sstevel@tonic-gate SBD_STATE_CONFIGURED); 42427c478bd9Sstevel@tonic-gate } else if (rv == -1) { 42437c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_MEM, i, 42447c478bd9Sstevel@tonic-gate SBD_STATE_FATAL); 42457c478bd9Sstevel@tonic-gate } 42467c478bd9Sstevel@tonic-gate } 42477c478bd9Sstevel@tonic-gate 42487c478bd9Sstevel@tonic-gate PR_ALL("%s: unreleasing devset (0x%x)\n", f, (uint_t)devset); 42497c478bd9Sstevel@tonic-gate 42507c478bd9Sstevel@tonic-gate SBD_DEVS_CANCEL(sbp, devset); 42517c478bd9Sstevel@tonic-gate 42527c478bd9Sstevel@tonic-gate if (SBD_DEVS_UNREFERENCED(sbp) == 0) { 42537c478bd9Sstevel@tonic-gate sbd_istate_t new_state; 42547c478bd9Sstevel@tonic-gate /* 42557c478bd9Sstevel@tonic-gate * If the board no longer has any released devices 42567c478bd9Sstevel@tonic-gate * than transfer it back to the CONFIG/PARTIAL state. 42577c478bd9Sstevel@tonic-gate */ 42587c478bd9Sstevel@tonic-gate if (SBD_DEVS_ATTACHED(sbp) == SBD_DEVS_PRESENT(sbp)) 42597c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONFIGURED; 42607c478bd9Sstevel@tonic-gate else 42617c478bd9Sstevel@tonic-gate new_state = SBD_STATE_PARTIAL; 42627c478bd9Sstevel@tonic-gate if (SBD_BOARD_STATE(sbp) != new_state) { 42637c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, new_state); 42647c478bd9Sstevel@tonic-gate } 42657c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_CONFIGURED; 42667c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 42677c478bd9Sstevel@tonic-gate } 42687c478bd9Sstevel@tonic-gate } 42697c478bd9Sstevel@tonic-gate 42707c478bd9Sstevel@tonic-gate static void 42717c478bd9Sstevel@tonic-gate sbd_get_ncm(sbd_handle_t *hp) 42727c478bd9Sstevel@tonic-gate { 42737c478bd9Sstevel@tonic-gate sbd_devset_t devset; 42747c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 42757c478bd9Sstevel@tonic-gate sbd_cmd_t *cmdp = (sbd_cmd_t *)hp->h_iap; 42767c478bd9Sstevel@tonic-gate int error; 42777c478bd9Sstevel@tonic-gate 42787c478bd9Sstevel@tonic-gate /* pre_op restricted the devices to those selected by the ioctl */ 42797c478bd9Sstevel@tonic-gate devset = shp->sh_devset; 42807c478bd9Sstevel@tonic-gate 42817c478bd9Sstevel@tonic-gate cmdp->cmd_getncm.g_ncm = sbd_cpu_cnt(hp, devset) 42827c478bd9Sstevel@tonic-gate + sbd_io_cnt(hp, devset) + sbd_mem_cnt(hp, devset); 42837c478bd9Sstevel@tonic-gate 42847c478bd9Sstevel@tonic-gate error = sbd_copyout_ioarg(hp->h_mode, hp->h_cmd, cmdp, 42857c478bd9Sstevel@tonic-gate (sbd_ioctl_arg_t *)shp->sh_arg); 42867c478bd9Sstevel@tonic-gate 42877c478bd9Sstevel@tonic-gate if (error != 0) 42887c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), error); 42897c478bd9Sstevel@tonic-gate } 42907c478bd9Sstevel@tonic-gate 42917c478bd9Sstevel@tonic-gate static void 42927c478bd9Sstevel@tonic-gate sbd_status(sbd_handle_t *hp) 42937c478bd9Sstevel@tonic-gate { 42947c478bd9Sstevel@tonic-gate int nstat, mode, ncm, sz, cksz; 42957c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 42967c478bd9Sstevel@tonic-gate sbd_devset_t devset; 42977c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 42987c478bd9Sstevel@tonic-gate sbd_stat_t *dstatp; 42997c478bd9Sstevel@tonic-gate sbd_cmd_t *cmdp = (sbd_cmd_t *)hp->h_iap; 43007c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 43017c478bd9Sstevel@tonic-gate sbd_dev_stat_t *devstatp; 43027c478bd9Sstevel@tonic-gate 43037c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 43047c478bd9Sstevel@tonic-gate int sz32; 43057c478bd9Sstevel@tonic-gate sbd_stat32_t *dstat32p; 43067c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 43077c478bd9Sstevel@tonic-gate 43087c478bd9Sstevel@tonic-gate static fn_t f = "sbd_status"; 43097c478bd9Sstevel@tonic-gate 43107c478bd9Sstevel@tonic-gate mode = hp->h_mode; 43117c478bd9Sstevel@tonic-gate devset = shp->sh_devset; 43127c478bd9Sstevel@tonic-gate 43137c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 43147c478bd9Sstevel@tonic-gate 43157c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_id.c_type == SBD_COMP_NONE) { 43167c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_flags & SBD_FLAG_ALLCMP) { 43177c478bd9Sstevel@tonic-gate /* 43187c478bd9Sstevel@tonic-gate * Get the number of components "ncm" on the board. 43197c478bd9Sstevel@tonic-gate * Calculate size of buffer required to store one 43207c478bd9Sstevel@tonic-gate * sbd_stat_t structure plus ncm-1 sbd_dev_stat_t 43217c478bd9Sstevel@tonic-gate * structures. Note that sbd_stat_t already contains 43227c478bd9Sstevel@tonic-gate * one sbd_dev_stat_t, so only an additional ncm-1 43237c478bd9Sstevel@tonic-gate * sbd_dev_stat_t structures need to be accounted for 43247c478bd9Sstevel@tonic-gate * in the calculation when more than one component 43257c478bd9Sstevel@tonic-gate * is present. 43267c478bd9Sstevel@tonic-gate */ 43277c478bd9Sstevel@tonic-gate ncm = sbd_cpu_cnt(hp, devset) + sbd_io_cnt(hp, devset) + 43287c478bd9Sstevel@tonic-gate sbd_mem_cnt(hp, devset); 43297c478bd9Sstevel@tonic-gate 43307c478bd9Sstevel@tonic-gate } else { 43317c478bd9Sstevel@tonic-gate /* 43327c478bd9Sstevel@tonic-gate * In the case of c_type == SBD_COMP_NONE, and 43337c478bd9Sstevel@tonic-gate * SBD_FLAG_ALLCMP not specified, only the board 43347c478bd9Sstevel@tonic-gate * info is to be returned, no components. 43357c478bd9Sstevel@tonic-gate */ 43367c478bd9Sstevel@tonic-gate ncm = 0; 43377c478bd9Sstevel@tonic-gate devset = 0; 43387c478bd9Sstevel@tonic-gate } 43397c478bd9Sstevel@tonic-gate } else { 43407c478bd9Sstevel@tonic-gate /* Confirm that only one component is selected. */ 43417c478bd9Sstevel@tonic-gate ncm = sbd_cpu_cnt(hp, devset) + sbd_io_cnt(hp, devset) + 43427c478bd9Sstevel@tonic-gate sbd_mem_cnt(hp, devset); 43437c478bd9Sstevel@tonic-gate if (ncm != 1) { 43447c478bd9Sstevel@tonic-gate PR_ALL("%s: expected ncm of 1, got %d, devset 0x%x\n", 43457c478bd9Sstevel@tonic-gate f, ncm, devset); 43467c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EINVAL); 43477c478bd9Sstevel@tonic-gate return; 43487c478bd9Sstevel@tonic-gate } 43497c478bd9Sstevel@tonic-gate } 43507c478bd9Sstevel@tonic-gate 43517c478bd9Sstevel@tonic-gate sz = sizeof (sbd_stat_t); 43527c478bd9Sstevel@tonic-gate if (ncm > 1) 43537c478bd9Sstevel@tonic-gate sz += sizeof (sbd_dev_stat_t) * (ncm - 1); 43547c478bd9Sstevel@tonic-gate 43557c478bd9Sstevel@tonic-gate cksz = sz; 43567c478bd9Sstevel@tonic-gate 43577c478bd9Sstevel@tonic-gate /* 43587c478bd9Sstevel@tonic-gate * s_nbytes describes the size of the preallocated user 43597c478bd9Sstevel@tonic-gate * buffer into which the application is executing to 43607c478bd9Sstevel@tonic-gate * receive the sbd_stat_t and sbd_dev_stat_t structures. 43617c478bd9Sstevel@tonic-gate * This buffer must be at least the required (sz) size. 43627c478bd9Sstevel@tonic-gate */ 43637c478bd9Sstevel@tonic-gate 43647c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 43657c478bd9Sstevel@tonic-gate 43667c478bd9Sstevel@tonic-gate /* 43677c478bd9Sstevel@tonic-gate * More buffer space is required for the 64bit to 32bit 43687c478bd9Sstevel@tonic-gate * conversion of data structures. 43697c478bd9Sstevel@tonic-gate */ 43707c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 43717c478bd9Sstevel@tonic-gate sz32 = sizeof (sbd_stat32_t); 43727c478bd9Sstevel@tonic-gate if (ncm > 1) 43737c478bd9Sstevel@tonic-gate sz32 += sizeof (sbd_dev_stat32_t) * (ncm - 1); 43747c478bd9Sstevel@tonic-gate cksz = sz32; 43757c478bd9Sstevel@tonic-gate } else 43767c478bd9Sstevel@tonic-gate sz32 = 0; 43777c478bd9Sstevel@tonic-gate #endif 43787c478bd9Sstevel@tonic-gate 43797c478bd9Sstevel@tonic-gate if ((int)cmdp->cmd_stat.s_nbytes < cksz) { 43807c478bd9Sstevel@tonic-gate PR_ALL("%s: ncm=%d s_nbytes = 0x%x\n", f, ncm, 43817c478bd9Sstevel@tonic-gate cmdp->cmd_stat.s_nbytes); 43827c478bd9Sstevel@tonic-gate PR_ALL("%s: expected size of 0x%x\n", f, cksz); 43837c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EINVAL); 43847c478bd9Sstevel@tonic-gate return; 43857c478bd9Sstevel@tonic-gate } 43867c478bd9Sstevel@tonic-gate 43877c478bd9Sstevel@tonic-gate dstatp = kmem_zalloc(sz, KM_SLEEP); 43887c478bd9Sstevel@tonic-gate devstatp = &dstatp->s_stat[0]; 43897c478bd9Sstevel@tonic-gate 43907c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 43917c478bd9Sstevel@tonic-gate if (sz32 != 0) 43927c478bd9Sstevel@tonic-gate dstat32p = kmem_zalloc(sz32, KM_SLEEP); 43937c478bd9Sstevel@tonic-gate #endif 43947c478bd9Sstevel@tonic-gate 43957c478bd9Sstevel@tonic-gate /* 43967c478bd9Sstevel@tonic-gate * if connected or better, provide cached status if available, 43977c478bd9Sstevel@tonic-gate * otherwise call sbdp for status 43987c478bd9Sstevel@tonic-gate */ 43997c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_flags_mutex); 44007c478bd9Sstevel@tonic-gate switch (sbp->sb_state) { 44017c478bd9Sstevel@tonic-gate 44027c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 44037c478bd9Sstevel@tonic-gate case SBD_STATE_PARTIAL: 44047c478bd9Sstevel@tonic-gate case SBD_STATE_CONFIGURED: 44057c478bd9Sstevel@tonic-gate if (sbp->sb_flags & SBD_BOARD_STATUS_CACHED) { 44067c478bd9Sstevel@tonic-gate bcopy(&sbp->sb_stat, dstatp, sizeof (sbd_stat_t)); 44077c478bd9Sstevel@tonic-gate dstatp->s_rstate = rstate_cvt(sbp->sb_state); 44087c478bd9Sstevel@tonic-gate dstatp->s_ostate = ostate_cvt(sbp->sb_state); 44097c478bd9Sstevel@tonic-gate dstatp->s_busy = sbp->sb_busy; 44107c478bd9Sstevel@tonic-gate dstatp->s_time = sbp->sb_time; 44117c478bd9Sstevel@tonic-gate dstatp->s_cond = sbp->sb_cond; 44127c478bd9Sstevel@tonic-gate break; 44137c478bd9Sstevel@tonic-gate } 44147c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 44157c478bd9Sstevel@tonic-gate 44167c478bd9Sstevel@tonic-gate default: 44177c478bd9Sstevel@tonic-gate sbp->sb_flags &= ~SBD_BOARD_STATUS_CACHED; 44187c478bd9Sstevel@tonic-gate dstatp->s_board = sbp->sb_num; 44197c478bd9Sstevel@tonic-gate dstatp->s_ostate = ostate_cvt(sbp->sb_state); 44207c478bd9Sstevel@tonic-gate dstatp->s_time = sbp->sb_time; 44217c478bd9Sstevel@tonic-gate 44227c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 44237c478bd9Sstevel@tonic-gate 44247c478bd9Sstevel@tonic-gate if (sbdp_get_board_status(hdp, dstatp) != 0) { 44257c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 44267c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 44277c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 44287c478bd9Sstevel@tonic-gate if (sz32 != 0) 44297c478bd9Sstevel@tonic-gate kmem_free(dstat32p, sz32); 44307c478bd9Sstevel@tonic-gate #endif 44317c478bd9Sstevel@tonic-gate kmem_free(dstatp, sz); 44327c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_flags_mutex); 44337c478bd9Sstevel@tonic-gate return; 44347c478bd9Sstevel@tonic-gate } 44357c478bd9Sstevel@tonic-gate /* 44367c478bd9Sstevel@tonic-gate * Do not cache status if the busy flag has 44377c478bd9Sstevel@tonic-gate * been set by the call to sbdp_get_board_status(). 44387c478bd9Sstevel@tonic-gate */ 44397c478bd9Sstevel@tonic-gate if (!dstatp->s_busy) { 44407c478bd9Sstevel@tonic-gate /* Can get board busy flag now */ 44417c478bd9Sstevel@tonic-gate dstatp->s_busy = sbp->sb_busy; 44427c478bd9Sstevel@tonic-gate sbp->sb_cond = (sbd_cond_t)dstatp->s_cond; 44437c478bd9Sstevel@tonic-gate bcopy(dstatp, &sbp->sb_stat, 44447c478bd9Sstevel@tonic-gate sizeof (sbd_stat_t)); 44457c478bd9Sstevel@tonic-gate sbp->sb_flags |= SBD_BOARD_STATUS_CACHED; 44467c478bd9Sstevel@tonic-gate } 44477c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 44487c478bd9Sstevel@tonic-gate break; 44497c478bd9Sstevel@tonic-gate } 44507c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_flags_mutex); 44517c478bd9Sstevel@tonic-gate 44527c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) 44537c478bd9Sstevel@tonic-gate if ((nstat = sbd_cpu_flags(hp, devset, devstatp)) > 0) { 44547c478bd9Sstevel@tonic-gate dstatp->s_nstat += nstat; 44557c478bd9Sstevel@tonic-gate devstatp += nstat; 44567c478bd9Sstevel@tonic-gate } 44577c478bd9Sstevel@tonic-gate 44587c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) 44597c478bd9Sstevel@tonic-gate if ((nstat = sbd_mem_status(hp, devset, devstatp)) > 0) { 44607c478bd9Sstevel@tonic-gate dstatp->s_nstat += nstat; 44617c478bd9Sstevel@tonic-gate devstatp += nstat; 44627c478bd9Sstevel@tonic-gate } 44637c478bd9Sstevel@tonic-gate 44647c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) 44657c478bd9Sstevel@tonic-gate if ((nstat = sbd_io_status(hp, devset, devstatp)) > 0) { 44667c478bd9Sstevel@tonic-gate dstatp->s_nstat += nstat; 44677c478bd9Sstevel@tonic-gate devstatp += nstat; 44687c478bd9Sstevel@tonic-gate } 44697c478bd9Sstevel@tonic-gate 44707c478bd9Sstevel@tonic-gate /* paranoia: detect buffer overrun */ 44717c478bd9Sstevel@tonic-gate if ((caddr_t)devstatp > ((caddr_t)dstatp) + sz) { 44727c478bd9Sstevel@tonic-gate PR_ALL("%s: buffer overrun\n", f); 44737c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 44747c478bd9Sstevel@tonic-gate if (sz32 != 0) 44757c478bd9Sstevel@tonic-gate kmem_free(dstat32p, sz32); 44767c478bd9Sstevel@tonic-gate #endif 44777c478bd9Sstevel@tonic-gate kmem_free(dstatp, sz); 44787c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EINVAL); 44797c478bd9Sstevel@tonic-gate return; 44807c478bd9Sstevel@tonic-gate } 44817c478bd9Sstevel@tonic-gate 44827c478bd9Sstevel@tonic-gate /* if necessary, move data into intermediate device status buffer */ 44837c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 44847c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 44857c478bd9Sstevel@tonic-gate int i, j; 44867c478bd9Sstevel@tonic-gate 44877c478bd9Sstevel@tonic-gate ASSERT(sz32 != 0); 44887c478bd9Sstevel@tonic-gate /* paranoia: detect buffer overrun */ 44897c478bd9Sstevel@tonic-gate if ((caddr_t)&dstat32p->s_stat[dstatp->s_nstat] > 44907c478bd9Sstevel@tonic-gate ((caddr_t)dstat32p) + sz32) { 44917c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 44927c478bd9Sstevel@tonic-gate "sbd:%s: buffer32 overrun", f); 44937c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 44947c478bd9Sstevel@tonic-gate if (sz32 != 0) 44957c478bd9Sstevel@tonic-gate kmem_free(dstat32p, sz32); 44967c478bd9Sstevel@tonic-gate #endif 44977c478bd9Sstevel@tonic-gate kmem_free(dstatp, sz); 44987c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EINVAL); 44997c478bd9Sstevel@tonic-gate return; 45007c478bd9Sstevel@tonic-gate } 45017c478bd9Sstevel@tonic-gate 45027c478bd9Sstevel@tonic-gate /* 45037c478bd9Sstevel@tonic-gate * initialize 32 bit sbd board status structure 45047c478bd9Sstevel@tonic-gate */ 45057c478bd9Sstevel@tonic-gate dstat32p->s_board = (int32_t)dstatp->s_board; 45067c478bd9Sstevel@tonic-gate dstat32p->s_nstat = (int32_t)dstatp->s_nstat; 45077c478bd9Sstevel@tonic-gate dstat32p->s_rstate = dstatp->s_rstate; 45087c478bd9Sstevel@tonic-gate dstat32p->s_ostate = dstatp->s_ostate; 45097c478bd9Sstevel@tonic-gate dstat32p->s_cond = dstatp->s_cond; 45107c478bd9Sstevel@tonic-gate dstat32p->s_busy = dstatp->s_busy; 45117c478bd9Sstevel@tonic-gate dstat32p->s_time = dstatp->s_time; 45127c478bd9Sstevel@tonic-gate dstat32p->s_assigned = dstatp->s_assigned; 45137c478bd9Sstevel@tonic-gate dstat32p->s_power = dstatp->s_power; 45147c478bd9Sstevel@tonic-gate dstat32p->s_platopts = (int32_t)dstatp->s_platopts; 45157c478bd9Sstevel@tonic-gate (void) strcpy(dstat32p->s_type, dstatp->s_type); 45167c478bd9Sstevel@tonic-gate 45177c478bd9Sstevel@tonic-gate for (i = 0; i < dstatp->s_nstat; i++) { 45187c478bd9Sstevel@tonic-gate sbd_dev_stat_t *dsp = &dstatp->s_stat[i]; 45197c478bd9Sstevel@tonic-gate sbd_dev_stat32_t *ds32p = &dstat32p->s_stat[i]; 45207c478bd9Sstevel@tonic-gate 45217c478bd9Sstevel@tonic-gate /* 45227c478bd9Sstevel@tonic-gate * copy common data for the device 45237c478bd9Sstevel@tonic-gate */ 45247c478bd9Sstevel@tonic-gate ds32p->d_cm.ci_type = (int32_t)dsp->d_cm.ci_type; 45257c478bd9Sstevel@tonic-gate ds32p->d_cm.ci_unit = (int32_t)dsp->d_cm.ci_unit; 45267c478bd9Sstevel@tonic-gate ds32p->d_cm.c_ostate = (int32_t)dsp->d_cm.c_ostate; 45277c478bd9Sstevel@tonic-gate ds32p->d_cm.c_cond = (int32_t)dsp->d_cm.c_cond; 45287c478bd9Sstevel@tonic-gate ds32p->d_cm.c_busy = (int32_t)dsp->d_cm.c_busy; 45297c478bd9Sstevel@tonic-gate ds32p->d_cm.c_time = (time32_t)dsp->d_cm.c_time; 45307c478bd9Sstevel@tonic-gate ds32p->d_cm.c_sflags = (int32_t)dsp->d_cm.c_sflags; 45317c478bd9Sstevel@tonic-gate (void) strcpy(ds32p->d_cm.ci_name, dsp->d_cm.ci_name); 45327c478bd9Sstevel@tonic-gate 45337c478bd9Sstevel@tonic-gate /* copy type specific data for the device */ 45347c478bd9Sstevel@tonic-gate switch (dsp->d_cm.ci_type) { 45357c478bd9Sstevel@tonic-gate 45367c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 45377c478bd9Sstevel@tonic-gate ds32p->d_cpu.cs_isbootproc = 45387c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cpu.cs_isbootproc; 45397c478bd9Sstevel@tonic-gate ds32p->d_cpu.cs_cpuid = 45407c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cpu.cs_cpuid; 45417c478bd9Sstevel@tonic-gate ds32p->d_cpu.cs_speed = 45427c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cpu.cs_speed; 45437c478bd9Sstevel@tonic-gate ds32p->d_cpu.cs_ecache = 45447c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cpu.cs_ecache; 45457c478bd9Sstevel@tonic-gate break; 45467c478bd9Sstevel@tonic-gate 45477c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 45487c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_type = 45497c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_type; 45507c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_ostate = 45517c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_ostate; 45527c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_cond = 45537c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_cond; 45547c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_interleave = 45557c478bd9Sstevel@tonic-gate (uint32_t)dsp->d_mem.ms_interleave; 45567c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_basepfn = 45577c478bd9Sstevel@tonic-gate (uint32_t)dsp->d_mem.ms_basepfn; 45587c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_totpages = 45597c478bd9Sstevel@tonic-gate (uint32_t)dsp->d_mem.ms_totpages; 45607c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_detpages = 45617c478bd9Sstevel@tonic-gate (uint32_t)dsp->d_mem.ms_detpages; 45627c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_pageslost = 45637c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_pageslost; 45647c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_managed_pages = 45657c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_managed_pages; 45667c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_noreloc_pages = 45677c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_noreloc_pages; 45687c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_noreloc_first = 45697c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_noreloc_first; 45707c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_noreloc_last = 45717c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_noreloc_last; 45727c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_cage_enabled = 45737c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_cage_enabled; 45747c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_peer_is_target = 45757c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_peer_is_target; 45767c478bd9Sstevel@tonic-gate (void) strcpy(ds32p->d_mem.ms_peer_ap_id, 45777c478bd9Sstevel@tonic-gate dsp->d_mem.ms_peer_ap_id); 45787c478bd9Sstevel@tonic-gate break; 45797c478bd9Sstevel@tonic-gate 45807c478bd9Sstevel@tonic-gate 45817c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 45827c478bd9Sstevel@tonic-gate 45837c478bd9Sstevel@tonic-gate ds32p->d_io.is_type = 45847c478bd9Sstevel@tonic-gate (int32_t)dsp->d_io.is_type; 45857c478bd9Sstevel@tonic-gate ds32p->d_io.is_unsafe_count = 45867c478bd9Sstevel@tonic-gate (int32_t)dsp->d_io.is_unsafe_count; 45877c478bd9Sstevel@tonic-gate ds32p->d_io.is_referenced = 45887c478bd9Sstevel@tonic-gate (int32_t)dsp->d_io.is_referenced; 45897c478bd9Sstevel@tonic-gate for (j = 0; j < SBD_MAX_UNSAFE; j++) 45907c478bd9Sstevel@tonic-gate ds32p->d_io.is_unsafe_list[j] = 45917c478bd9Sstevel@tonic-gate (int32_t) 45927c478bd9Sstevel@tonic-gate ds32p->d_io.is_unsafe_list[j]; 45937c478bd9Sstevel@tonic-gate bcopy(dsp->d_io.is_pathname, 45947c478bd9Sstevel@tonic-gate ds32p->d_io.is_pathname, MAXPATHLEN); 45957c478bd9Sstevel@tonic-gate break; 45967c478bd9Sstevel@tonic-gate 45977c478bd9Sstevel@tonic-gate case SBD_COMP_CMP: 45987c478bd9Sstevel@tonic-gate /* copy sbd_cmp_stat_t structure members */ 45997c478bd9Sstevel@tonic-gate bcopy(&dsp->d_cmp.ps_cpuid[0], 46007c478bd9Sstevel@tonic-gate &ds32p->d_cmp.ps_cpuid[0], 46017c478bd9Sstevel@tonic-gate sizeof (ds32p->d_cmp.ps_cpuid)); 46027c478bd9Sstevel@tonic-gate ds32p->d_cmp.ps_ncores = 46037c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cmp.ps_ncores; 46047c478bd9Sstevel@tonic-gate ds32p->d_cmp.ps_speed = 46057c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cmp.ps_speed; 46067c478bd9Sstevel@tonic-gate ds32p->d_cmp.ps_ecache = 46077c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cmp.ps_ecache; 46087c478bd9Sstevel@tonic-gate break; 46097c478bd9Sstevel@tonic-gate 46107c478bd9Sstevel@tonic-gate default: 46117c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 46127c478bd9Sstevel@tonic-gate "sbd:%s: unknown dev type (%d)", f, 46137c478bd9Sstevel@tonic-gate (int)dsp->d_cm.c_id.c_type); 46147c478bd9Sstevel@tonic-gate break; 46157c478bd9Sstevel@tonic-gate } 46167c478bd9Sstevel@tonic-gate } 46177c478bd9Sstevel@tonic-gate 46187c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)dstat32p, 46197c478bd9Sstevel@tonic-gate cmdp->cmd_stat.s_statp, sz32, mode) != 0) { 46207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 46217c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout status " 46227c478bd9Sstevel@tonic-gate "for board %d", f, sbp->sb_num); 46237c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EFAULT); 46247c478bd9Sstevel@tonic-gate } 46257c478bd9Sstevel@tonic-gate } else 46267c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 46277c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)dstatp, cmdp->cmd_stat.s_statp, 46287c478bd9Sstevel@tonic-gate sz, mode) != 0) { 46297c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 46307c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout status for board %d", 46317c478bd9Sstevel@tonic-gate f, sbp->sb_num); 46327c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EFAULT); 46337c478bd9Sstevel@tonic-gate } 46347c478bd9Sstevel@tonic-gate 46357c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 46367c478bd9Sstevel@tonic-gate if (sz32 != 0) 46377c478bd9Sstevel@tonic-gate kmem_free(dstat32p, sz32); 46387c478bd9Sstevel@tonic-gate #endif 46397c478bd9Sstevel@tonic-gate kmem_free(dstatp, sz); 46407c478bd9Sstevel@tonic-gate } 46417c478bd9Sstevel@tonic-gate 46427c478bd9Sstevel@tonic-gate /* 46437c478bd9Sstevel@tonic-gate * Called at driver load time to determine the state and condition 46447c478bd9Sstevel@tonic-gate * of an existing board in the system. 46457c478bd9Sstevel@tonic-gate */ 46467c478bd9Sstevel@tonic-gate static void 46477c478bd9Sstevel@tonic-gate sbd_board_discovery(sbd_board_t *sbp) 46487c478bd9Sstevel@tonic-gate { 46497c478bd9Sstevel@tonic-gate int i; 46507c478bd9Sstevel@tonic-gate dev_info_t *dip; 46517c478bd9Sstevel@tonic-gate sbd_devset_t devs_lost, devs_attached = 0; 46527c478bd9Sstevel@tonic-gate extern kmutex_t cpu_lock; 46537c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 46547c478bd9Sstevel@tonic-gate static fn_t f = "sbd_board_discovery"; 46557c478bd9Sstevel@tonic-gate sbderror_t error, *ep; 46567c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 46577c478bd9Sstevel@tonic-gate 46587c478bd9Sstevel@tonic-gate if (SBD_DEVS_PRESENT(sbp) == 0) { 46597c478bd9Sstevel@tonic-gate PR_ALL("%s: board %d has no devices present\n", 46607c478bd9Sstevel@tonic-gate f, sbp->sb_num); 46617c478bd9Sstevel@tonic-gate return; 46627c478bd9Sstevel@tonic-gate } 46637c478bd9Sstevel@tonic-gate 46647c478bd9Sstevel@tonic-gate ep = &error; 46657c478bd9Sstevel@tonic-gate bzero(ep, sizeof (sbderror_t)); 46667c478bd9Sstevel@tonic-gate 46677c478bd9Sstevel@tonic-gate /* 46687c478bd9Sstevel@tonic-gate * Check for existence of cpus. 46697c478bd9Sstevel@tonic-gate */ 46707c478bd9Sstevel@tonic-gate 46717c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 46727c478bd9Sstevel@tonic-gate 46737c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 46747c478bd9Sstevel@tonic-gate processorid_t cpuid; 46757c478bd9Sstevel@tonic-gate 46767c478bd9Sstevel@tonic-gate if (!SBD_DEV_IS_PRESENT(sbp, SBD_COMP_CPU, i)) 46777c478bd9Sstevel@tonic-gate continue; 46787c478bd9Sstevel@tonic-gate 46797c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_CPU)][i]; 46807c478bd9Sstevel@tonic-gate 46817c478bd9Sstevel@tonic-gate if (dip != NULL) { 46827c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 46837c478bd9Sstevel@tonic-gate 46847c478bd9Sstevel@tonic-gate if (cpuid < 0) { 46857c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, 46867c478bd9Sstevel@tonic-gate ep); 46877c478bd9Sstevel@tonic-gate continue; 46887c478bd9Sstevel@tonic-gate } 46897c478bd9Sstevel@tonic-gate 46907c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); /* needed to call cpu_get() */ 46917c478bd9Sstevel@tonic-gate if (cpu_get(cpuid)) { 46927c478bd9Sstevel@tonic-gate SBD_DEV_SET_ATTACHED(sbp, SBD_COMP_CPU, i); 46937c478bd9Sstevel@tonic-gate DEVSET_ADD(devs_attached, SBD_COMP_CPU, i); 46947c478bd9Sstevel@tonic-gate PR_ALL("%s: board %d, cpuid %d - attached\n", 46957c478bd9Sstevel@tonic-gate f, sbp->sb_num, cpuid); 46967c478bd9Sstevel@tonic-gate } 46977c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 46987c478bd9Sstevel@tonic-gate sbd_init_cpu_unit(sbp, i); 46997c478bd9Sstevel@tonic-gate } 47007c478bd9Sstevel@tonic-gate } 47017c478bd9Sstevel@tonic-gate 47027c478bd9Sstevel@tonic-gate /* 47037c478bd9Sstevel@tonic-gate * Check for existence of memory. 47047c478bd9Sstevel@tonic-gate */ 47057c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 47067c478bd9Sstevel@tonic-gate uint64_t basepa, endpa; 47077c478bd9Sstevel@tonic-gate struct memlist *ml; 47087c478bd9Sstevel@tonic-gate extern struct memlist *phys_install; 47097c478bd9Sstevel@tonic-gate 47107c478bd9Sstevel@tonic-gate if (!SBD_DEV_IS_PRESENT(sbp, SBD_COMP_MEM, i)) 47117c478bd9Sstevel@tonic-gate continue; 47127c478bd9Sstevel@tonic-gate 47137c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_MEM)][i]; 47147c478bd9Sstevel@tonic-gate if (dip == NULL) 47157c478bd9Sstevel@tonic-gate continue; 47167c478bd9Sstevel@tonic-gate 47177c478bd9Sstevel@tonic-gate if (sbdphw_get_base_physaddr(hdp, dip, &basepa)) { 47187c478bd9Sstevel@tonic-gate /* omit phantom memory controllers on I/O boards */ 47197c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_MEM, i)) { 47207c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_ndev != 0); 47217c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_MEM, i); 47227c478bd9Sstevel@tonic-gate sbp->sb_ndev--; 47237c478bd9Sstevel@tonic-gate } 47247c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_MEM)][i] = NULL; 47257c478bd9Sstevel@tonic-gate continue; 47267c478bd9Sstevel@tonic-gate } 47277c478bd9Sstevel@tonic-gate 47287c478bd9Sstevel@tonic-gate /* 47297c478bd9Sstevel@tonic-gate * basepa may not be on a alignment boundary, make it so. 47307c478bd9Sstevel@tonic-gate */ 47317c478bd9Sstevel@tonic-gate if (sbdp_get_mem_alignment(hdp, dip, &endpa)) { 47327c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s sbdp_get_mem_alignment fail", f); 47337c478bd9Sstevel@tonic-gate continue; 47347c478bd9Sstevel@tonic-gate } 47357c478bd9Sstevel@tonic-gate 47367c478bd9Sstevel@tonic-gate basepa &= ~(endpa - 1); 47377c478bd9Sstevel@tonic-gate endpa += basepa; 47387c478bd9Sstevel@tonic-gate 47397c478bd9Sstevel@tonic-gate /* 47407c478bd9Sstevel@tonic-gate * Check if base address is in phys_install. 47417c478bd9Sstevel@tonic-gate */ 47427c478bd9Sstevel@tonic-gate memlist_read_lock(); 4743*56f33205SJonathan Adams for (ml = phys_install; ml; ml = ml->ml_next) 4744*56f33205SJonathan Adams if ((endpa <= ml->ml_address) || 4745*56f33205SJonathan Adams (basepa >= (ml->ml_address + ml->ml_size))) 47467c478bd9Sstevel@tonic-gate continue; 47477c478bd9Sstevel@tonic-gate else 47487c478bd9Sstevel@tonic-gate break; 47497c478bd9Sstevel@tonic-gate memlist_read_unlock(); 47507c478bd9Sstevel@tonic-gate 47517c478bd9Sstevel@tonic-gate if (ml) { 47527c478bd9Sstevel@tonic-gate SBD_DEV_SET_ATTACHED(sbp, SBD_COMP_MEM, i); 47537c478bd9Sstevel@tonic-gate DEVSET_ADD(devs_attached, SBD_COMP_MEM, i); 47547c478bd9Sstevel@tonic-gate PR_ALL("%s: board %d, mem-unit %d - attached\n", 47557c478bd9Sstevel@tonic-gate f, sbp->sb_num, i); 47567c478bd9Sstevel@tonic-gate } 47577c478bd9Sstevel@tonic-gate sbd_init_mem_unit(sbp, i, ep); 47587c478bd9Sstevel@tonic-gate } 47597c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 47607c478bd9Sstevel@tonic-gate 47617c478bd9Sstevel@tonic-gate /* 47627c478bd9Sstevel@tonic-gate * If so far we have found an error, we just log it but continue 47637c478bd9Sstevel@tonic-gate */ 47647c478bd9Sstevel@tonic-gate if (SBD_GET_ERRNO(ep) != 0) 47657c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s errno has occurred: errno %d", f, 47667c478bd9Sstevel@tonic-gate SBD_GET_ERRNO(ep)); 47677c478bd9Sstevel@tonic-gate 47687c478bd9Sstevel@tonic-gate /* 47697c478bd9Sstevel@tonic-gate * Check for i/o state. 47707c478bd9Sstevel@tonic-gate */ 47717c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 47727c478bd9Sstevel@tonic-gate 47737c478bd9Sstevel@tonic-gate if (!SBD_DEV_IS_PRESENT(sbp, SBD_COMP_IO, i)) 47747c478bd9Sstevel@tonic-gate continue; 47757c478bd9Sstevel@tonic-gate 47767c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][i]; 47777c478bd9Sstevel@tonic-gate if (dip == NULL) 47787c478bd9Sstevel@tonic-gate continue; 47797c478bd9Sstevel@tonic-gate 47807c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(dip)); 47817c478bd9Sstevel@tonic-gate 47827c478bd9Sstevel@tonic-gate /* 47837c478bd9Sstevel@tonic-gate * XXX Is the devstate check needed ? 47847c478bd9Sstevel@tonic-gate */ 4785737d277aScth if (i_ddi_devi_attached(dip) || 47867c478bd9Sstevel@tonic-gate ddi_get_devstate(dip) == DDI_DEVSTATE_UP) { 47877c478bd9Sstevel@tonic-gate 47887c478bd9Sstevel@tonic-gate /* 47897c478bd9Sstevel@tonic-gate * Found it! 47907c478bd9Sstevel@tonic-gate */ 47917c478bd9Sstevel@tonic-gate SBD_DEV_SET_ATTACHED(sbp, SBD_COMP_IO, i); 47927c478bd9Sstevel@tonic-gate DEVSET_ADD(devs_attached, SBD_COMP_IO, i); 47937c478bd9Sstevel@tonic-gate PR_ALL("%s: board %d, io-unit %d - attached\n", 47947c478bd9Sstevel@tonic-gate f, sbp->sb_num, i); 47957c478bd9Sstevel@tonic-gate } 47967c478bd9Sstevel@tonic-gate sbd_init_io_unit(sbp, i); 47977c478bd9Sstevel@tonic-gate } 47987c478bd9Sstevel@tonic-gate 47997c478bd9Sstevel@tonic-gate SBD_DEVS_CONFIGURE(sbp, devs_attached); 48007c478bd9Sstevel@tonic-gate if (devs_attached && ((devs_lost = SBD_DEVS_UNATTACHED(sbp)) != 0)) { 48017c478bd9Sstevel@tonic-gate int ut; 48027c478bd9Sstevel@tonic-gate /* 48037c478bd9Sstevel@tonic-gate * A prior comment stated that a partially configured 48047c478bd9Sstevel@tonic-gate * board was not permitted. The Serengeti architecture 48057c478bd9Sstevel@tonic-gate * makes this possible, so the SB_DEVS_DISCONNECT 48067c478bd9Sstevel@tonic-gate * at the end of this block has been removed. 48077c478bd9Sstevel@tonic-gate */ 48087c478bd9Sstevel@tonic-gate 48097c478bd9Sstevel@tonic-gate PR_ALL("%s: some devices not configured (0x%x)...\n", 48107c478bd9Sstevel@tonic-gate f, devs_lost); 48117c478bd9Sstevel@tonic-gate 48127c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_CPU_UNITS_PER_BOARD; ut++) 48137c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devs_lost, SBD_COMP_CPU, ut)) { 48147c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, 48157c478bd9Sstevel@tonic-gate ut, SBD_STATE_UNCONFIGURED); 48167c478bd9Sstevel@tonic-gate } 48177c478bd9Sstevel@tonic-gate 48187c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_MEM_UNITS_PER_BOARD; ut++) 48197c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devs_lost, SBD_COMP_MEM, ut)) { 48207c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_MEM, 48217c478bd9Sstevel@tonic-gate ut, SBD_STATE_UNCONFIGURED); 48227c478bd9Sstevel@tonic-gate } 48237c478bd9Sstevel@tonic-gate 48247c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_IO_UNITS_PER_BOARD; ut++) 48257c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devs_lost, SBD_COMP_IO, ut)) { 48267c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, 48277c478bd9Sstevel@tonic-gate ut, SBD_STATE_UNCONFIGURED); 48287c478bd9Sstevel@tonic-gate } 48297c478bd9Sstevel@tonic-gate } 48307c478bd9Sstevel@tonic-gate } 48317c478bd9Sstevel@tonic-gate 48327c478bd9Sstevel@tonic-gate static int 48337c478bd9Sstevel@tonic-gate hold_rele_branch(dev_info_t *rdip, void *arg) 48347c478bd9Sstevel@tonic-gate { 48357c478bd9Sstevel@tonic-gate walk_tree_t *wp = (walk_tree_t *)arg; 48367c478bd9Sstevel@tonic-gate 48377c478bd9Sstevel@tonic-gate ASSERT(wp && (wp->hold == 0 || wp->hold == 1)); 48387c478bd9Sstevel@tonic-gate 48397c478bd9Sstevel@tonic-gate switch (get_node_type(wp->sbp, rdip, NULL)) { 48407c478bd9Sstevel@tonic-gate case SBD_COMP_CMP: 48417c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 48427c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 48437c478bd9Sstevel@tonic-gate break; 48447c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 48457c478bd9Sstevel@tonic-gate 48467c478bd9Sstevel@tonic-gate /* 48477c478bd9Sstevel@tonic-gate * All CPU nodes under CMP nodes should have 48487c478bd9Sstevel@tonic-gate * gotten pruned when the CMP node was first 48497c478bd9Sstevel@tonic-gate * encountered. 48507c478bd9Sstevel@tonic-gate */ 48517c478bd9Sstevel@tonic-gate ASSERT(!sbd_is_cmp_child(rdip)); 48527c478bd9Sstevel@tonic-gate 48537c478bd9Sstevel@tonic-gate break; 48547c478bd9Sstevel@tonic-gate 48557c478bd9Sstevel@tonic-gate case SBD_COMP_UNKNOWN: 48567c478bd9Sstevel@tonic-gate /* Not of interest to us */ 48577c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 48587c478bd9Sstevel@tonic-gate default: 48597c478bd9Sstevel@tonic-gate ASSERT(0); 48607c478bd9Sstevel@tonic-gate return (DDI_WALK_PRUNECHILD); 48617c478bd9Sstevel@tonic-gate } 48627c478bd9Sstevel@tonic-gate 48637c478bd9Sstevel@tonic-gate if (wp->hold) { 48647c478bd9Sstevel@tonic-gate ASSERT(!e_ddi_branch_held(rdip)); 48657c478bd9Sstevel@tonic-gate e_ddi_branch_hold(rdip); 48667c478bd9Sstevel@tonic-gate } else { 48677c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(rdip)); 48687c478bd9Sstevel@tonic-gate e_ddi_branch_rele(rdip); 48697c478bd9Sstevel@tonic-gate } 48707c478bd9Sstevel@tonic-gate 48717c478bd9Sstevel@tonic-gate return (DDI_WALK_PRUNECHILD); 48727c478bd9Sstevel@tonic-gate } 48737c478bd9Sstevel@tonic-gate 48747c478bd9Sstevel@tonic-gate static void 48757c478bd9Sstevel@tonic-gate sbd_board_init(sbd_board_t *sbp, sbd_softstate_t *softsp, 48767c478bd9Sstevel@tonic-gate int bd, dev_info_t *top_dip, int wnode) 48777c478bd9Sstevel@tonic-gate { 48787c478bd9Sstevel@tonic-gate int i; 48797c478bd9Sstevel@tonic-gate dev_info_t *pdip; 48807c478bd9Sstevel@tonic-gate int circ; 48817c478bd9Sstevel@tonic-gate walk_tree_t walk = {0}; 48827c478bd9Sstevel@tonic-gate 48837c478bd9Sstevel@tonic-gate mutex_init(&sbp->sb_mutex, NULL, MUTEX_DRIVER, NULL); 48847c478bd9Sstevel@tonic-gate mutex_init(&sbp->sb_flags_mutex, NULL, MUTEX_DRIVER, NULL); 48857c478bd9Sstevel@tonic-gate mutex_init(&sbp->sb_slock, NULL, MUTEX_DRIVER, NULL); 48867c478bd9Sstevel@tonic-gate 48877c478bd9Sstevel@tonic-gate sbp->sb_ref = 0; 48887c478bd9Sstevel@tonic-gate sbp->sb_num = bd; 48897c478bd9Sstevel@tonic-gate sbp->sb_time = gethrestime_sec(); 48907c478bd9Sstevel@tonic-gate /* 48917c478bd9Sstevel@tonic-gate * For serengeti, top_dip doesn't need to be held because 48927c478bd9Sstevel@tonic-gate * sbp i.e. sbd_board_t will be destroyed in sbd_teardown_instance() 48937c478bd9Sstevel@tonic-gate * before top_dip detaches. For Daktari, top_dip is the 48947c478bd9Sstevel@tonic-gate * root node which never has to be held. 48957c478bd9Sstevel@tonic-gate */ 48967c478bd9Sstevel@tonic-gate sbp->sb_topdip = top_dip; 48977c478bd9Sstevel@tonic-gate sbp->sb_cpuid = -1; 48987c478bd9Sstevel@tonic-gate sbp->sb_softsp = (void *) softsp; 48997c478bd9Sstevel@tonic-gate sbp->sb_cond = SBD_COND_UNKNOWN; 49007c478bd9Sstevel@tonic-gate sbp->sb_wnode = wnode; 49017c478bd9Sstevel@tonic-gate sbp->sb_memaccess_ok = 1; 49027c478bd9Sstevel@tonic-gate 49037c478bd9Sstevel@tonic-gate ASSERT(MAX_IO_UNITS_PER_BOARD <= SBD_MAX_UNITS_PER_BOARD); 49047c478bd9Sstevel@tonic-gate ASSERT(MAX_CPU_UNITS_PER_BOARD <= SBD_MAX_UNITS_PER_BOARD); 49057c478bd9Sstevel@tonic-gate ASSERT(MAX_MEM_UNITS_PER_BOARD <= SBD_MAX_UNITS_PER_BOARD); 49067c478bd9Sstevel@tonic-gate 49077c478bd9Sstevel@tonic-gate /* 49087c478bd9Sstevel@tonic-gate * Allocate the devlist for cpus. 49097c478bd9Sstevel@tonic-gate */ 49107c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_CPU)] = GETSTRUCT(dev_info_t *, 49117c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD); 49127c478bd9Sstevel@tonic-gate 49137c478bd9Sstevel@tonic-gate /* 49147c478bd9Sstevel@tonic-gate * Allocate the devlist for mem. 49157c478bd9Sstevel@tonic-gate */ 49167c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_MEM)] = GETSTRUCT(dev_info_t *, 49177c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD); 49187c478bd9Sstevel@tonic-gate 49197c478bd9Sstevel@tonic-gate /* 49207c478bd9Sstevel@tonic-gate * Allocate the devlist for io. 49217c478bd9Sstevel@tonic-gate */ 49227c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_IO)] = GETSTRUCT(dev_info_t *, 49237c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD); 49247c478bd9Sstevel@tonic-gate 49257c478bd9Sstevel@tonic-gate 49267c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_CPU)] = GETSTRUCT(sbd_dev_unit_t, 49277c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD); 49287c478bd9Sstevel@tonic-gate 49297c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_MEM)] = GETSTRUCT(sbd_dev_unit_t, 49307c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD); 49317c478bd9Sstevel@tonic-gate 49327c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_IO)] = GETSTRUCT(sbd_dev_unit_t, 49337c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD); 49347c478bd9Sstevel@tonic-gate 49357c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 49367c478bd9Sstevel@tonic-gate sbp->sb_cpupath[i] = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 49377c478bd9Sstevel@tonic-gate } 49387c478bd9Sstevel@tonic-gate 49397c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 49407c478bd9Sstevel@tonic-gate sbp->sb_mempath[i] = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 49417c478bd9Sstevel@tonic-gate } 49427c478bd9Sstevel@tonic-gate 49437c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 49447c478bd9Sstevel@tonic-gate sbp->sb_iopath[i] = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 49457c478bd9Sstevel@tonic-gate } 49467c478bd9Sstevel@tonic-gate 49477c478bd9Sstevel@tonic-gate /* 49487c478bd9Sstevel@tonic-gate * Walk the device tree, find all top dips on this board and 49497c478bd9Sstevel@tonic-gate * hold the branches rooted at them 49507c478bd9Sstevel@tonic-gate */ 49517c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_topdip); 49527c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(sbp->sb_topdip); 49537c478bd9Sstevel@tonic-gate if (pdip) 49547c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &circ); 49557c478bd9Sstevel@tonic-gate walk.sbp = sbp; 49567c478bd9Sstevel@tonic-gate walk.hold = 1; 49577c478bd9Sstevel@tonic-gate ddi_walk_devs(sbp->sb_topdip, hold_rele_branch, (void *)&walk); 49587c478bd9Sstevel@tonic-gate if (pdip) 49597c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, circ); 49607c478bd9Sstevel@tonic-gate 49617c478bd9Sstevel@tonic-gate /* 49627c478bd9Sstevel@tonic-gate * Initialize the devlists 49637c478bd9Sstevel@tonic-gate */ 49647c478bd9Sstevel@tonic-gate if (sbd_init_devlists(sbp) == 0) { 49657c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_EMPTY); 49667c478bd9Sstevel@tonic-gate } else { 49677c478bd9Sstevel@tonic-gate /* 49687c478bd9Sstevel@tonic-gate * Couldn't have made it down here without 49697c478bd9Sstevel@tonic-gate * having found at least one device. 49707c478bd9Sstevel@tonic-gate */ 49717c478bd9Sstevel@tonic-gate ASSERT(SBD_DEVS_PRESENT(sbp) != 0); 49727c478bd9Sstevel@tonic-gate /* 49737c478bd9Sstevel@tonic-gate * Check the state of any possible devices on the 49747c478bd9Sstevel@tonic-gate * board. 49757c478bd9Sstevel@tonic-gate */ 49767c478bd9Sstevel@tonic-gate sbd_board_discovery(sbp); 49777c478bd9Sstevel@tonic-gate 49787c478bd9Sstevel@tonic-gate if (SBD_DEVS_UNATTACHED(sbp) == 0) { 49797c478bd9Sstevel@tonic-gate /* 49807c478bd9Sstevel@tonic-gate * The board has no unattached devices, therefore 49817c478bd9Sstevel@tonic-gate * by reason of insanity it must be configured! 49827c478bd9Sstevel@tonic-gate */ 49837c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONFIGURED); 49847c478bd9Sstevel@tonic-gate sbp->sb_cond = SBD_COND_OK; 49857c478bd9Sstevel@tonic-gate } else if (SBD_DEVS_ATTACHED(sbp)) { 49867c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_PARTIAL); 49877c478bd9Sstevel@tonic-gate } else { 49887c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONNECTED); 49897c478bd9Sstevel@tonic-gate } 49907c478bd9Sstevel@tonic-gate } 49917c478bd9Sstevel@tonic-gate } 49927c478bd9Sstevel@tonic-gate 49937c478bd9Sstevel@tonic-gate static void 49947c478bd9Sstevel@tonic-gate sbd_board_destroy(sbd_board_t *sbp) 49957c478bd9Sstevel@tonic-gate { 49967c478bd9Sstevel@tonic-gate int i; 49977c478bd9Sstevel@tonic-gate dev_info_t *pdip; 49987c478bd9Sstevel@tonic-gate int circ; 49997c478bd9Sstevel@tonic-gate walk_tree_t walk = {0}; 50007c478bd9Sstevel@tonic-gate 50017c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_EMPTY); 50027c478bd9Sstevel@tonic-gate 50037c478bd9Sstevel@tonic-gate #ifdef DEBUG 50047c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 50057c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 50067c478bd9Sstevel@tonic-gate 50077c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, i); 50087c478bd9Sstevel@tonic-gate ASSERT(mp->sbm_mlist == NULL); 50097c478bd9Sstevel@tonic-gate } 50107c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 50117c478bd9Sstevel@tonic-gate 50127c478bd9Sstevel@tonic-gate /* 50137c478bd9Sstevel@tonic-gate * Free up MEM unit structs. 50147c478bd9Sstevel@tonic-gate */ 50157c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_dev[NIX(SBD_COMP_MEM)], 50167c478bd9Sstevel@tonic-gate sbd_dev_unit_t, MAX_MEM_UNITS_PER_BOARD); 50177c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_MEM)] = NULL; 50187c478bd9Sstevel@tonic-gate 50197c478bd9Sstevel@tonic-gate /* 50207c478bd9Sstevel@tonic-gate * Free up CPU unit structs. 50217c478bd9Sstevel@tonic-gate */ 50227c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_dev[NIX(SBD_COMP_CPU)], 50237c478bd9Sstevel@tonic-gate sbd_dev_unit_t, MAX_CPU_UNITS_PER_BOARD); 50247c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_CPU)] = NULL; 50257c478bd9Sstevel@tonic-gate 50267c478bd9Sstevel@tonic-gate /* 50277c478bd9Sstevel@tonic-gate * Free up IO unit structs. 50287c478bd9Sstevel@tonic-gate */ 50297c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_dev[NIX(SBD_COMP_IO)], 50307c478bd9Sstevel@tonic-gate sbd_dev_unit_t, MAX_IO_UNITS_PER_BOARD); 50317c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_IO)] = NULL; 50327c478bd9Sstevel@tonic-gate 50337c478bd9Sstevel@tonic-gate /* 50347c478bd9Sstevel@tonic-gate * free up CPU devlists. 50357c478bd9Sstevel@tonic-gate */ 50367c478bd9Sstevel@tonic-gate 50377c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 50387c478bd9Sstevel@tonic-gate kmem_free((caddr_t)sbp->sb_cpupath[i], MAXPATHLEN); 50397c478bd9Sstevel@tonic-gate } 50407c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_devlist[NIX(SBD_COMP_CPU)], dev_info_t *, 50417c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD); 50427c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_CPU)] = NULL; 50437c478bd9Sstevel@tonic-gate 50447c478bd9Sstevel@tonic-gate /* 50457c478bd9Sstevel@tonic-gate * free up MEM devlists. 50467c478bd9Sstevel@tonic-gate */ 50477c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 50487c478bd9Sstevel@tonic-gate kmem_free((caddr_t)sbp->sb_mempath[i], MAXPATHLEN); 50497c478bd9Sstevel@tonic-gate } 50507c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_devlist[NIX(SBD_COMP_MEM)], dev_info_t *, 50517c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD); 50527c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_MEM)] = NULL; 50537c478bd9Sstevel@tonic-gate 50547c478bd9Sstevel@tonic-gate /* 50557c478bd9Sstevel@tonic-gate * free up IO devlists. 50567c478bd9Sstevel@tonic-gate */ 50577c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 50587c478bd9Sstevel@tonic-gate kmem_free((caddr_t)sbp->sb_iopath[i], MAXPATHLEN); 50597c478bd9Sstevel@tonic-gate } 50607c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_devlist[NIX(SBD_COMP_IO)], dev_info_t *, 50617c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD); 50627c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_IO)] = NULL; 50637c478bd9Sstevel@tonic-gate 50647c478bd9Sstevel@tonic-gate /* 50657c478bd9Sstevel@tonic-gate * Release all branches held earlier 50667c478bd9Sstevel@tonic-gate */ 50677c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_topdip); 50687c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(sbp->sb_topdip); 50697c478bd9Sstevel@tonic-gate if (pdip) 50707c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &circ); 50717c478bd9Sstevel@tonic-gate walk.sbp = sbp; 50727c478bd9Sstevel@tonic-gate walk.hold = 0; 50737c478bd9Sstevel@tonic-gate ddi_walk_devs(sbp->sb_topdip, hold_rele_branch, (void *)&walk); 50747c478bd9Sstevel@tonic-gate if (pdip) 50757c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, circ); 50767c478bd9Sstevel@tonic-gate 50777c478bd9Sstevel@tonic-gate mutex_destroy(&sbp->sb_slock); 50787c478bd9Sstevel@tonic-gate mutex_destroy(&sbp->sb_flags_mutex); 50797c478bd9Sstevel@tonic-gate mutex_destroy(&sbp->sb_mutex); 50807c478bd9Sstevel@tonic-gate } 50817c478bd9Sstevel@tonic-gate 50827c478bd9Sstevel@tonic-gate sbd_comp_type_t 50837c478bd9Sstevel@tonic-gate sbd_cm_type(char *name) 50847c478bd9Sstevel@tonic-gate { 50857c478bd9Sstevel@tonic-gate sbd_comp_type_t type = SBD_COMP_UNKNOWN; 50867c478bd9Sstevel@tonic-gate int i; 50877c478bd9Sstevel@tonic-gate 50887c478bd9Sstevel@tonic-gate /* look up type in table */ 50897c478bd9Sstevel@tonic-gate for (i = 0; SBD_COMP(i) != SBD_COMP_UNKNOWN; i++) { 50907c478bd9Sstevel@tonic-gate if (strcmp(name, SBD_OTYPE(i)) == 0) { 50917c478bd9Sstevel@tonic-gate type = SBD_COMP(i); 50927c478bd9Sstevel@tonic-gate break; 50937c478bd9Sstevel@tonic-gate } 50947c478bd9Sstevel@tonic-gate } 50957c478bd9Sstevel@tonic-gate 50967c478bd9Sstevel@tonic-gate return (type); 50977c478bd9Sstevel@tonic-gate } 50987c478bd9Sstevel@tonic-gate 50997c478bd9Sstevel@tonic-gate /* 51007c478bd9Sstevel@tonic-gate * There are certain cases where obp marks components as failed 51017c478bd9Sstevel@tonic-gate * If the status is ok the node won't have any status property. It 51027c478bd9Sstevel@tonic-gate * is only there if the status is other than ok. 51037c478bd9Sstevel@tonic-gate * 51047c478bd9Sstevel@tonic-gate * The translation is as follows: 51057c478bd9Sstevel@tonic-gate * If there is no status prop, the the cond is SBD_COND_OK 51067c478bd9Sstevel@tonic-gate * If we find a status prop but can't get to it then cond is SBD_COND_UNKNOWN 51077c478bd9Sstevel@tonic-gate * if we find a stat and it is failed the cond is SBD_COND_FAILED 51087c478bd9Sstevel@tonic-gate * If the stat is disabled, the cond is SBD_COND_UNUSABLE 51097c478bd9Sstevel@tonic-gate * Otherwise we return con as SBD_COND_OK 51107c478bd9Sstevel@tonic-gate */ 51117c478bd9Sstevel@tonic-gate sbd_cond_t 51127c478bd9Sstevel@tonic-gate sbd_get_comp_cond(dev_info_t *dip) 51137c478bd9Sstevel@tonic-gate { 51147c478bd9Sstevel@tonic-gate int len; 51157c478bd9Sstevel@tonic-gate char *status_buf; 51167c478bd9Sstevel@tonic-gate static const char *status = "status"; 51177c478bd9Sstevel@tonic-gate static const char *failed = "fail"; 51187c478bd9Sstevel@tonic-gate static const char *disabled = "disabled"; 51197c478bd9Sstevel@tonic-gate 51207c478bd9Sstevel@tonic-gate if (dip == NULL) { 51217c478bd9Sstevel@tonic-gate PR_BYP("dip is NULL\n"); 51227c478bd9Sstevel@tonic-gate return (SBD_COND_UNKNOWN); 51237c478bd9Sstevel@tonic-gate } 51247c478bd9Sstevel@tonic-gate 512525e8c5aaSvikram /* 512625e8c5aaSvikram * If retired, return FAILED 512725e8c5aaSvikram */ 512825e8c5aaSvikram if (DEVI(dip)->devi_flags & DEVI_RETIRED) { 512925e8c5aaSvikram PR_CPU("dip is retired\n"); 513025e8c5aaSvikram return (SBD_COND_FAILED); 513125e8c5aaSvikram } 513225e8c5aaSvikram 51337c478bd9Sstevel@tonic-gate if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 51347c478bd9Sstevel@tonic-gate (char *)status, &len) != DDI_PROP_SUCCESS) { 51357c478bd9Sstevel@tonic-gate PR_CPU("status in sbd is ok\n"); 51367c478bd9Sstevel@tonic-gate return (SBD_COND_OK); 51377c478bd9Sstevel@tonic-gate } 51387c478bd9Sstevel@tonic-gate 51397c478bd9Sstevel@tonic-gate status_buf = kmem_zalloc(sizeof (char) * OBP_MAXPROPNAME, KM_SLEEP); 5140a3282898Scth if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 51417c478bd9Sstevel@tonic-gate (char *)status, status_buf, &len) != DDI_PROP_SUCCESS) { 51427c478bd9Sstevel@tonic-gate PR_CPU("status in sbd is unknown\n"); 51437c478bd9Sstevel@tonic-gate return (SBD_COND_UNKNOWN); 51447c478bd9Sstevel@tonic-gate } 51457c478bd9Sstevel@tonic-gate 51467c478bd9Sstevel@tonic-gate if (strncmp(status_buf, failed, strlen(failed)) == 0) { 51477c478bd9Sstevel@tonic-gate PR_CPU("status in sbd is failed\n"); 51487c478bd9Sstevel@tonic-gate kmem_free(status_buf, sizeof (char) * OBP_MAXPROPNAME); 51497c478bd9Sstevel@tonic-gate return (SBD_COND_FAILED); 51507c478bd9Sstevel@tonic-gate } 51517c478bd9Sstevel@tonic-gate 51527c478bd9Sstevel@tonic-gate if (strcmp(status_buf, disabled) == 0) { 51537c478bd9Sstevel@tonic-gate PR_CPU("status in sbd is unusable\n"); 51547c478bd9Sstevel@tonic-gate kmem_free(status_buf, sizeof (char) * OBP_MAXPROPNAME); 51557c478bd9Sstevel@tonic-gate return (SBD_COND_UNUSABLE); 51567c478bd9Sstevel@tonic-gate } 51577c478bd9Sstevel@tonic-gate 51587c478bd9Sstevel@tonic-gate kmem_free(status_buf, sizeof (char) * OBP_MAXPROPNAME); 51597c478bd9Sstevel@tonic-gate return (SBD_COND_OK); 51607c478bd9Sstevel@tonic-gate } 51617c478bd9Sstevel@tonic-gate 51627c478bd9Sstevel@tonic-gate #ifdef SBD_DEBUG_ERRS 51637c478bd9Sstevel@tonic-gate 51647c478bd9Sstevel@tonic-gate /* function to simulate errors throughout the sbd code */ 51657c478bd9Sstevel@tonic-gate void 51667c478bd9Sstevel@tonic-gate sbd_inject_err(int error, sbderror_t *ep, int Errno, int ecode, 51677c478bd9Sstevel@tonic-gate char *rsc) 51687c478bd9Sstevel@tonic-gate { 51697c478bd9Sstevel@tonic-gate static fn_t f = "sbd_inject_err"; 51707c478bd9Sstevel@tonic-gate 51717c478bd9Sstevel@tonic-gate if (sbd_err_debug == 0) 51727c478bd9Sstevel@tonic-gate return; 51737c478bd9Sstevel@tonic-gate 51747c478bd9Sstevel@tonic-gate if (ep == NULL) { 51757c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s ep is NULL", f); 51767c478bd9Sstevel@tonic-gate return; 51777c478bd9Sstevel@tonic-gate } 51787c478bd9Sstevel@tonic-gate 51797c478bd9Sstevel@tonic-gate if (SBD_GET_ERRNO(ep) != 0) { 51807c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s errno already set to %d", f, 51817c478bd9Sstevel@tonic-gate SBD_GET_ERRNO(ep)); 51827c478bd9Sstevel@tonic-gate return; 51837c478bd9Sstevel@tonic-gate } 51847c478bd9Sstevel@tonic-gate 51857c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) != 0) { 51867c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s code already set to %d", f, 51877c478bd9Sstevel@tonic-gate SBD_GET_ERR(ep)); 51887c478bd9Sstevel@tonic-gate return; 51897c478bd9Sstevel@tonic-gate } 51907c478bd9Sstevel@tonic-gate 51917c478bd9Sstevel@tonic-gate if ((sbd_err_debug & (1 << error)) != 0) { 51927c478bd9Sstevel@tonic-gate ep->e_errno = Errno; 51937c478bd9Sstevel@tonic-gate ep->e_code = ecode; 51947c478bd9Sstevel@tonic-gate 51957c478bd9Sstevel@tonic-gate if (rsc != NULL) 51967c478bd9Sstevel@tonic-gate bcopy((caddr_t)rsc, 51977c478bd9Sstevel@tonic-gate (caddr_t)ep->e_rsc, 51987c478bd9Sstevel@tonic-gate sizeof (ep->e_rsc)); 51997c478bd9Sstevel@tonic-gate 52007c478bd9Sstevel@tonic-gate if (Errno != 0) 52017c478bd9Sstevel@tonic-gate PR_ERR_ERRNO("%s set errno to %d", f, ep->e_errno); 52027c478bd9Sstevel@tonic-gate 52037c478bd9Sstevel@tonic-gate if (ecode != 0) 52047c478bd9Sstevel@tonic-gate PR_ERR_ECODE("%s set ecode to %d", f, ep->e_code); 52057c478bd9Sstevel@tonic-gate 52067c478bd9Sstevel@tonic-gate if (rsc != NULL) 52077c478bd9Sstevel@tonic-gate PR_ERR_RSC("%s set rsc to %s", f, ep->e_rsc); 52087c478bd9Sstevel@tonic-gate } 52097c478bd9Sstevel@tonic-gate } 52107c478bd9Sstevel@tonic-gate #endif 5211