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