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