25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER START
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The contents of this file are subject to the terms of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Common Development and Distribution License (the "License").
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You may not use this file except in compliance with the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * or http://www.opensolaris.org/os/licensing.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * See the License for the specific language governing permissions
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and limitations under the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * When distributing Covered Code, include this CDDL HEADER in each
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If applicable, add the following below this CDDL HEADER, with the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fields enclosed by brackets "[]" replaced with your own identifying
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * information: Portions Copyright [yyyy] [name of copyright owner]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER END
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
88294e09b5c27cbb12b6735e2fb247a86b76666dRichard Bean * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Use is subject to license terms.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/conf.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/kmem.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/debug.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/modctl.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/autoconf.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/hwconf.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ddi_impldefs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ddi.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sunddi.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sunndi.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ndi_impldefs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/machsystm.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/fcode.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/promif.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/promimpl.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/opl_cfg.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/scfd/scfostoescf.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic unsigned int opl_cfg_inited;
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic opl_board_cfg_t opl_boards[HWD_SBS_PER_DOMAIN];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Module control operations
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern struct mod_ops mod_miscops;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct modlmisc modlmisc = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &mod_miscops, /* Type of module */
88294e09b5c27cbb12b6735e2fb247a86b76666dRichard Bean "OPL opl_cfg"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct modlinkage modlinkage = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl MODREV_1, (void *)&modlmisc, NULL
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_map_in(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_map_out(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_register_fetch(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_register_store(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_claim_memory(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_release_memory(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_vtop(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_config_child(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_get_fcode_size(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_get_fcode(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_map_phys(dev_info_t *, struct regspec *, caddr_t *,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_device_acc_attr_t *, ddi_acc_handle_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void opl_unmap_phys(ddi_acc_handle_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_get_hwd_va(dev_info_t *, fco_handle_t, fc_ci_t *);
531232457f24de82ba95346b3de302b990fe50f4mvstatic int opl_master_interrupt(dev_info_t *, fco_handle_t, fc_ci_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern int prom_get_fcode_size(char *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern int prom_get_fcode(char *, char *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
531232457f24de82ba95346b3de302b990fe50f4mvstatic int master_interrupt_init(uint32_t, uint32_t);
531232457f24de82ba95346b3de302b990fe50f4mv
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define PROBE_STR_SIZE 64
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define UNIT_ADDR_SIZE 64
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_fc_ops_t opl_fc_ops[] = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_MAP_IN, opl_map_in},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_MAP_OUT, opl_map_out},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "rx@", opl_register_fetch},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_RL_FETCH, opl_register_fetch},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_RW_FETCH, opl_register_fetch},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_RB_FETCH, opl_register_fetch},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "rx!", opl_register_store},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_RL_STORE, opl_register_store},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_RW_STORE, opl_register_store},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_RB_STORE, opl_register_store},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "claim-memory", opl_claim_memory},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "release-memory", opl_release_memory},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "vtop", opl_vtop},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_CONFIG_CHILD, opl_config_child},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_GET_FCODE_SIZE, opl_get_fcode_size},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { FC_GET_FCODE, opl_get_fcode},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "get-hwd-va", opl_get_hwd_va},
531232457f24de82ba95346b3de302b990fe50f4mv { "master-interrupt", opl_master_interrupt},
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { NULL, NULL}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern caddr_t efcode_vaddr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern int efcode_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define HWDDUMP_OFFSETS 1
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define HWDDUMP_ALL_STATUS 2
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define HWDDUMP_CHUNKS 3
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define HWDDUMP_SBP 4
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint hwddump_flags = HWDDUMP_SBP | HWDDUMP_CHUNKS;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
531232457f24de82ba95346b3de302b990fe50f4mvstatic int master_interrupt_inited = 0;
531232457f24de82ba95346b3de302b990fe50f4mv
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_init()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int err = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create a resource map for the contiguous memory allocated
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * at start-of-day in startup.c
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = ndi_ra_map_setup(ddi_root_node(), "opl-fcodemem");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (err == NDI_FAILURE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "Cannot setup resource map opl-fcodemem\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Put the allocated memory into the pool.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ndi_ra_free(ddi_root_node(), (uint64_t)efcode_vaddr,
e98fafb9956429b59c817d4fbd27720c73879203jl (uint64_t)efcode_size, "opl-fcodemem", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((err = mod_install(&modlinkage)) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "opl_cfg failed to load, error=%d", err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ndi_ra_map_destroy(ddi_root_node(), "opl-fcodemem");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_fini(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = (mod_remove(&modlinkage));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ret);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ndi_ra_map_destroy(ddi_root_node(), "opl-fcodemem");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ret);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_info(modinfop)
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstruct modinfo *modinfop;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (mod_info(&modlinkage, modinfop));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_dump_hwd(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_header_t *hdrp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_sb_status_t *statp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_domain_info_t *dinfop;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_sb_t *sbp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_chip_t *chips;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_pci_ch_t *channels;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int board, i, status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board = probe->pr_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hdrp = probe->pr_hdr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl statp = probe->pr_sb_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dinfop = probe->pr_dinfo;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbp = probe->pr_sb;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD: board %d\n", board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:magic = 0x%x\n", hdrp->hdr_magic);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:version = 0x%x.%x\n", hdrp->hdr_version.major,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hdrp->hdr_version.minor);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (hwddump_flags & HWDDUMP_OFFSETS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:status offset = 0x%x\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hdrp->hdr_sb_status_offset);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:domain offset = 0x%x\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hdrp->hdr_domain_info_offset);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:board offset = 0x%x\n", hdrp->hdr_sb_info_offset);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (hwddump_flags & HWDDUMP_SBP)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:sb_t ptr = 0x%p\n", (void *)probe->pr_sb);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (hwddump_flags & HWDDUMP_ALL_STATUS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:board status =");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (bd = 0; bd < HWD_SBS_PER_DOMAIN; bd++)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("%x ", statp->sb_status[bd]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:board status = %d\n", statp->sb_status[board]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:banner name = %s\n", dinfop->dinf_banner_name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:platform = %s\n", dinfop->dinf_platform_token);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:chip status:\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl chips = &sbp->sb_cmu.cmu_cpu_chips[0];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_CPU_CHIPS_PER_CMU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status = chips[i].chip_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("chip[%d] = ", i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (HWD_STATUS_NONE(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("none");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (HWD_STATUS_FAILED(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("fail");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (HWD_STATUS_OK(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("ok");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (hwddump_flags & HWDDUMP_CHUNKS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int chunk;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_memory_t *mem = &sbp->sb_cmu.cmu_memory;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:chunks:\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (chunk = 0; chunk < HWD_MAX_MEM_CHUNKS; chunk++)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("\t%d 0x%lx 0x%lx\n", chunk,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem->mem_chunks[chunk].chnk_start_address,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem->mem_chunks[chunk].chnk_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("HWD:channel status:\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl channels = &sbp->sb_pci_ch[0];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_PCI_CHANNELS_PER_SB; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status = channels[i].pci_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("channels[%d] = ", i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (HWD_STATUS_NONE(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("none");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (HWD_STATUS_FAILED(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("fail");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (HWD_STATUS_OK(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("ok");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("channels[%d] = ", i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status = sbp->sb_cmu.cmu_ch.chan_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (HWD_STATUS_NONE(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("none");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (HWD_STATUS_FAILED(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("fail");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (HWD_STATUS_OK(status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("ok");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl printf("\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif /* DEBUG */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef UCTEST
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * For SesamI debugging, just map the SRAM directly to a kernel
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * VA and read it out from there
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/vmem.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <vm/seg_kmem.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 0x4081F1323000LL is the HWD base address for LSB 0. But we need to map
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * at page boundaries. So, we use a base address of 0x4081F1322000LL.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Note that this has to match the HWD base pa set in .sesami-common-defs.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The size specified for the HWD in the SCF spec is 36K. But since
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we adjusted the base address by 4K, we need to use 40K for the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * mapping size to cover the HWD. And 40K is also a multiple of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * base page size.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define OPL_HWD_BASE(lsb) \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl(0x4081F1322000LL | (((uint64_t)(lsb)) << 40))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *opl_hwd_vaddr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif /* UCTEST */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the hardware descriptor from SCF.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_read_hwd(int board, hwd_header_t **hdrp, hwd_sb_status_t **statp,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_domain_info_t **dinfop, hwd_sb_t **sbp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl static int (*getinfop)(uint32_t, uint8_t, uint32_t, uint32_t *,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *) = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *hwdp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t key = KEY_ESCF; /* required value */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint8_t type = 0x40; /* SUB_OS_RECEIVE_HWD */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t transid = board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t datasize = HWD_DATA_SIZE;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_header_t *hd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_sb_status_t *st;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_domain_info_t *di;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_sb_t *sb;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_boards[board].cfg_hwd == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef UCTEST
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Just map the HWD in SRAM to a kernel VA
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size_t size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pfn_t pfn;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size = 0xA000;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_hwd_vaddr = vmem_alloc(heap_arena, size, VM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_hwd_vaddr == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_NOTE, "No space for HWD");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pfn = btop(OPL_HWD_BASE(board));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hat_devload(kas.a_hat, opl_hwd_vaddr, size, pfn, PROT_READ,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwdp = (void *)((char *)opl_hwd_vaddr + 0x1000);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_boards[board].cfg_hwd = hwdp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* find the scf_service_getinfo() function */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (getinfop == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl getinfop = (int (*)(uint32_t, uint8_t, uint32_t,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t *,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *))modgetsymvalue("scf_service_getinfo", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (getinfop == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* allocate memory to receive the data */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwdp = kmem_alloc(HWD_DATA_SIZE, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* get the HWD */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = (*getinfop)(key, type, transid, &datasize, hwdp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_boards[board].cfg_hwd = hwdp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(hwdp, HWD_DATA_SIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwdp = opl_boards[board].cfg_hwd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* copy the data to the destination */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hd = (hwd_header_t *)hwdp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl st = (hwd_sb_status_t *)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((char *)hwdp + hd->hdr_sb_status_offset);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl di = (hwd_domain_info_t *)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((char *)hwdp + hd->hdr_domain_info_offset);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sb = (hwd_sb_t *)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((char *)hwdp + hd->hdr_sb_info_offset);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (hdrp != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *hdrp = hd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (statp != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *statp = st;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (dinfop != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *dinfop = di;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (sbp != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *sbp = sb;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ret);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The opl_probe_t probe structure is used to pass all sorts of parameters
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to callback functions during probing. It also contains a snapshot of
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the hardware descriptor that is taken at the beginning of a probe.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_probe_init(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_header_t **hdrp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_sb_status_t **statp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_domain_info_t **dinfop;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_sb_t **sbp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int board, ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board = probe->pr_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hdrp = &probe->pr_hdr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl statp = &probe->pr_sb_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dinfop = &probe->pr_dinfo;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbp = &probe->pr_sb;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Read the hardware descriptor.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = opl_read_hwd(board, hdrp, statp, dinfop, sbp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: failed to read HWD header");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_dump_hwd(probe);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This function is used to obtain pointers to relevant device nodes
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * which are created by Solaris at boot time.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This function walks the child nodes of a given node, extracts
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the "name" property, if it exists, and passes the node to a
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * callback init function. The callback determines if this node is
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * interesting or not. If it is, then a pointer to the node is
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * stored away by the callback for use during unprobe.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The DDI get property function allocates storage for the name
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * property. That needs to be freed within this function.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_init_nodes(dev_info_t *parent, opl_init_func_t init)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *name;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int circ, ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(parent != NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Hold parent node busy to walk its child list
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_enter(parent, &circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = ddi_get_child(parent);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (node != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = OPL_GET_PROP(string, node, "name", &name, &len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The property does not exist for this node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = ddi_get_next_sibling(node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = init(node, name, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(name, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_exit(parent, circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = ddi_get_next_sibling(node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_exit(parent, circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This init function finds all the interesting nodes under the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * root node and stores pointers to them. The following nodes
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * are considered interesting by this implementation:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * "cmp"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * These are nodes that represent processor chips.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * "pci"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * These are nodes that represent PCI leaves.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * "pseudo-mc"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * These are nodes that contain memory information.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_init_root_nodes(dev_info_t *node, char *name, int len)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int portid, board, chip, channel, leaf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strncmp(name, OPL_CPU_CHIP_NODE, len) == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = OPL_GET_PROP(int, node, "portid", &portid, -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_PROP_SUCCESS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = OPL_GET_PROP(int, node, "board#", &board, -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_PROP_SUCCESS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl chip = OPL_CPU_CHIP(portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_boards[board].cfg_cpu_chips[chip] = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (strncmp(name, OPL_PCI_LEAF_NODE, len) == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = OPL_GET_PROP(int, node, "portid", &portid, -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_PROP_SUCCESS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board = OPL_IO_PORTID_TO_LSB(portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl channel = OPL_PORTID_TO_CHANNEL(portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (channel == OPL_CMU_CHANNEL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_boards[board].cfg_cmuch_leaf = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl leaf = OPL_PORTID_TO_LEAF(portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_boards[board].cfg_pcich_leaf[channel][leaf] = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (strncmp(name, OPL_PSEUDO_MC_NODE, len) == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = OPL_GET_PROP(int, node, "board#", &board, -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_PROP_SUCCESS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT((board >= 0) && (board < HWD_SBS_PER_DOMAIN));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_boards[board].cfg_pseudo_mc = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This function initializes the OPL IKP feature. Currently, all it does
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * is find the interesting nodes that Solaris has created at boot time
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for boards present at boot time and store pointers to them. This
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * is useful if those boards are unprobed by DR.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_init_cfg()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *root;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_cfg_inited == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl root = ddi_root_node();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((opl_init_nodes(root, opl_init_root_nodes) != 0)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: init failed");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_cfg_inited = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * When DR is initialized, we walk the device tree and acquire a hold on
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * all the nodes that are interesting to IKP. This is so that the corresponding
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * branches cannot be deleted.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The following function informs the walk about which nodes are interesting
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * so that it can hold the corresponding branches.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_hold_node(char *name)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We only need to hold/release the following nodes which
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * represent separate branches that must be managed.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((strcmp(name, OPL_CPU_CHIP_NODE) == 0) ||
e98fafb9956429b59c817d4fbd27720c73879203jl (strcmp(name, OPL_PSEUDO_MC_NODE) == 0) ||
e98fafb9956429b59c817d4fbd27720c73879203jl (strcmp(name, OPL_PCI_LEAF_NODE) == 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_hold_rele_devtree(dev_info_t *rdip, void *arg)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int *holdp = (int *)arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *name = ddi_node_name(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We only need to hold/release the following nodes which
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * represent separate branches that must be managed.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_hold_node(name) == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Not of interest to us */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (*holdp) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(!e_ddi_branch_held(rdip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e_ddi_branch_hold(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(e_ddi_branch_held(rdip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e_ddi_branch_rele(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_hold_devtree()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int circ;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int hold = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dip = ddi_root_node();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_enter(dip, &circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_walk_devs(ddi_get_child(dip), opl_hold_rele_devtree, &hold);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_exit(dip, circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_release_devtree()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int circ;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int hold = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dip = ddi_root_node();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_enter(dip, &circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_walk_devs(ddi_get_child(dip), opl_hold_rele_devtree, &hold);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_exit(dip, circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This is a helper function that allows opl_create_node() to return a
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * pointer to a newly created node to its caller.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_set_node(dev_info_t *node, void *arg, uint_t flags)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_probe_t *probe;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe = arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_node = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Function to create a node in the device tree under a specified parent.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * e_ddi_branch_create() allows the creation of a whole branch with a
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * single call of the function. However, we only use it to create one node
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * at a time in the case of non-I/O device nodes. In other words, we
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * create branches by repeatedly using this function. This makes the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * code more readable.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The branch descriptor passed to e_ddi_branch_create() takes two
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * callbacks. The create() callback is used to set the properties of a
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * newly created node. The other callback is used to return a pointer
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to the newly created node. The create() callback is passed by the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * caller of this function based on the kind of node he wishes to
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * create.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * e_ddi_branch_create() returns with the newly created node held. We
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * only need to hold the top nodes of the branches we create. We release
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the hold for the others. E.g., the "cmp" node needs to be held. Since
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we hold the "cmp" node, there is no need to hold the "core" and "cpu"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * nodes below it.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic dev_info_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_create_node(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl devi_branch_t branch;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_node = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl branch.arg = probe;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl branch.type = DEVI_BRANCH_SID;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl branch.create.sid_branch_create = probe->pr_create;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl branch.devi_branch_callback = opl_set_node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (e_ddi_branch_create(probe->pr_parent, &branch, NULL, 0) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(probe->pr_node != NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (probe->pr_hold == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e_ddi_branch_rele(probe->pr_node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (probe->pr_node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Function to tear down a whole branch rooted at the specified node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Although we create each node of a branch individually, we destroy
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * a whole branch in one call. This is more efficient.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_destroy_node(dev_info_t *node)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (e_ddi_branch_destroy(node, NULL, 0) != 0) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl (void) ddi_pathname(node, path);
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "OPL node removal failed: %s (%p)", path,
e98fafb9956429b59c817d4fbd27720c73879203jl (void *)node);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl kmem_free(path, MAXPATHLEN);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Set the properties for a "cpu" node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_create_cpu(dev_info_t *node, void *arg, uint_t flags)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_probe_t *probe;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_chip_t *chip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_core_t *core;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_t *cpu;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe = arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl chip = &probe->pr_sb->sb_cmu.cmu_cpu_chips[probe->pr_cpu_chip];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core = &chip->chip_cores[probe->pr_core];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpu = &core->core_cpus[probe->pr_cpu];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "name", OPL_CPU_NODE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "device_type", OPL_CPU_NODE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "cpuid", cpu->cpu_cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "reg", probe->pr_cpu);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "status", "okay");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create "cpu" nodes as child nodes of a given "core" node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_probe_cpus(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_chip_t *chip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_core_t *core;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_t *cpus;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl chip = &probe->pr_sb->sb_cmu.cmu_cpu_chips[probe->pr_cpu_chip];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core = &chip->chip_cores[probe->pr_core];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpus = &core->core_cpus[0];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_CPUS_PER_CORE; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Olympus-C has 2 cpus per core.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Jupiter has 4 cpus per core.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * For the Olympus-C based platform, we expect the cpu_status
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * of the non-existent cpus to be set to missing.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!HWD_STATUS_OK(cpus[i].cpu_status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_create = opl_create_cpu;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_cpu = i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_create_node(probe) == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: create cpu (%d-%d-%d-%d) failed",
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_board, probe->pr_cpu_chip, probe->pr_core,
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_cpu);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Set the properties for a "core" node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_create_core(dev_info_t *node, void *arg, uint_t flags)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_probe_t *probe;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_chip_t *chip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_core_t *core;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int sharing[2];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe = arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl chip = &probe->pr_sb->sb_cmu.cmu_cpu_chips[probe->pr_cpu_chip];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core = &chip->chip_cores[probe->pr_core];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "name", OPL_CORE_NODE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "device_type", OPL_CORE_NODE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "compatible", chip->chip_compatible);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "reg", probe->pr_core);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "manufacturer#", core->core_manufacturer);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "implementation#",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_implementation);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "mask#", core->core_mask);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
0e9f8900ad569e1a4305035ffd4cc236099ca742jimand OPL_UPDATE_PROP(int, node, "sparc-version", 9);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "clock-frequency", core->core_frequency);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l1-icache-size", core->core_l1_icache_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l1-icache-line-size",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_l1_icache_line_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l1-icache-associativity",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_l1_icache_associativity);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "#itlb-entries",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_num_itlb_entries);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l1-dcache-size", core->core_l1_dcache_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l1-dcache-line-size",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_l1_dcache_line_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l1-dcache-associativity",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_l1_dcache_associativity);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "#dtlb-entries",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_num_dtlb_entries);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l2-cache-size", core->core_l2_cache_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l2-cache-line-size",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_l2_cache_line_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "l2-cache-associativity",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core->core_l2_cache_associativity);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sharing[0] = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sharing[1] = core->core_l2_cache_sharing;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP_ARRAY(int, node, "l2-cache-sharing", sharing, 2);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "status", "okay");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create "core" nodes as child nodes of a given "cmp" node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create the branch below each "core" node".
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_probe_cores(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_chip_t *chip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_core_t *cores;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *parent, *node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl chip = &probe->pr_sb->sb_cmu.cmu_cpu_chips[probe->pr_cpu_chip];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cores = &chip->chip_cores[0];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl parent = probe->pr_parent;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_CORES_PER_CPU_CHIP; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!HWD_STATUS_OK(cores[i].core_status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_parent = parent;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_create = opl_create_core;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_core = i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = opl_create_node(probe);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (node == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: create core (%d-%d-%d) failed",
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_board, probe->pr_cpu_chip,
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_core);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create "cpu" nodes below "core".
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_parent = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_probe_cpus(probe) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_cpu_impl |= (1 << cores[i].core_implementation);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Set the properties for a "cmp" node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_create_cpu_chip(dev_info_t *node, void *arg, uint_t flags)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_probe_t *probe;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_chip_t *chip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_range_t range;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t dummy_addr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe = arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl chip = &probe->pr_sb->sb_cmu.cmu_cpu_chips[probe->pr_cpu_chip];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "name", OPL_CPU_CHIP_NODE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "portid", chip->chip_portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "board#", probe->pr_board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dummy_addr = OPL_PROC_AS(probe->pr_board, probe->pr_cpu_chip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_addr_hi = OPL_HI(dummy_addr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_addr_lo = OPL_LO(dummy_addr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_size_hi = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_size_lo = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP_ARRAY(int, node, "reg", (int *)&range, 4);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "#address-cells", 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "#size-cells", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "status", "okay");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create "cmp" nodes as child nodes of the root node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create the branch below each "cmp" node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_probe_cpu_chips(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t **cfg_cpu_chips;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_cpu_chip_t *chips;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cfg_cpu_chips = opl_boards[probe->pr_board].cfg_cpu_chips;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl chips = &probe->pr_sb->sb_cmu.cmu_cpu_chips[0];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_CPU_CHIPS_PER_CMU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(cfg_cpu_chips[i] == NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!HWD_STATUS_OK(chips[i].chip_status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_parent = ddi_root_node();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_create = opl_create_cpu_chip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_cpu_chip = i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_hold = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = opl_create_node(probe);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (node == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: create chip (%d-%d) failed",
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_board, probe->pr_cpu_chip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cfg_cpu_chips[i] = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create "core" nodes below "cmp".
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We hold the "cmp" node. So, there is no need to hold
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the "core" and "cpu" nodes below it.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_parent = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_hold = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_probe_cores(probe) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Set the properties for a "pseudo-mc" node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_create_pseudo_mc(dev_info_t *node, void *arg, uint_t flags)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_probe_t *probe;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int board, portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_bank_t *bank;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_memory_t *mem;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_range_t range;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_mc_addr_t mc[HWD_BANKS_PER_CMU];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int status[2][7];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i, j;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe = arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board = probe->pr_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "name", OPL_PSEUDO_MC_NODE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "device_type", "memory-controller");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "compatible", "FJSV,oplmc");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = OPL_LSB_TO_PSEUDOMC_PORTID(board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "portid", portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_addr_hi = OPL_HI(OPL_MC_AS(board));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_addr_lo = 0x200;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_size_hi = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_size_lo = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP_ARRAY(int, node, "reg", (int *)&range, 4);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "board#", board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "physical-board#",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_sb->sb_psb_number);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "#address-cells", 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(int, node, "#size-cells", 2);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem = &probe->pr_sb->sb_cmu.cmu_memory;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_addr_hi = OPL_HI(mem->mem_start_address);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_addr_lo = OPL_LO(mem->mem_start_address);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_size_hi = OPL_HI(mem->mem_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl range.rg_size_lo = OPL_LO(mem->mem_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP_ARRAY(int, node, "sb-mem-ranges", (int *)&range, 4);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bank = probe->pr_sb->sb_cmu.cmu_memory.mem_banks;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0, j = 0; i < HWD_BANKS_PER_CMU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!HWD_STATUS_OK(bank[i].bank_status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mc[j].mc_bank = i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mc[j].mc_hi = OPL_HI(bank[i].bank_register_address);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mc[j].mc_lo = OPL_LO(bank[i].bank_register_address);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl j++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (j > 0) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl OPL_UPDATE_PROP_ARRAY(int, node, "mc-addr", (int *)mc, j*3);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl } else {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * If there is no memory, we need the mc-addr property, but
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * it is length 0. The only way to do this using ndi seems
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * to be by creating a boolean property.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, node, "mc-addr");
68ac2337c38c8af06edcf32a72e42de36ec72a9djl OPL_UPDATE_PROP_ERR(ret, "mc-addr");
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP_ARRAY(byte, node, "cs0-mc-pa-trans-table",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem->mem_cs[0].cs_pa_mac_table, 64);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP_ARRAY(byte, node, "cs1-mc-pa-trans-table",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem->mem_cs[1].cs_pa_mac_table, 64);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define CS_PER_MEM 2
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0, j = 0; i < CS_PER_MEM; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (HWD_STATUS_OK(mem->mem_cs[i].cs_status) ||
e98fafb9956429b59c817d4fbd27720c73879203jl HWD_STATUS_FAILED(mem->mem_cs[i].cs_status)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status[j][0] = i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (HWD_STATUS_OK(mem->mem_cs[i].cs_status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status[j][1] = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status[j][1] = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status[j][2] =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_HI(mem->mem_cs[i].cs_available_capacity);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status[j][3] =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_LO(mem->mem_cs[i].cs_available_capacity);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status[j][4] = OPL_HI(mem->mem_cs[i].cs_dimm_capacity);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status[j][5] = OPL_LO(mem->mem_cs[i].cs_dimm_capacity);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status[j][6] = mem->mem_cs[i].cs_number_of_dimms;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl j++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (j > 0) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl OPL_UPDATE_PROP_ARRAY(int, node, "cs-status", (int *)status,
68ac2337c38c8af06edcf32a72e42de36ec72a9djl j*7);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl } else {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * If there is no memory, we need the cs-status property, but
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * it is length 0. The only way to do this using ndi seems
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * to be by creating a boolean property.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, node,
68ac2337c38c8af06edcf32a72e42de36ec72a9djl "cs-status");
68ac2337c38c8af06edcf32a72e42de36ec72a9djl OPL_UPDATE_PROP_ERR(ret, "cs-status");
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create "pseudo-mc" nodes
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_probe_memory(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_board_cfg_t *board_cfg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board = probe->pr_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board_cfg = &opl_boards[board];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(board_cfg->cfg_pseudo_mc == NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_parent = ddi_root_node();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_create = opl_create_pseudo_mc;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_hold = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = opl_create_node(probe);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (node == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: create pseudo-mc (%d) failed", board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board_cfg->cfg_pseudo_mc = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Allocate the fcode ops handle.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic
25cf1a301a396c38e8adf52c15f537b80d2483f7jlfco_handle_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_fc_ops_alloc_handle(dev_info_t *parent, dev_info_t *child,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *fcode, size_t fcode_size, char *unit_address,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *my_args)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fco_handle_t rp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl phandle_t h;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *buf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp = kmem_zalloc(sizeof (struct fc_resource_list), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->next_handle = fc_ops_alloc_handle(parent, child, fcode, fcode_size,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl unit_address, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->ap = parent;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->child = child;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->fcode = fcode;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->fcode_size = fcode_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->my_args = my_args;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (unit_address) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl buf = kmem_zalloc(UNIT_ADDR_SIZE, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) strcpy(buf, unit_address);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rp->unit_address = buf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Add the child's nodeid to our table...
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl h = ddi_get_nodeid(rp->child);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_add_dip_to_phandle(fc_handle_to_phandle_head(rp), rp->child, h);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_fc_ops_free_handle(fco_handle_t rp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct fc_resource *resp, *nresp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rp->next_handle)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_ops_free_handle(rp->next_handle);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rp->unit_address)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(rp->unit_address, UNIT_ADDR_SIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Release all the resources from the resource list
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (resp = rp->head; resp != NULL; resp = nresp) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nresp = resp->next;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (resp->type) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case RT_MAP:
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * If this is still mapped, we'd better unmap it now,
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * or all our structures that are tracking it will
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * be leaked.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (resp->fc_map_handle != NULL)
68ac2337c38c8af06edcf32a72e42de36ec72a9djl opl_unmap_phys(&resp->fc_map_handle);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case RT_DMA:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DMA has to be freed up at exit time.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_CONT,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "opl_fc_ops_free_handle: Unexpected DMA seen!");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case RT_CONTIGIOUS:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG2(1, CE_CONT, "opl_fc_ops_free: "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Free claim-memory resource 0x%lx size 0x%x\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_contig_virt, resp->fc_contig_len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ndi_ra_free(ddi_root_node(),
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (uint64_t)resp->fc_contig_virt,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_contig_len, "opl-fcodemem",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NDI_RA_PASS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_CONT, "opl_fc_ops_free: "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "unknown resource type %d", resp->type);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_rem_resource(rp, resp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(resp, sizeof (struct fc_resource));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(rp, sizeof (struct fc_resource_list));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_fc_do_op(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_fc_ops_t *op;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *service = fc_cell2ptr(cp->svc_name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG1(1, CE_CONT, "opl_fc_do_op: <%s>\n", service);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * First try the generic fc_ops.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_ops(ap, rp->next_handle, cp) == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Now try the Jupiter-specific ops.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (op = opl_fc_ops; op->fc_service != NULL; ++op)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(op->fc_service, service) == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (op->fc_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG1(9, CE_CONT, "opl_fc_do_op: <%s> not serviced\n", service);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * map-in (phys.lo phys.hi size -- virt)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_map_in(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size_t len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int error;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct fc_resource *resp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct regspec rspec;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_device_acc_attr_t acc;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_acc_handle_t h;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 3)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 3"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) < 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be >= 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rspec.regspec_size = len = fc_cell2size(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rspec.regspec_bustype = fc_cell2uint(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rspec.regspec_addr = fc_cell2uint(fc_arg(cp, 2));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG3(1, CE_CONT, "opl_map_in: attempting map in "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "address 0x%08x.%08x length %x\n", rspec.regspec_bustype,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rspec.regspec_addr, rspec.regspec_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl error = opl_map_phys(rp->child, &rspec, &virt, &acc, &h);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (error) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG3(1, CE_CONT, "opl_map_in: map in failed - "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "address 0x%08x.%08x length %x\n", rspec.regspec_bustype,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rspec.regspec_addr, rspec.regspec_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "opl map-in failed"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG1(3, CE_CONT, "opl_map_in: returning virt %p\n", virt);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_result(cp, 0) = fc_ptr2cell(virt);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Log this resource ...
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp = kmem_zalloc(sizeof (struct fc_resource), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->type = RT_MAP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_map_virt = virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_map_len = len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_map_handle = h;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_add_resource(rp, resp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * map-out (virt size -- )
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_map_out(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size_t len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct fc_resource *resp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 2)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 2"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl virt = fc_cell2ptr(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = fc_cell2size(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG2(1, CE_CONT, "opl_map_out: attempting map out %p %x\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl virt, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Find if this request matches a mapping resource we set up.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_lock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (resp = rp->head; resp != NULL; resp = resp->next) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type != RT_MAP)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->fc_map_virt != virt)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->fc_map_len == len)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_unlock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "request doesn't match a "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "known mapping"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_unmap_phys(&resp->fc_map_handle);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * remove the resource from the list and release it.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_rem_resource(rp, resp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(resp, sizeof (struct fc_resource));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_register_fetch(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size_t len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int error = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t v;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t x;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t l;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint16_t w;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint8_t b;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *service = fc_cell2ptr(cp->svc_name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct fc_resource *resp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) < 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be >= 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl virt = fc_cell2ptr(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Determine the access width .. we can switch on the 2nd
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * character of the name which is "rx@", "rl@", "rb@" or "rw@"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (*(service + 1)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case 'x': len = sizeof (x); break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case 'l': len = sizeof (l); break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case 'w': len = sizeof (w); break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case 'b': len = sizeof (b); break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Check the alignment ...
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (((intptr_t)virt & (len - 1)) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "unaligned access"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Find if this virt is 'within' a request we know about
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_lock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (resp = rp->head; resp != NULL; resp = resp->next) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((virt >= (caddr_t)resp->fc_map_virt) &&
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((virt + len) <=
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((caddr_t)resp->fc_map_virt + resp->fc_map_len)))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (resp->type == RT_CONTIGIOUS) {
e98fafb9956429b59c817d4fbd27720c73879203jl if ((virt >= (caddr_t)resp->fc_contig_virt) &&
e98fafb9956429b59c817d4fbd27720c73879203jl ((virt + len) <= ((caddr_t)resp->fc_contig_virt +
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_contig_len)))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_unlock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "request not within "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "known mappings"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (len) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (x):
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP)
e98fafb9956429b59c817d4fbd27720c73879203jl error = ddi_peek64(rp->child, (int64_t *)virt,
e98fafb9956429b59c817d4fbd27720c73879203jl (int64_t *)&x);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else /* RT_CONTIGIOUS */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl x = *(int64_t *)virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl v = x;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (l):
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP)
e98fafb9956429b59c817d4fbd27720c73879203jl error = ddi_peek32(rp->child, (int32_t *)virt,
e98fafb9956429b59c817d4fbd27720c73879203jl (int32_t *)&l);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else /* RT_CONTIGIOUS */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl l = *(int32_t *)virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl v = l;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (w):
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP)
e98fafb9956429b59c817d4fbd27720c73879203jl error = ddi_peek16(rp->child, (int16_t *)virt,
e98fafb9956429b59c817d4fbd27720c73879203jl (int16_t *)&w);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else /* RT_CONTIGIOUS */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl w = *(int16_t *)virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl v = w;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (b):
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP)
e98fafb9956429b59c817d4fbd27720c73879203jl error = ddi_peek8(rp->child, (int8_t *)virt,
e98fafb9956429b59c817d4fbd27720c73879203jl (int8_t *)&b);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else /* RT_CONTIGIOUS */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl b = *(int8_t *)virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl v = b;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (error == DDI_FAILURE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG2(1, CE_CONT, "opl_register_fetch: access error "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "accessing virt %p len %d\n", virt, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "access error"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG3(1, CE_CONT, "register_fetch (%s) %llx %llx\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl service, virt, v);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (len) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (x): fc_result(cp, 0) = x; break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (l): fc_result(cp, 0) = fc_uint32_t2cell(l); break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (w): fc_result(cp, 0) = fc_uint16_t2cell(w); break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (b): fc_result(cp, 0) = fc_uint8_t2cell(b); break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_register_store(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size_t len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t v;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t x;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t l;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint16_t w;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint8_t b;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *service = fc_cell2ptr(cp->svc_name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct fc_resource *resp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int error = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 2)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 2"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl virt = fc_cell2ptr(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Determine the access width .. we can switch on the 2nd
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * character of the name which is "rx!", "rl!", "rb!" or "rw!"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (*(service + 1)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case 'x':
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (x);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl x = fc_arg(cp, 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl v = x;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case 'l':
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (l);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl l = fc_cell2uint32_t(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl v = l;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case 'w':
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (w);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl w = fc_cell2uint16_t(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl v = w;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case 'b':
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (b);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl b = fc_cell2uint8_t(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl v = b;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG3(1, CE_CONT, "register_store (%s) %llx %llx\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl service, virt, v);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Check the alignment ...
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (((intptr_t)virt & (len - 1)) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "unaligned access"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Find if this virt is 'within' a request we know about
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_lock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (resp = rp->head; resp != NULL; resp = resp->next) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((virt >= (caddr_t)resp->fc_map_virt) &&
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((virt + len) <=
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((caddr_t)resp->fc_map_virt + resp->fc_map_len)))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (resp->type == RT_CONTIGIOUS) {
e98fafb9956429b59c817d4fbd27720c73879203jl if ((virt >= (caddr_t)resp->fc_contig_virt) &&
e98fafb9956429b59c817d4fbd27720c73879203jl ((virt + len) <= ((caddr_t)resp->fc_contig_virt +
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_contig_len)))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_unlock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "request not within"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "known mappings"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (len) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (x):
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl error = ddi_poke64(rp->child, (int64_t *)virt, x);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (resp->type == RT_CONTIGIOUS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(uint64_t *)virt = x;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (l):
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl error = ddi_poke32(rp->child, (int32_t *)virt, l);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (resp->type == RT_CONTIGIOUS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(uint32_t *)virt = l;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (w):
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl error = ddi_poke16(rp->child, (int16_t *)virt, w);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (resp->type == RT_CONTIGIOUS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(uint16_t *)virt = w;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case sizeof (b):
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type == RT_MAP)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl error = ddi_poke8(rp->child, (int8_t *)virt, b);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (resp->type == RT_CONTIGIOUS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(uint8_t *)virt = b;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (error == DDI_FAILURE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG2(1, CE_CONT, "opl_register_store: access error "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "accessing virt %p len %d\n", virt, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "access error"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * opl_claim_memory
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * claim-memory (align size vhint -- vaddr)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_claim_memory(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int align, size, vhint;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t answer, alen;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_ra_request_t request;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct fc_resource *resp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 3)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 3"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) < 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be >= 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl vhint = fc_cell2int(fc_arg(cp, 2));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size = fc_cell2int(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl align = fc_cell2int(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG3(1, CE_CONT, "opl_claim_memory: align=0x%x size=0x%x "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "vhint=0x%x\n", align, size, vhint);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (size == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "opl_claim_memory - unable to allocate "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "contiguous memory of size zero\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "allocation error"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (vhint) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "opl_claim_memory - vhint is not zero "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "vhint=0x%x - Ignoring Argument\n", vhint);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl request.ra_flags = NDI_RA_ALLOC_BOUNDED;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl request.ra_boundbase = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl request.ra_boundlen = 0xffffffff;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl request.ra_len = size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl request.ra_align_mask = align - 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ndi_ra_alloc(ddi_root_node(), &request, &answer, &alen,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "opl-fcodemem", NDI_RA_PASS) != NDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "opl_claim_memory - unable to allocate "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "contiguous memory\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "allocation error"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG2(1, CE_CONT, "opl_claim_memory: address allocated=0x%lx "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "size=0x%x\n", answer, alen);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_result(cp, 0) = answer;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Log this resource ...
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp = kmem_zalloc(sizeof (struct fc_resource), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->type = RT_CONTIGIOUS;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_contig_virt = (void *)answer;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl resp->fc_contig_len = size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_add_resource(rp, resp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * opl_release_memory
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * release-memory (size vaddr -- )
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_release_memory(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int32_t vaddr, size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct fc_resource *resp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 2)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 2"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be 0"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl vaddr = fc_cell2int(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size = fc_cell2int(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG2(1, CE_CONT, "opl_release_memory: vaddr=0x%x size=0x%x\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl vaddr, size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Find if this request matches a mapping resource we set up.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_lock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (resp = rp->head; resp != NULL; resp = resp->next) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type != RT_CONTIGIOUS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->fc_contig_virt != (void *)(uintptr_t)vaddr)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->fc_contig_len == size)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_unlock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "request doesn't match a "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "known mapping"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ndi_ra_free(ddi_root_node(), vaddr, size,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "opl-fcodemem", NDI_RA_PASS);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * remove the resource from the list and release it.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_rem_resource(rp, resp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(resp, sizeof (struct fc_resource));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * opl_vtop
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * vtop (vaddr -- paddr.lo paddr.hi)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_vtop(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int vaddr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t paddr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct fc_resource *resp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) >= 3)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be less than 2"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl vaddr = fc_cell2int(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Find if this request matches a mapping resource we set up.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_lock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (resp = rp->head; resp != NULL; resp = resp->next) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp->type != RT_CONTIGIOUS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
431161eb3a9469e6dffc1f86269f5ce88d061f97bm if (((uint64_t)resp->fc_contig_virt <= vaddr) &&
431161eb3a9469e6dffc1f86269f5ce88d061f97bm (vaddr < (uint64_t)resp->fc_contig_virt +
431161eb3a9469e6dffc1f86269f5ce88d061f97bm resp->fc_contig_len))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_unlock_resource_list(rp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (resp == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "request doesn't match a "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "known mapping"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl paddr = va_to_pa((void *)(uintptr_t)vaddr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG2(1, CE_CONT, "opl_vtop: vaddr=0x%x paddr=0x%x\n",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl vaddr, paddr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(2);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_result(cp, 0) = paddr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_result(cp, 1) = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_config_child(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_phandle_t h;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 0"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) < 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be >= 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl h = fc_dip_to_phandle(fc_handle_to_phandle_head(rp), rp->child);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_result(cp, 0) = fc_phandle2cell(h);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_get_fcode(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t dropin_name_virt, fcode_virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *dropin_name, *fcode;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int fcode_len, status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 3)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 3"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) < 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be >= 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dropin_name_virt = fc_cell2ptr(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fcode_virt = fc_cell2ptr(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fcode_len = fc_cell2int(fc_arg(cp, 2));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dropin_name = kmem_zalloc(FC_SVC_NAME_LEN, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG2(1, CE_CONT, "get_fcode: %x %d\n", fcode_virt, fcode_len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (copyinstr(fc_cell2ptr(dropin_name_virt), dropin_name,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_SVC_NAME_LEN - 1, NULL)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG1(1, CE_CONT, "opl_get_fcode: "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "fault copying in drop in name %p\n", dropin_name_virt);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG1(1, CE_CONT, "get_fcode: %s\n", dropin_name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fcode = kmem_zalloc(fcode_len, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((status = prom_get_fcode(dropin_name, fcode)) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (copyout((void *)fcode, (void *)fcode_virt,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fcode_len)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, " opl_get_fcode: Unable "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "to copy out fcode image");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(fcode, fcode_len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(dropin_name, FC_SVC_NAME_LEN);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_result(cp, 0) = status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_get_fcode_size(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *dropin_name;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) < 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be >= 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl virt = fc_cell2ptr(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dropin_name = kmem_zalloc(FC_SVC_NAME_LEN, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG0(1, CE_CONT, "opl_get_fcode_size:\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (copyinstr(fc_cell2ptr(virt), dropin_name,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_SVC_NAME_LEN - 1, NULL)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG1(1, CE_CONT, "opl_get_fcode_size: "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "fault copying in drop in name %p\n", virt);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG1(1, CE_CONT, "opl_get_fcode_size: %s\n", dropin_name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = prom_get_fcode_size(dropin_name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(dropin_name, FC_SVC_NAME_LEN);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl FC_DEBUG1(1, CE_CONT, "opl_get_fcode_size: fcode_len = %d\n", len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_result(cp, 0) = len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_map_phys(dev_info_t *dip, struct regspec *phys_spec,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t *addrp, ddi_device_acc_attr_t *accattrp,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_acc_handle_t *handlep)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_map_req_t mapreq;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_acc_hdl_t *acc_handlep;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int result;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct regspec *rspecp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *handlep = impl_acc_hdl_alloc(KM_SLEEP, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep = impl_acc_hdl_get(*handlep);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_vers = VERS_ACCHDL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_dip = dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_rnumber = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_offset = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_len = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_acc = *accattrp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rspecp = kmem_zalloc(sizeof (struct regspec), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *rspecp = *phys_spec;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * cache a copy of the reg spec
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_bus_private = rspecp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_op = DDI_MO_MAP_LOCKED;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_type = DDI_MT_REGSPEC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_obj.rp = (struct regspec *)phys_spec;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_prot = PROT_READ | PROT_WRITE;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_flags = DDI_MF_KERNEL_MAPPING;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_handlep = acc_handlep;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_vers = DDI_MAP_VERSION;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl result = ddi_map(dip, &mapreq, 0, 0, addrp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (result != DDI_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl impl_acc_hdl_free(*handlep);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl kmem_free(rspecp, sizeof (struct regspec));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *handlep = (ddi_acc_handle_t)NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_addr = *addrp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (result);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_unmap_phys(ddi_acc_handle_t *handlep)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_map_req_t mapreq;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_acc_hdl_t *acc_handlep;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct regspec *rspecp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep = impl_acc_hdl_get(*handlep);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(acc_handlep);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rspecp = acc_handlep->ah_bus_private;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_op = DDI_MO_UNMAP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_type = DDI_MT_REGSPEC;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_obj.rp = (struct regspec *)rspecp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_prot = PROT_READ | PROT_WRITE;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_flags = DDI_MF_KERNEL_MAPPING;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_handlep = acc_handlep;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mapreq.map_vers = DDI_MAP_VERSION;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ddi_map(acc_handlep->ah_dip, &mapreq, acc_handlep->ah_offset,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl acc_handlep->ah_len, &acc_handlep->ah_addr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl impl_acc_hdl_free(*handlep);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Free the cached copy
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(rspecp, sizeof (struct regspec));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *handlep = (ddi_acc_handle_t)NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_get_hwd_va(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *hwd_virt;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_header_t *hwd_h = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_sb_t *hwd_sb = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int lsb, ch, leaf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int status = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Check the argument */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nargs) != 2)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nargs must be 2"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fc_cell2int(cp->nresults) < 1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_syntax_error(cp, "nresults must be >= 1"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get the parameters */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = fc_cell2uint32_t(fc_arg(cp, 0));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_virt = (void *)fc_cell2ptr(fc_arg(cp, 1));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get the ID numbers */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl lsb = OPL_IO_PORTID_TO_LSB(portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ch = OPL_PORTID_TO_CHANNEL(portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl leaf = OPL_PORTID_TO_LEAF(portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(OPL_IO_PORTID(lsb, ch, leaf) == portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Set the pointer of hwd. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((hwd_h = (hwd_header_t *)opl_boards[lsb].cfg_hwd) == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "null hwd header"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Set the pointer of hwd sb. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((hwd_sb = (hwd_sb_t *)((char *)hwd_h + hwd_h->hdr_sb_info_offset))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_priv_error(cp, "null hwd sb"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ch == OPL_CMU_CHANNEL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Copyout CMU-CH HW Descriptor */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (copyout((void *)&hwd_sb->sb_cmu.cmu_ch,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void *)hwd_virt, sizeof (hwd_cmu_chan_t))) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "opl_get_hwd_va: "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Unable to copy out cmuch descriptor for %x",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Copyout PCI-CH HW Descriptor */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (copyout((void *)&hwd_sb->sb_pci_ch[ch].pci_leaf[leaf],
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void *)hwd_virt, sizeof (hwd_leaf_t))) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "opl_get_hwd_va: "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Unable to copy out pcich descriptor for %x",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl status = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->nresults = fc_int2cell(1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fc_result(cp, 0) = status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (fc_success_op(ap, rp, cp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * After Solaris boots, a user can enter OBP using L1A, etc. While in OBP,
531232457f24de82ba95346b3de302b990fe50f4mv * interrupts may be received from PCI devices. These interrupts
531232457f24de82ba95346b3de302b990fe50f4mv * cannot be handled meaningfully since the system is in OBP. These
531232457f24de82ba95346b3de302b990fe50f4mv * interrupts need to be cleared on the CPU side so that the CPU may
531232457f24de82ba95346b3de302b990fe50f4mv * continue with whatever it is doing. Devices that have raised the
531232457f24de82ba95346b3de302b990fe50f4mv * interrupts are expected to reraise the interrupts after sometime
531232457f24de82ba95346b3de302b990fe50f4mv * as they have not been handled. At that time, Solaris will have a
531232457f24de82ba95346b3de302b990fe50f4mv * chance to properly service the interrupts.
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * The location of the interrupt registers depends on what is present
531232457f24de82ba95346b3de302b990fe50f4mv * at a port. OPL currently supports the Oberon and the CMU channel.
531232457f24de82ba95346b3de302b990fe50f4mv * The following handler handles both kinds of ports and computes
531232457f24de82ba95346b3de302b990fe50f4mv * interrupt register addresses from the specifications and Jupiter Bus
531232457f24de82ba95346b3de302b990fe50f4mv * device bindings.
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * Fcode drivers install their interrupt handler via a "master-interrupt"
531232457f24de82ba95346b3de302b990fe50f4mv * service. For boot time devices, this takes place within OBP. In the case
531232457f24de82ba95346b3de302b990fe50f4mv * of DR, OPL uses IKP. The Fcode drivers that run within the efcode framework
531232457f24de82ba95346b3de302b990fe50f4mv * attempt to install their handler via the "master-interrupt" service.
531232457f24de82ba95346b3de302b990fe50f4mv * However, we cannot meaningfully install the Fcode driver's handler.
531232457f24de82ba95346b3de302b990fe50f4mv * Instead, we install our own handler in OBP which does the same thing.
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * Note that the only handling done for interrupts here is to clear it
531232457f24de82ba95346b3de302b990fe50f4mv * on the CPU side. If any device in the future requires more special
531232457f24de82ba95346b3de302b990fe50f4mv * handling, we would have to put in some kind of framework for adding
531232457f24de82ba95346b3de302b990fe50f4mv * device-specific handlers. This is *highly* unlikely, but possible.
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * Finally, OBP provides a hook called "unix-interrupt-handler" to install
531232457f24de82ba95346b3de302b990fe50f4mv * a Solaris-defined master-interrupt handler for a port. The default
531232457f24de82ba95346b3de302b990fe50f4mv * definition for this method does nothing. Solaris may override this
531232457f24de82ba95346b3de302b990fe50f4mv * with its own definition. This is the way the following handler gets
531232457f24de82ba95346b3de302b990fe50f4mv * control from OBP when interrupts happen at a port after L1A, etc.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mvstatic char define_master_interrupt_handler[] =
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * This method translates an Oberon port id to the base (physical) address
531232457f24de82ba95346b3de302b990fe50f4mv * of the interrupt clear registers for that port id.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv": pcich-mid>clear-int-pa ( mid -- pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" dup 1 >> 7 and ( mid ch# ) "
531232457f24de82ba95346b3de302b990fe50f4mv" over 4 >> h# 1f and ( mid ch# lsb# ) "
531232457f24de82ba95346b3de302b990fe50f4mv" 1 d# 46 << ( mid ch# lsb# pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap d# 40 << or ( mid ch# pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap d# 37 << or ( mid pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap 1 and if h# 70.0000 else h# 60.0000 then "
531232457f24de82ba95346b3de302b990fe50f4mv" or h# 1400 or ( pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv"; "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * This method translates a CMU channel port id to the base (physical) address
531232457f24de82ba95346b3de302b990fe50f4mv * of the interrupt clear registers for that port id. There are two classes of
531232457f24de82ba95346b3de302b990fe50f4mv * interrupts that need to be handled for a CMU channel:
531232457f24de82ba95346b3de302b990fe50f4mv * - obio interrupts
531232457f24de82ba95346b3de302b990fe50f4mv * - pci interrupts
531232457f24de82ba95346b3de302b990fe50f4mv * So, there are two addresses that need to be computed.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv": cmuch-mid>clear-int-pa ( mid -- obio-pa pci-pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" dup 1 >> 7 and ( mid ch# ) "
531232457f24de82ba95346b3de302b990fe50f4mv" over 4 >> h# 1f and ( mid ch# lsb# ) "
531232457f24de82ba95346b3de302b990fe50f4mv" 1 d# 46 << ( mid ch# lsb# pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap d# 40 << or ( mid ch# pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap d# 37 << or ( mid pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" nip dup h# 1800 + ( pa obio-pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap h# 1400 + ( obio-pa pci-pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv"; "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * This method checks if a given I/O port ID is valid or not.
531232457f24de82ba95346b3de302b990fe50f4mv * For a given LSB,
531232457f24de82ba95346b3de302b990fe50f4mv * Oberon ports range from 0 - 3
531232457f24de82ba95346b3de302b990fe50f4mv * CMU ch ports range from 4 - 4
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * Also, the Oberon supports leaves 0 and 1.
531232457f24de82ba95346b3de302b990fe50f4mv * The CMU ch supports only one leaf, leaf 0.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv": valid-io-mid? ( mid -- flag ) "
531232457f24de82ba95346b3de302b990fe50f4mv" dup 1 >> 7 and ( mid ch# ) "
531232457f24de82ba95346b3de302b990fe50f4mv" dup 4 > if 2drop false exit then ( mid ch# ) "
531232457f24de82ba95346b3de302b990fe50f4mv" 4 = swap 1 and 1 = and not "
531232457f24de82ba95346b3de302b990fe50f4mv"; "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * This method checks if a given port id is a CMU ch.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv": cmuch? ( mid -- flag ) 1 >> 7 and 4 = ; "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * Given the base address of the array of interrupt clear registers for
531232457f24de82ba95346b3de302b990fe50f4mv * a port id, this method iterates over the given interrupt number bitmap
531232457f24de82ba95346b3de302b990fe50f4mv * and resets the interrupt on the CPU side for every interrupt number
531232457f24de82ba95346b3de302b990fe50f4mv * in the bitmap. Note that physical addresses are used to perform the
531232457f24de82ba95346b3de302b990fe50f4mv * writes, not virtual addresses. This allows the handler to work without
531232457f24de82ba95346b3de302b990fe50f4mv * any involvement from Solaris.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv": clear-ints ( pa bitmap count -- ) "
531232457f24de82ba95346b3de302b990fe50f4mv" 0 do ( pa bitmap ) "
531232457f24de82ba95346b3de302b990fe50f4mv" dup 0= if 2drop unloop exit then "
531232457f24de82ba95346b3de302b990fe50f4mv" tuck ( bitmap pa bitmap ) "
531232457f24de82ba95346b3de302b990fe50f4mv" 1 and if ( bitmap pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" dup i 8 * + 0 swap ( bitmap pa 0 pa' ) "
531232457f24de82ba95346b3de302b990fe50f4mv" h# 15 spacex! ( bitmap pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" then ( bitmap pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap 1 >> ( pa bitmap ) "
531232457f24de82ba95346b3de302b990fe50f4mv" loop "
531232457f24de82ba95346b3de302b990fe50f4mv"; "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * This method replaces the master-interrupt handler in OBP. Once
531232457f24de82ba95346b3de302b990fe50f4mv * this method is plumbed into OBP, OBP transfers control to this
531232457f24de82ba95346b3de302b990fe50f4mv * handler while returning to Solaris from OBP after L1A. This method's
531232457f24de82ba95346b3de302b990fe50f4mv * task is to simply reset received interrupts on the CPU side.
531232457f24de82ba95346b3de302b990fe50f4mv * When the devices reassert the interrupts later, Solaris will
531232457f24de82ba95346b3de302b990fe50f4mv * be able to see them and handle them.
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * For each port ID that has interrupts, this method is called
531232457f24de82ba95346b3de302b990fe50f4mv * once by OBP. The input arguments are:
531232457f24de82ba95346b3de302b990fe50f4mv * mid portid
531232457f24de82ba95346b3de302b990fe50f4mv * bitmap bitmap of interrupts that have happened
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * This method returns true, if it is able to handle the interrupts.
531232457f24de82ba95346b3de302b990fe50f4mv * OBP does nothing further.
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * This method returns false, if it encountered a problem. Currently,
531232457f24de82ba95346b3de302b990fe50f4mv * the only problem could be an invalid port id. OBP needs to do
531232457f24de82ba95346b3de302b990fe50f4mv * its own processing in that case. If this method returns false,
531232457f24de82ba95346b3de302b990fe50f4mv * it preserves the mid and bitmap arguments for OBP.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv": unix-resend-mondos ( mid bitmap -- [ mid bitmap false ] | true ) "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * Uncomment the following line if you want to display the input arguments.
531232457f24de82ba95346b3de302b990fe50f4mv * This is meant for debugging.
531232457f24de82ba95346b3de302b990fe50f4mv * " .\" Bitmap=\" dup u. .\" MID=\" over u. cr "
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * If the port id is not valid (according to the Oberon and CMU ch
531232457f24de82ba95346b3de302b990fe50f4mv * specifications, then return false to OBP to continue further
531232457f24de82ba95346b3de302b990fe50f4mv * processing.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv" over valid-io-mid? not if ( mid bitmap ) "
531232457f24de82ba95346b3de302b990fe50f4mv" false exit "
531232457f24de82ba95346b3de302b990fe50f4mv" then "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * If the port is a CMU ch, then the 64-bit bitmap represents
531232457f24de82ba95346b3de302b990fe50f4mv * 2 32-bit bitmaps:
531232457f24de82ba95346b3de302b990fe50f4mv * - obio interrupt bitmap (20 bits)
531232457f24de82ba95346b3de302b990fe50f4mv * - pci interrupt bitmap (32 bits)
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * - Split the bitmap into two
531232457f24de82ba95346b3de302b990fe50f4mv * - Compute the base addresses of the interrupt clear registers
531232457f24de82ba95346b3de302b990fe50f4mv * for both pci interrupts and obio interrupts
531232457f24de82ba95346b3de302b990fe50f4mv * - Clear obio interrupts
531232457f24de82ba95346b3de302b990fe50f4mv * - Clear pci interrupts
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv" over cmuch? if ( mid bitmap ) "
531232457f24de82ba95346b3de302b990fe50f4mv" xlsplit ( mid pci-bit obio-bit ) "
531232457f24de82ba95346b3de302b990fe50f4mv" rot cmuch-mid>clear-int-pa ( pci-bit obio-bit obio-pa pci-pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" >r ( pci-bit obio-bit obio-pa ) ( r: pci-pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap d# 20 clear-ints ( pci-bit ) ( r: pci-pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" r> swap d# 32 clear-ints ( ) ( r: ) "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * If the port is an Oberon, then the 64-bit bitmap is used fully.
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * - Compute the base address of the interrupt clear registers
531232457f24de82ba95346b3de302b990fe50f4mv * - Clear interrupts
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv" else ( mid bitmap ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap pcich-mid>clear-int-pa ( bitmap pa ) "
531232457f24de82ba95346b3de302b990fe50f4mv" swap d# 64 clear-ints ( ) "
531232457f24de82ba95346b3de302b990fe50f4mv" then "
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * Always return true from here.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv" true ( true ) "
531232457f24de82ba95346b3de302b990fe50f4mv"; "
531232457f24de82ba95346b3de302b990fe50f4mv;
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mvstatic char install_master_interrupt_handler[] =
531232457f24de82ba95346b3de302b990fe50f4mv "' unix-resend-mondos to unix-interrupt-handler";
531232457f24de82ba95346b3de302b990fe50f4mvstatic char handler[] = "unix-interrupt-handler";
531232457f24de82ba95346b3de302b990fe50f4mvstatic char handler_defined[] = "p\" %s\" find nip swap l! ";
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*ARGSUSED*/
531232457f24de82ba95346b3de302b990fe50f4mvstatic int
531232457f24de82ba95346b3de302b990fe50f4mvmaster_interrupt_init(uint32_t portid, uint32_t xt)
531232457f24de82ba95346b3de302b990fe50f4mv{
531232457f24de82ba95346b3de302b990fe50f4mv uint_t defined;
531232457f24de82ba95346b3de302b990fe50f4mv char buf[sizeof (handler) + sizeof (handler_defined)];
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv if (master_interrupt_inited)
531232457f24de82ba95346b3de302b990fe50f4mv return (1);
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv /*
531232457f24de82ba95346b3de302b990fe50f4mv * Check if the defer word "unix-interrupt-handler" is defined.
531232457f24de82ba95346b3de302b990fe50f4mv * This must be defined for OPL systems. So, this is only a
531232457f24de82ba95346b3de302b990fe50f4mv * sanity check.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv (void) sprintf(buf, handler_defined, handler);
531232457f24de82ba95346b3de302b990fe50f4mv prom_interpret(buf, (uintptr_t)&defined, 0, 0, 0, 0);
531232457f24de82ba95346b3de302b990fe50f4mv if (!defined) {
531232457f24de82ba95346b3de302b990fe50f4mv cmn_err(CE_WARN, "master_interrupt_init: "
531232457f24de82ba95346b3de302b990fe50f4mv "%s is not defined\n", handler);
531232457f24de82ba95346b3de302b990fe50f4mv return (0);
531232457f24de82ba95346b3de302b990fe50f4mv }
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv /*
531232457f24de82ba95346b3de302b990fe50f4mv * Install the generic master-interrupt handler. Note that
531232457f24de82ba95346b3de302b990fe50f4mv * this is only done one time on the first DR operation.
531232457f24de82ba95346b3de302b990fe50f4mv * This is because, for OPL, one, single generic handler
531232457f24de82ba95346b3de302b990fe50f4mv * handles all ports (Oberon and CMU channel) and all
531232457f24de82ba95346b3de302b990fe50f4mv * interrupt sources within each port.
531232457f24de82ba95346b3de302b990fe50f4mv *
531232457f24de82ba95346b3de302b990fe50f4mv * The current support is only for the Oberon and CMU-channel.
531232457f24de82ba95346b3de302b990fe50f4mv * If any others need to be supported, the handler has to be
531232457f24de82ba95346b3de302b990fe50f4mv * modified accordingly.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv /*
531232457f24de82ba95346b3de302b990fe50f4mv * Define the OPL master interrupt handler
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv prom_interpret(define_master_interrupt_handler, 0, 0, 0, 0, 0);
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv /*
531232457f24de82ba95346b3de302b990fe50f4mv * Take over the master interrupt handler from OBP.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv prom_interpret(install_master_interrupt_handler, 0, 0, 0, 0, 0);
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv master_interrupt_inited = 1;
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv /*
531232457f24de82ba95346b3de302b990fe50f4mv * prom_interpret() does not return a status. So, we assume
531232457f24de82ba95346b3de302b990fe50f4mv * that the calls succeeded. In reality, the calls may fail
531232457f24de82ba95346b3de302b990fe50f4mv * if there is a syntax error, etc in the strings.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv return (1);
531232457f24de82ba95346b3de302b990fe50f4mv}
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv/*
531232457f24de82ba95346b3de302b990fe50f4mv * Install the master-interrupt handler for a device.
531232457f24de82ba95346b3de302b990fe50f4mv */
531232457f24de82ba95346b3de302b990fe50f4mvstatic int
531232457f24de82ba95346b3de302b990fe50f4mvopl_master_interrupt(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
531232457f24de82ba95346b3de302b990fe50f4mv{
531232457f24de82ba95346b3de302b990fe50f4mv uint32_t portid, xt;
531232457f24de82ba95346b3de302b990fe50f4mv int board, channel, leaf;
531232457f24de82ba95346b3de302b990fe50f4mv int status;
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv /* Check the argument */
531232457f24de82ba95346b3de302b990fe50f4mv if (fc_cell2int(cp->nargs) != 2)
531232457f24de82ba95346b3de302b990fe50f4mv return (fc_syntax_error(cp, "nargs must be 2"));
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv if (fc_cell2int(cp->nresults) < 1)
531232457f24de82ba95346b3de302b990fe50f4mv return (fc_syntax_error(cp, "nresults must be >= 1"));
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv /* Get the parameters */
531232457f24de82ba95346b3de302b990fe50f4mv portid = fc_cell2uint32_t(fc_arg(cp, 0));
531232457f24de82ba95346b3de302b990fe50f4mv xt = fc_cell2uint32_t(fc_arg(cp, 1));
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv board = OPL_IO_PORTID_TO_LSB(portid);
531232457f24de82ba95346b3de302b990fe50f4mv channel = OPL_PORTID_TO_CHANNEL(portid);
531232457f24de82ba95346b3de302b990fe50f4mv leaf = OPL_PORTID_TO_LEAF(portid);
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv if ((board >= HWD_SBS_PER_DOMAIN) || !OPL_VALID_CHANNEL(channel) ||
531232457f24de82ba95346b3de302b990fe50f4mv (OPL_OBERON_CHANNEL(channel) && !OPL_VALID_LEAF(leaf)) ||
531232457f24de82ba95346b3de302b990fe50f4mv ((channel == OPL_CMU_CHANNEL) && (leaf != 0))) {
531232457f24de82ba95346b3de302b990fe50f4mv FC_DEBUG1(1, CE_CONT, "opl_master_interrupt: invalid port %x\n",
531232457f24de82ba95346b3de302b990fe50f4mv portid);
531232457f24de82ba95346b3de302b990fe50f4mv status = 0;
531232457f24de82ba95346b3de302b990fe50f4mv } else {
531232457f24de82ba95346b3de302b990fe50f4mv status = master_interrupt_init(portid, xt);
531232457f24de82ba95346b3de302b990fe50f4mv }
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv cp->nresults = fc_int2cell(1);
531232457f24de82ba95346b3de302b990fe50f4mv fc_result(cp, 0) = status;
531232457f24de82ba95346b3de302b990fe50f4mv
531232457f24de82ba95346b3de302b990fe50f4mv return (fc_success_op(ap, rp, cp));
531232457f24de82ba95346b3de302b990fe50f4mv}
531232457f24de82ba95346b3de302b990fe50f4mv
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Set the properties for a leaf node (Oberon leaf or CMU channel leaf).
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_create_leaf(dev_info_t *node, void *arg, uint_t flags)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "name", OPL_PCI_LEAF_NODE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP(string, node, "status", "okay");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic char *
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_get_probe_string(opl_probe_t *probe, int channel, int leaf)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *probe_string;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe_string = kmem_zalloc(PROBE_STR_SIZE, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (channel == OPL_CMU_CHANNEL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = probe->pr_sb->sb_cmu.cmu_ch.chan_portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = probe->
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pr_sb->sb_pci_ch[channel].pci_leaf[leaf].leaf_port_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) sprintf(probe_string, "%x", portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (probe_string);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_probe_leaf(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int channel, leaf, portid, error, circ;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fco_handle_t fco_handle, *cfg_handle;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *parent, *leaf_node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char unit_address[UNIT_ADDR_SIZE];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *probe_string;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_board_cfg_t *board_cfg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board = probe->pr_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl channel = probe->pr_channel;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl leaf = probe->pr_leaf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl parent = ddi_root_node();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board_cfg = &opl_boards[board];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(OPL_VALID_CHANNEL(channel));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(OPL_VALID_LEAF(leaf));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (channel == OPL_CMU_CHANNEL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = probe->pr_sb->sb_cmu.cmu_ch.chan_portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cfg_handle = &board_cfg->cfg_cmuch_handle;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = probe->
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pr_sb->sb_pci_ch[channel].pci_leaf[leaf].leaf_port_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cfg_handle = &board_cfg->cfg_pcich_handle[channel][leaf];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Prevent any changes to leaf_node until we have bound
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * it to the correct driver.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_enter(parent, &circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Ideally, fcode would be run from the "sid_branch_create"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * callback (that is the primary purpose of that callback).
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * However, the fcode interpreter was written with the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * assumption that the "new_child" was linked into the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * device tree. The callback is invoked with the devinfo node
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * in the DS_PROTO state. More investigation is needed before
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we can invoke the interpreter from the callback. For now,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we create the "new_child" in the BOUND state, invoke the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fcode interpreter and then rebind the dip to use any
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * compatible properties created by fcode.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_parent = parent;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_create = opl_create_leaf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_hold = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl leaf_node = opl_create_node(probe);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (leaf_node == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: create leaf (%d-%d-%d) failed",
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_board, probe->pr_channel, probe->pr_leaf);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_exit(parent, circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The platform DR interfaces created the dip in
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * bound state. Bring devinfo node down to linked
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * state and hold it there until compatible
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * properties are created.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e_ddi_branch_rele(leaf_node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) i_ndi_unconfig_node(leaf_node, DS_LINKED, 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(i_ddi_node_state(leaf_node) == DS_LINKED);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl e_ddi_branch_hold(leaf_node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&DEVI(leaf_node)->devi_lock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DEVI(leaf_node)->devi_flags |= DEVI_NO_BIND;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&DEVI(leaf_node)->devi_lock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Drop the busy-hold on parent before calling
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fcode_interpreter to prevent potential deadlocks
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_exit(parent, circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) sprintf(unit_address, "%x", portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the probe string
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe_string = opl_get_probe_string(probe, channel, leaf);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The fcode pointer specified here is NULL and the fcode
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * size specified here is 0. This causes the user-level
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fcode interpreter to issue a request to the fcode
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * driver to get the Oberon/cmu-ch fcode.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fco_handle = opl_fc_ops_alloc_handle(parent, leaf_node,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL, 0, unit_address, probe_string);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl error = fcode_interpreter(parent, &opl_fc_do_op, fco_handle);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (error != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: Unable to probe PCI leaf (%d-%d-%d)",
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_board, probe->pr_channel, probe->pr_leaf);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_fc_ops_free_handle(fco_handle);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (probe_string != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(probe_string, PROBE_STR_SIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) opl_destroy_node(leaf_node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *cfg_handle = fco_handle;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (channel == OPL_CMU_CHANNEL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board_cfg->cfg_cmuch_probe_str = probe_string;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board_cfg->cfg_pcich_probe_str[channel][leaf]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl = probe_string;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Compatible properties (if any) have been created,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * so bind driver.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_enter(parent, &circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(i_ddi_node_state(leaf_node) <= DS_LINKED);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&DEVI(leaf_node)->devi_lock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DEVI(leaf_node)->devi_flags &= ~DEVI_NO_BIND;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&DEVI(leaf_node)->devi_lock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_exit(parent, circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl if (ndi_devi_bind_driver(leaf_node, 0) != DDI_SUCCESS) {
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "IKP: Unable to bind PCI leaf "
e98fafb9956429b59c817d4fbd27720c73879203jl "(%d-%d-%d)", probe->pr_board, probe->pr_channel,
e98fafb9956429b59c817d4fbd27720c73879203jl probe->pr_leaf);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((error != 0) && (channel == OPL_CMU_CHANNEL))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_init_leaves(int myboard)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *parent, *node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *name;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int circ, ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len, portid, board, channel, leaf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_board_cfg_t *cfg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl parent = ddi_root_node();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Hold parent node busy to walk its child list
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_enter(parent, &circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl for (node = ddi_get_child(parent); (node != NULL); node =
e98fafb9956429b59c817d4fbd27720c73879203jl ddi_get_next_sibling(node)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = OPL_GET_PROP(string, node, "name", &name, &len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The property does not exist for this node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strncmp(name, OPL_PCI_LEAF_NODE, len) == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = OPL_GET_PROP(int, node, "portid", &portid, -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret == DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = OPL_GET_PROP(int, node, "board#",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &board, -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((ret != DDI_PROP_SUCCESS) ||
68ac2337c38c8af06edcf32a72e42de36ec72a9djl (board != myboard)) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl kmem_free(name, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cfg = &opl_boards[board];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl channel = OPL_PORTID_TO_CHANNEL(portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (channel == OPL_CMU_CHANNEL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (cfg->cfg_cmuch_handle != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cfg->cfg_cmuch_leaf = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl leaf = OPL_PORTID_TO_LEAF(portid);
e98fafb9956429b59c817d4fbd27720c73879203jl if (cfg->cfg_pcich_handle[
e98fafb9956429b59c817d4fbd27720c73879203jl channel][leaf] != NULL)
e98fafb9956429b59c817d4fbd27720c73879203jl cfg->cfg_pcich_leaf[
e98fafb9956429b59c817d4fbd27720c73879203jl channel][leaf] = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(name, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != DDI_PROP_SUCCESS)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_exit(parent, circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create "pci" node and hierarchy for the Oberon channels and the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CMU channel.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_probe_io(opl_probe_t *probe)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i, j;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_pci_ch_t *channels;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (HWD_STATUS_OK(probe->pr_sb->sb_cmu.cmu_ch.chan_status)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_channel = HWD_CMU_CHANNEL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_channel_status =
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_sb->sb_cmu.cmu_ch.chan_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_leaf = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_leaf_status = probe->pr_channel_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_probe_leaf(probe) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl channels = &probe->pr_sb->sb_pci_ch[0];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_PCI_CHANNELS_PER_SB; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!HWD_STATUS_OK(channels[i].pci_status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_channel = i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_channel_status = channels[i].pci_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (j = 0; j < HWD_LEAVES_PER_PCI_CHANNEL; j++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_leaf = j;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_leaf_status =
e98fafb9956429b59c817d4fbd27720c73879203jl channels[i].pci_leaf[j].leaf_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!HWD_STATUS_OK(probe->pr_leaf_status))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) opl_probe_leaf(probe);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_init_leaves(probe->pr_board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Perform the probe in the following order:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * processors
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * memory
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * IO
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Each probe function returns 0 on sucess and a non-zero value on failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * What is a failure is determined by the implementor of the probe function.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * For example, while probing CPUs, any error encountered during probe
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * is considered a failure and causes the whole probe operation to fail.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * However, for I/O, an error encountered while probing one device
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * should not prevent other devices from being probed. It should not cause
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the whole probe operation to fail.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
e98fafb9956429b59c817d4fbd27720c73879203jlopl_probe_sb(int board, unsigned *cpu_impl)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_probe_t *probe;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((board < 0) || (board >= HWD_SBS_PER_DOMAIN))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(opl_cfg_inited != 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If the previous probe failed and left a partially configured
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * board, we need to unprobe the board and start with a clean slate.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((opl_boards[board].cfg_hwd != NULL) &&
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (opl_unprobe_sb(board) != 0))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe = kmem_zalloc(sizeof (opl_probe_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe->pr_board = board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((opl_probe_init(probe) != 0) ||
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (opl_probe_cpu_chips(probe) != 0) ||
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (opl_probe_memory(probe) != 0) ||
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (opl_probe_io(probe) != 0)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Probe failed. Perform cleanup.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) opl_unprobe_sb(board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl *cpu_impl = probe->pr_cpu_impl;
e98fafb9956429b59c817d4fbd27720c73879203jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(probe, sizeof (opl_probe_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ret);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This unprobing also includes CMU-CH.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_unprobe_io(int board)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i, j, ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_board_cfg_t *board_cfg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t **node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl fco_handle_t *hand;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char **probe_str;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board_cfg = &opl_boards[board];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_PCI_CHANNELS_PER_SB; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (j = 0; j < HWD_LEAVES_PER_PCI_CHANNEL; j++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = &board_cfg->cfg_pcich_leaf[i][j];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hand = &board_cfg->cfg_pcich_handle[i][j];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe_str = &board_cfg->cfg_pcich_probe_str[i][j];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (*node == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (*hand != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_fc_ops_free_handle(*hand);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *hand = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (*probe_str != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(*probe_str, PROBE_STR_SIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *probe_str = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ret = opl_destroy_node(*node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ret != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "IKP: destroy pci (%d-%d-%d) "
e98fafb9956429b59c817d4fbd27720c73879203jl "failed", board, i, j);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *node = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = &board_cfg->cfg_cmuch_leaf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hand = &board_cfg->cfg_cmuch_handle;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl probe_str = &board_cfg->cfg_cmuch_probe_str;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (*node == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (*hand != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_fc_ops_free_handle(*hand);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *hand = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (*probe_str != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(*probe_str, PROBE_STR_SIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *probe_str = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_destroy_node(*node) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "IKP: destroy pci (%d-%d-%d) failed", board,
e98fafb9956429b59c817d4fbd27720c73879203jl OPL_CMU_CHANNEL, 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *node = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Destroy the "pseudo-mc" node for a board.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_unprobe_memory(int board)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_board_cfg_t *board_cfg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board_cfg = &opl_boards[board];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (board_cfg->cfg_pseudo_mc == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_destroy_node(board_cfg->cfg_pseudo_mc) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IKP: destroy pseudo-mc (%d) failed", board);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl board_cfg->cfg_pseudo_mc = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Destroy the "cmp" nodes for a board. This also destroys the "core"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and "cpu" nodes below the "cmp" nodes.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_unprobe_processors(int board)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t **cfg_cpu_chips;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cfg_cpu_chips = opl_boards[board].cfg_cpu_chips;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_CPU_CHIPS_PER_CMU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (cfg_cpu_chips[i] == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_destroy_node(cfg_cpu_chips[i]) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "IKP: destroy chip (%d-%d) failed",
e98fafb9956429b59c817d4fbd27720c73879203jl board, i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cfg_cpu_chips[i] = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Perform the unprobe in the following order:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * IO
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * memory
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * processors
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_unprobe_sb(int board)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((board < 0) || (board >= HWD_SBS_PER_DOMAIN))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(opl_cfg_inited != 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((opl_unprobe_io(board) != 0) ||
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (opl_unprobe_memory(board) != 0) ||
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (opl_unprobe_processors(board) != 0))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_boards[board].cfg_hwd != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef UCTEST
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size_t size = 0xA000;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Release the memory for the HWD */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *hwdp = opl_boards[board].cfg_hwd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_boards[board].cfg_hwd = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef UCTEST
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwdp = (void *)((char *)hwdp - 0x1000);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hat_unload(kas.a_hat, hwdp, size, HAT_UNLOAD_UNLOCK);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl vmem_free(heap_arena, hwdp, size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(hwdp, HWD_DATA_SIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * For MAC patrol support, we need to update the PA-related properties
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * when there is a copy-rename event. This should be called after the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * physical copy and rename has been done by DR, and before the MAC
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * patrol is restarted.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jloplcfg_pa_swap(int from, int to)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *from_node = opl_boards[from].cfg_pseudo_mc;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *to_node = opl_boards[to].cfg_pseudo_mc;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_range_t *rangef, *ranget;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int elems;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ret;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((OPL_GET_PROP_ARRAY(int, from_node, "sb-mem-ranges", rangef,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl elems) != DDI_SUCCESS) || (elems != 4)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* XXX -- bad news */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((OPL_GET_PROP_ARRAY(int, to_node, "sb-mem-ranges", ranget,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl elems) != DDI_SUCCESS) || (elems != 4)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* XXX -- bad news */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP_ARRAY(int, from_node, "sb-mem-ranges", (int *)ranget,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 4);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_UPDATE_PROP_ARRAY(int, to_node, "sb-mem-ranges", (int *)rangef,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 4);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_FREE_PROP(ranget);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl OPL_FREE_PROP(rangef);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}