03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Common Development and Distribution License (the "License").
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MonteCarlo HotSwap Controller functionality
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_HSC_FORCE_REMOVE 1 /* force remove enum intr handler */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* TUNABLE PARAMETERS. Some are Debug Only. Please take care when using. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set this flag to 1, to enable full hotswap mode at boot time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since HPS is threaded, it is not recommended that we set this flag
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to 1 because enabling full hotswap interrupt can invoke the ENUM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * event handler accessing the slot data structure which may have not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been initialized in the hotplug framework since the HPS may not yet
03831d35f7499c87d51205817c93e9a8d42c4baestevel * have called the slot registration function with the bus nexus.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Every time a slot is registered with the hotswap framework, the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * framework calls back. This variable keeps a count on how many
03831d35f7499c87d51205817c93e9a8d42c4baestevel * callbacks are done.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When this flag is set, the board is taken offline (put in reset) after
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a unconfigure operation, in Basic Hotswap mode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When this flag is set, we take the board to reset after unconfigure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * operation when operating in full hotswap mode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Implementation of this counter will work only on Montecarlo since
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the ENUM# Interrupt line is not shared with other interrupts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When the hardware routing changes, then there may be need to remove
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or change this functionality.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This functionality is provided so that a bad or non friendly full hotswap
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board does not hang the system in full hotswap mode. Atleast the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * intent is that! Eventually Solaris kernel will provide similar support
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for recovering from a stuck interrupt line. Till then, lets do this.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since the hardware does not support enabling/disabling ENUM#, the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * following flag can be used for imitating that behaviour.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Currently we can set this flag and use the remove op to remove the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt handler from the system. Care must be taken when using this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * function since trying to remove the interrupt handler when the interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are pending may hang the system permanently.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since the hardware does not support this functionality, we adopt this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * approach for debugs.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When the board loses Healthy# at runtime (with the board being configured),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cPCI specs states that a Reset has to be asserted immediately.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We dont do this currently, until satellite processor support is given
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and the implications of such a act is fully understood.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To adopt the cPCI specs recommendation, set this flag to 1.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * According to PCI 2.2 specification, once a board comes out of PCI_RST#,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it may take upto 2^25 clock cycles to respond to config cycles. For
03831d35f7499c87d51205817c93e9a8d42c4baestevel * montecarlo using a 33MHz cPCI bus, it's around 1.024 s. The variable
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will specify the time in ms to wait before attempting config access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot map property for MC should be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hsc-slot-map="/pci@1f,0/pci@1/pci@1","15","2",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1","14","3",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1","13","4",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1","12","5"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1","11","6"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1","10","7"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1","8","8";
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot map property for Tonga should be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hsc-slot-map="/pci@1f,0/pci@1/pci@1","8","1"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1", "15", "2"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1", "14", "4"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "/pci@1f,0/pci@1/pci@1", "13", "5"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Please note that the CPU slot number is 3 for Tonga.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Services we require from the SCSB
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int scsb_get_slot_state(void *, int, int *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int scsb_read_slot_health(scsb_state_t *scsb, int pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int scsb_connect_slot(void *, int, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int scsb_disconnect_slot(void *, int, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic hsc_slot_t *hsc_get_slot_info(hsc_state_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int atoi(const char *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int isdigit(int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void hsc_led_op(hsc_slot_t *, int, hpc_led_t, hpc_led_state_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int hsc_led_state(hsc_slot_t *, int, hpc_led_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int hsc_slot_register(hsc_state_t *, char *, uint16_t, uint_t,
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int hsc_slot_unregister(int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_hsc_init_slot_state(hsc_state_t *, hsc_slot_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic hsc_slot_t *hsc_slot_list; /* linked list of slots */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This mutex protects the following variables:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hsc_slot_list
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_connect(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("hsc_connect: slot %d, healthy %d", hsp->hs_slot_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(hsp->hs_flags & (HSC_ENABLED|HSC_SLOT_ENABLED)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* if SCB hotswapped, do not allow connect operations */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if previous occupant stayed configured, do not allow another
03831d35f7499c87d51205817c93e9a8d42c4baestevel * occupant to be connected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This behaviour is an indication that the slot state
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is not clean.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In the current implementation, we turn both fault
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and active LEDs to ON state in this situation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the actual status from the i2c bus
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb_get_slot_state(hsp->hs_hpchandle, hsp->hs_slot_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "?hsc_connect: slot %d is empty\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * call scsb to connect the slot. This also makes sure board is healthy
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_connect_slot(hsp->hs_hpchandle, hsp->hs_slot_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unresetting a board may have caused an interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * burst in case of non friendly boards. So it is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * important to make sure that the ISR has not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * put this board back to disconnect state.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PCI 2.2 specs recommend that the probe software wait
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for upto 2^25 PCI clock cycles after deassertion of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PCI_RST# before the board is able to respond to config
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cycles. So, before we return, we wait for ~1 sec.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_disconnect(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_disconnect: slot %d", hsp->hs_slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel "%s: cannot disconnect configured board in slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if already disconnected, just return success
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Duplicate disconnect messages should not be failed!
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* if SCB hotswapped, do not allow disconnect operations */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* call scsb to disconnect the slot */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_disconnect_slot(hsp->hs_hpchandle, B_TRUE, hsp->hs_slot_number)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In the cPCI world, this operation is not applicable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * However, we use this function to enable full hotswap mode in debug mode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_insert(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In the cPCI world, this operation is not applicable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * However, we use this function to disable full hotswap mode in debug mode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_remove(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags)
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_led_op(hsc_slot_t *hsp, int cmd, hpc_led_t led, hpc_led_state_t led_state)
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_led_state(hsc_slot_t *hsp, int cmd, hpc_led_info_t *hlip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We ignore operations on LEDs that we don't support
03831d35f7499c87d51205817c93e9a8d42c4baestevel res = scsb_led_set(hsp->hs_hpchandle, &sunit, sunit.led_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel res = scsb_led_get(hsp->hs_hpchandle, &sunit, sunit.led_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hlip->state = sunit.unit_state; */
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_get_slot_state(hsc_slot_t *hsp, hpc_slot_state_t *hssp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_get_slot_state: slot %d", hsp->hs_slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb_get_slot_state(hsp->hs_hpchandle, hsp->hs_slot_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* doing get-state above may have caused a freeze operation */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* freeze puts disconnected boards to connected state */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* in FHS, deassertion of reset may have configured the board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* a SCB hotswap may have forced a state change on the receptacle */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "hsc_get_state: slot%d state change due"
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_set_config_state: slot %d", hsp->hs_slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Closing of the Ejector switch in configured/busy state can
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cause duplicate CONFIGURED messages to come down.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make sure our LED states are fine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LED must be OFF on the occupant. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((hsc->state & HSC_ENUM_ENABLED) != HSC_ENUM_ENABLED) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the callback is invoked for all registered slots,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * enable ENUM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel ":%d non-empty slots\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Full Hotswap",
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_get_board_type(hsc_slot_t *hsp, hpc_board_type_t *hbtp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_autoconfig: slot %d", hsp->hs_slot_number);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(slotautocfg_prop, "slot%d-autoconfig",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsp->hsc->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((res = scsb_enable_enum(hsp->hsc)) == DDI_SUCCESS) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsp->hsc->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "No Slot Info for slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is invoked to enable/disable a slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_slot_enable: slot %d", hsp->hs_slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_control(caddr_t ops_arg, hpc_slot_t slot_hdl, int request, caddr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("hsc_control: slot %d, op=%x\n", hsp->hs_slot_number, request);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_get_slot_state(hsp, (hpc_slot_state_t *)arg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_set_config_state(hsp, HPC_CTRL_DEV_CONFIGURED));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_set_config_state(hsp, HPC_CTRL_DEV_UNCONFIGURED));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_set_config_state(hsp, HPC_CTRL_DEV_CONFIG_FAILURE));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_get_board_type(hsp, (hpc_board_type_t *)arg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_autoconfig(hsp, HPC_CTRL_DISABLE_AUTOCFG));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_autoconfig(hsp, HPC_CTRL_ENABLE_AUTOCFG));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No hardware support for disabling the slot.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Just imitate a disable_autoconfig operation for now
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_disable_slot: slot %d", hsp->hs_slot_number);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(slot_disable_prop, "slot%d-status", hsp->hs_slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb_reset_slot(hsp->hs_hpchandle, hsp->hs_slot_number,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) hsc_autoconfig(hsp, HPC_CTRL_DISABLE_AUTOCFG);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsp->hsc->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_disable_slot: slot %d", hsp->hs_slot_number);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(slot_disable_prop, "slot%d-status", hsp->hs_slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb_reset_slot(hsp->hs_hpchandle, hsp->hs_slot_number,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) hsc_autoconfig(hsp, HPC_CTRL_ENABLE_AUTOCFG);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_remove(DDI_DEV_T_NONE, hsp->hsc->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define NEW(type) (type *) kmem_zalloc(sizeof (type), KM_SLEEP)
03831d35f7499c87d51205817c93e9a8d42c4baestevel "hsc_alloc_slot: allocation failed for slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note: the name *must* be 'pci' so that the correct cfgadm plug-in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * library is selected
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(hsip->pci_slot_name, "cpci_slot%d", slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We assume that the following LED settings reflect
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the hardware state.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * After we register the slot, we will be invoked by the nexus
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if the slot is occupied, and we will turn on the LED then.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we should just set this to connected,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as MC slots are always connected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is invoked to register a slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("hsc_slot_register: slot number %d, device number %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "hsc_slot_register: hsc_alloc_slot failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsp->hs_hpchandle = hsc->scsb_handle; /* handle for call backs */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* slot autoconfiguration by default. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) hsc_autoconfig(hsp, HPC_CTRL_DISABLE_AUTOCFG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Append to our list
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: failed to register slot %s:%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_driver_name(hsc->dip), ddi_get_instance(hsc->dip),
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("hsc_slot_register: hpc_slot_register successful");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_slot_unregister: slot number %d", slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (hsp = hsc_slot_list; hsp != NULL; hsp = hsp->hs_next) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) hpc_slot_unregister(&hsp->hs_slot_handle);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((hsp->hsc->state & HSC_ATTACHED) != HSC_ATTACHED &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_hsc_init_slot_state(hsc_state_t *hsc, hsc_slot_t *hsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb = (scsb_state_t *)hsc->scsb_handle;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb_get_slot_state(hsc->scsb_handle, slot_number, &rstate);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set the healthy status for this slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsp->hs_board_healthy = scsb_read_slot_health(scsb, slot_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this will clear any state differences between
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB Freeze operations.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* slot empty. */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_reset_slot(hsc->scsb_handle, slot_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this will clear any state differences between
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB Freeze operations.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check recovery from SCB freeze */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Force a disconnect just in case there are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * differences between healthy and reset states.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Slot in reset. OBP has not probed this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * device. Hence it is ok to remove this board.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*FALLTHROUGH*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this will clear any state differences between
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB Freeze operations.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OBP should have probed this device, unless
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it was plugged in during the boot operation
03831d35f7499c87d51205817c93e9a8d42c4baestevel * before the driver was loaded. In any case,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * no assumption is made and hence we take
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the conservative approach by keeping fault
03831d35f7499c87d51205817c93e9a8d42c4baestevel * led off so board removal is not allowed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Netra ct alarm card hotswap support
03831d35f7499c87d51205817c93e9a8d42c4baestevel "set HSC_ALARM_CARD_PRES");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (hsp = hsc_slot_list; hsp != NULL; hsp = hsp->hs_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is invoked by the SCSB when an interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * happens to indicate that a board has been inserted-in/removed-from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the specified slot.
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_slot_occupancy(int slot_number, boolean_t occupied, int flags, int healthy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG4("hsc_slot_occupancy: slot %d %s, ac=%d, healthy=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "%s: cannot map slot number %d to a hsc_slot_t",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A board was just inserted. We are disconnected at this point.
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("Xhsc_slot_occupancy: set HSC_ALARM_CARD_PRES");
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if previous occupant stayed configured, do not allow another
03831d35f7499c87d51205817c93e9a8d42c4baestevel * occupant to be connected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * So as soon as the board is plugged in, we turn both LEDs On.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This behaviour is an indication that the slot state
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is not clean.
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Do not allow connect if slot is disabled */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((hsp->hs_flags & HSC_SLOT_ENABLED) != HSC_SLOT_ENABLED)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* if no healthy, we stay disconnected. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A board was just removed
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("Xhsc_slot_occupancy:clear HSC_ALARM_CARD_PRES");
03831d35f7499c87d51205817c93e9a8d42c4baestevel " on Slot %d, Occupant Online!!",
03831d35f7499c87d51205817c93e9a8d42c4baestevel " Inconsistent State! Slot disabled. Halt!",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Slot in reset and disabled */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* the following works for P1.0 only. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is invoked by the SCSB when the health status of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a board changes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_hsc_board_healthy(int slot_number, boolean_t healthy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("hsc_board_healthy: slot %d = %d\n", slot_number, healthy);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "hsc_board_healthy: No Slot Info.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Connect the slot if board healthy and in autoconfig mode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the board is connected. The result could be seviour depending
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on the occupant state.
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Regained HEALTHY# at Run Time...!!! */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "%s, Regained HEALTHY#!",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Lost HEALTHY# at Run Time...Serious Condition. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel " on Slot %d, Occupant %s",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* signal Ok to remove board. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "successfully taken offline",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Keep slot in reset unless autoconfiguration is enabled
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ie. for Basic Hotswap mode, we stay disconnected at
03831d35f7499c87d51205817c93e9a8d42c4baestevel * insertion. For full hotswap mode, we automatically
03831d35f7499c87d51205817c93e9a8d42c4baestevel * go into connected state at insertion, so that occupant
03831d35f7499c87d51205817c93e9a8d42c4baestevel * autoconfiguration is possible.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((hsc->state & HSC_ENUM_ENABLED) == HSC_ENUM_ENABLED) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* this statement must be here before unreset. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The SCSB code should invoke this function from its _init() function.
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = ddi_soft_state_init(&hsc_state, sizeof (hsc_state_t), 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The SCSB code should invoke this function from its _fini() function.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((hsc->state & HSC_ENUM_ENABLED) == HSC_ENUM_ENABLED)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: failed ENUM# interrupt registration",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_driver_name(hsc->dip), ddi_get_instance(hsc->dip));
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsc->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear all pending interrupts before unregistering
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the interrupt. Otherwise the system will hang.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Due to the hang problem, we'll not turn off or disable
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts because if there's a non-friendly full hotswap
03831d35f7499c87d51205817c93e9a8d42c4baestevel * device out there, the ENUM# will be kept asserted and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hence hsc_clear_all_enum() can never deassert ENUM#.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * So the system will hang.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((hsc->state & HSC_ENUM_ENABLED) == HSC_ENUM_ENABLED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hsc_clear_all_enum(hsc); */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "?%s%d: Successfully Downgraded to "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Basic Hotswap Mode\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsc->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* No programming interface for disabling ENUM# on MC/Tonga */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsp = hsc_find_slot(hsc->slot_table_prop[i].pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break; /* no pending interrupts across the bus */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_hsc_attach(dev_info_t *dip, void *scsb_handle, int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel int prom_prop = 0; /* default: OS property gives slot-table */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To get the slot information,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The OBP defines the 'slot-table' property. But the OS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can override it with 'hsc-slot-map' property
03831d35f7499c87d51205817c93e9a8d42c4baestevel * through the .conf file.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since the formats are different, 2 different property names
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are chosen.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The OBP property format is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * <phandle>,<pci-devno>,<phys-slotno>,<ga-bits>
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The OS property format is (ga-bits is not used however)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * <busnexus-path>,<pci-devno>,<phys-slotno>,<ga-bits>
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hsc->slot_info = hsc_slot_list; */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check whether the system should be in basic or full
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hotswap mode. The PROM property always says full, so
03831d35f7499c87d51205817c93e9a8d42c4baestevel * look at the .conf file property whether this is "full"
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "default-hotswap-mode", (caddr_t)&hotswap_model, &prop_len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Determine the size of the slot table from the property and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allocate the slot table arrary..Decoding is different for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OS and PROM property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0, n = 0; i < hpc_slot_table_size; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* There should be four elements per entry */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (n % 4) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel n = hpc_slot_table_size % sizeof (hsc_prom_slot_table_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Netract800 FTC (formerly known as CFTM) workaround.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Leave Slot 2 out of the HS table if FTC is present in Slot 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("hsc_attach: %d hotplug slots on bus\n", hsc->slot_table_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create enough space for each slot table entry
03831d35f7499c87d51205817c93e9a8d42c4baestevel * based on how many entries in the property
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Pick off pointer to nexus path or PROM handle */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*s != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Pick off pointer to the pci device number */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*s != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Pick off physical slot no */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*s != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Pick off GA bits which we dont use for now. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*s != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc->slot_table_prop[i].pslotnum = atoi(phys_slotname);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strcpy(hsc->slot_table_prop[i].nexus, nexus);
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpstp = (hsc_prom_slot_table_t *)hpc_slot_table_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < hsc->slot_table_size; i++, hpstp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc->slot_table_prop[i].pci_devno = hpstp->pci_devno;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* keep healthy register cache uptodate before reading slot state */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Before we start registering the slots, calculate how many
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slots are occupied.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&hsc->hsc_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("Registering on nexus [%s] cPCI device [%d]\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hsc_slot_register(hsc, hsc->slot_table_prop[i].nexus,
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "%s#%d: failed to unregister"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(hsc->slot_table_prop, (hsc->slot_table_size *
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsc->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We enable full hotswap right here if all the slots are empty.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((hsc->regDone == B_FALSE && hsc->n_registered_occupants == 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_hsc_detach(dev_info_t *dip, void *scsb_handle, int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * let's unregister the hotpluggable slots with hotplug service.
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsp = hsc_find_slot(hsc->slot_table_prop[i].pslotnum);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(slotautocfg_prop, "slot%d-autoconfig",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_remove(DDI_DEV_T_NONE, hsc->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hsc_slot_unregister(hsc->slot_table_prop[i].pslotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(hsc->slot_table_prop, (hsc->slot_table_size *
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((hsc->state & HSC_ENUM_ENABLED) == HSC_ENUM_ENABLED) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_prop_remove(DDI_DEV_T_NONE, hsc->dip, HOTSWAP_MODE_PROP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The following function is called when the SCSB is hot extracted from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the system.
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsp = hsc_find_slot(hsc->slot_table_prop[i].pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel " Cannot map slot number %d to a hsc_slot_t",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since reset lines are pulled low, lets mark these
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slots and not allow a connect operation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that we still keep the slot as slot disconnected,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * although it is connected from the hardware standpoint.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * As soon as the SCB is plugged back in, we check these
03831d35f7499c87d51205817c93e9a8d42c4baestevel * states and put the hardware state back to its original
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The following function is called when the SCSB is hot inserted from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the system. We must update the LED status and set the RST# registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsp = hsc_find_slot(hsc->slot_table_prop[i].pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel " Cannot map slot number %d to a hsc_slot_t",
03831d35f7499c87d51205817c93e9a8d42c4baestevel " Cannot reset disconnected slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_hsc_init_slot_state(hsc, hsp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot%d state",
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * update info about Alarm Card insert/remove mechanism.
03831d35f7499c87d51205817c93e9a8d42c4baestevelhsc_ac_op(int instance, int pslotnum, int op, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: hsc_ac_op: No Soft State Info",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_driver_name(hsc->dip), ddi_get_instance(hsc->dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_driver_name(hsc->dip), ddi_get_instance(hsc->dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If ENUM# is enabled, then action is pending on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this slot, just send a event.
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsp = hsc_find_slot(hsc->slot_table_prop[0].pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The following must be done to clear interrupt (synchronous event).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To process the interrupt, we send an asynchronous event.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * possible support for handling insertion of non friendly
03831d35f7499c87d51205817c93e9a8d42c4baestevel * full hotswap boards, otherwise the system hangs due
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to uncleared interrupt bursts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hsc->hsc_intr_counter == scsb_hsc_max_intr_count) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel " No Last Board Insertion Info.",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: Bad (non friendly ?) Board "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "in Slot %d ? Taking it Offline.",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this should put just inserted board back in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reset, thus deasserting the ENUM# and the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * system hang.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Enumeration failed on this board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel " now in Inconsistent State."
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if interrupt success, rc denotes the PCI device number which
03831d35f7499c87d51205817c93e9a8d42c4baestevel * generated the ENUM# interrupt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: hsc_enum_intr: no slot info for "
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED); /* interrupt already cleared */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* if this is Alarm Card and if it is busy, dont process event */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_hsc_ac_op(hsp->hs_hpchandle, hsp->hs_slot_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Busy means we need to inform (envmond)alarmcard.so
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that it should save the AC configuration, stop the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * heartbeat, and shutdown the RSC link.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If SCB was swapped out, dont process ENUM#. We put this slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel * back in reset after SCB is inserted.
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) hpc_slot_event_notify(hsp->hs_slot_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A routine to convert a number (represented as a string) to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the integer value it represents.
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!isdigit(c = *p)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (c) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHROUGH */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel n *= 10; /* two steps to avoid unnecessary overflow */
03831d35f7499c87d51205817c93e9a8d42c4baestevel n += '0' - c; /* accum neg to avoid surprises at MAX */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (neg ? n : -n);