/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Serengeti Platform specific functions.
*
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <kstat.h>
#include <string.h>
#include <assert.h>
#include <alloca.h>
#include <libintl.h>
#include <fcntl.h>
#include <varargs.h>
#include <sys/openpromio.h>
#include <sys/sysmacros.h>
#include <sys/serengeti.h>
#include <sys/sgfrutypes.h>
#include <pdevinfo.h>
#include <display.h>
#include <pdevinfo_sun4u.h>
#include <display_sun4u.h>
#include <libprtdiag.h>
#include <config_admin.h>
#if !defined(TEXT_DOMAIN)
#endif
#define ACTIVE 0
(e) == CFGA_STAT_EMPTY ? "empty" : \
(e) == CFGA_STAT_DISCONNECTED ? "disconnected" : \
(e) == CFGA_STAT_CONNECTED ? "connected" : \
(e) == CFGA_STAT_UNCONFIGURED ? "unconfigured" : \
(e) == CFGA_STAT_CONFIGURED ? "configured" : \
"unknown")
(c) == CFGA_COND_OK ? "ok" : \
(c) == CFGA_COND_FAILING ? "failing" : \
(c) == CFGA_COND_FAILED ? "failed" : \
(c) == CFGA_COND_UNUSABLE ? "unusable" : \
"???")
#define SG_SCHIZO_GOOD 0
{ \
char tmp_str[MAX_FRU_NAME_LEN]; \
}
{ \
char tmp_str[MAX_FRU_NAME_LEN]; \
}
{ \
char tmp_str[MAX_FRU_NAME_LEN]; \
}
extern int print_flag;
/*
* these functions will overlay the symbol table of libprtdiag
* at runtime (Serengeti systems only)
*/
void display_pci(Board_node *);
void display_ffb(Board_node *, int);
struct system_kstat_data *kstats);
void get_failed_parts(void);
/* Local Functions */
Board_node *bnode);
static void serengeti_display_board_info(int state);
static void serengeti_display_board_info_header(int state);
static void display_io_max_bus_speed(struct io_card *p);
static void display_io_slot_info(struct io_card *p);
/* The bus max freq is determined based on board level in use */
/*
* Serengeti now uses both the devinfo tree and the OBP tree for it's
* prtdiag. The devinfo tree is used for getting the HW config of the
* system and the OBP device tree is used for listing the failed HW
* in the system. This is because devinfo currently does not include
* any PROM nodes with a status of 'fail' so we need to go to OBP to
* get a list of failed HW. We use the tree flag to allow the same code
* to walk both trees.
*
* We really need to look at having a single tree for all platforms!
*/
#ifdef DEBUG
void
{
int i = 0;
for (i = 0; i < indent; i ++)
printf("\t");
}
#else
#define D_PRINTFINDENT
#endif
/*
* display_pci
* Display all the PCI IO cards on this board.
*/
void
{
void *value;
char *child_name;
int *int_val;
int pci_bus;
int pci_bridge = 0;
int pci_bridge_dev_no;
int i;
int portid;
int level = 0;
#ifdef DEBUG
int slot_name_bits;
#endif
return;
/* Initialize all the common information */
/*
* each schizo and xmits node found.
*/
/* set max freq for this board */
/*
* Find out if this is a PCI or cPCI IO Board.
* If "enum-impl" property exists in pci node => cPCI.
*/
} else {
}
if (strstr((char *)get_prop_val(
/*
* With XMITS 3.X and PCI-X mode, the bus speed
* can be higher than 66MHZ.
*/
value = (int *)get_prop_val
if (value) {
if (version >= 4)
}
} else if (strstr((char *)get_prop_val(
else
/*
* Get slot-name properties from parent node and
* store them in an array.
*/
#ifdef DEBUG
/* save the 4 byte bitmask */
slot_name_bits = *(int *)value;
#endif
/* array starts after first int */
slot_name_arr[0] = (char *)value + sizeof (int);
D_PRINTFINDENT(0, "slot_name_arr[0] is [%s]\n",
slot_name_arr[0]);
for (i = 1; i < SG_MAX_SLOTS_PER_IO_BD; i++) {
D_PRINTFINDENT(0, "slot_name_arr[%d] is [%s]\n", i,
slot_name_arr[i]);
}
}
/*
* Search for Children of this node ie. Cards.
* Note: any of these cards can be a pci-bridge
* that itself has children. If we find a
* pci-bridge we need to handle it specially.
*
* There can now be the condition of a pci-bridge
* being the child of a pci-bridge which create a
* two levels of pci-bridges. This special condition
* needs to be handled as well. The variable level
* is used to track the depth of the tree. This
* variable is then used to find instances of this case.
*/
level = 0;
pci_bridge = 0;
/* If it doesn't have a name, skip it */
name = (char *)get_prop_val(
continue;
}
type = (char *)get_prop_val(
/*
* get dev# and func# for this card from the
* 'reg' property.
*/
int_val = (int *)get_prop_val(
} else {
}
/*
* If this is a pci-bridge, then store it's dev#
* as it's children nodes need this to get their slot#.
* We set the pci_bridge flag so that we know we are
* looking at a pci-bridge node. This flag gets reset
* every time we enter this while loop.
*/
/*
* Check for a PCI-PCI Bridge for PCI and cPCI
* IO Boards using the name and type properties.
*
* If level is greater then 0, then check the parent
* node to see if it was also a pci-bridge. We do not
* this when level is 0 as this will see the schizo or
* xmits device as a pci-bridge node. This will mess
* up the slot number of child nodes.
*/
if (level > 0) {
pname = (char *)get_prop_val(
"name"));
ptype = (char *)get_prop_val(
"device_type"));
} else {
}
} else {
}
pci_bridge = TRUE;
"pci_bridge_dev_no is [%d]\n",
}
/*
* Get slot-names property from slot_names_arr.
* If we are the child of a pci_bridge we use the
* dev# of the pci_bridge as an index to get
* the slot number. We know that we are a child of
* a pci-bridge if our parent is the same as the last
* pci_bridge node found above.
*/
if (type)
"*** name is [%s] - type is [%s]\n",
else
"*** name is [%s]\n", name);
/*
* We compare this cards parent node with the
* pci_bridge_node to see if it's a child.
*/
if (((level > 0) &&
pci_bridge_node)) ||
/* use dev_no of pci_bridge */
" pci_bridge_dev_no is [%d]\n",
} else {
/* use cards own dev_no */
" card.dev_no is [%d]\n",
}
} else {
}
/*
* Get the portid of the schizo and xmits that this card
* lives under.
*/
portid = -1;
}
#ifdef DEBUG
" slot_name[%s] name_bits[%d]",
#endif
/*
* Find out whether this is PCI bus A or B
* using the 'reg' property.
*/
int_val = (int *)get_prop_val
int_val ++; /* skip over first integer */
if (pci_bus == 0x600000)
else if (pci_bus == 0x700000)
else
} else {
}
/*
* Check for failed status.
*/
sizeof (SG_FAIL));
sizeof (SG_DISABLED));
else
sizeof (SG_OK));
/* Get the model of this card */
else {
(char *)value);
/* Skip sgsbbc nodes, they are not cards */
continue;
}
}
/*
* Check if further processing is necessary to display
* this card uniquely.
*/
/*
* The card may have a "clock-frequency" but we
* are not interested in that. Instead we get the
* "clock-frequency" of the PCI Bus that the card
* resides on. PCI-A can operate at 33Mhz or 66Mhz
* depending on what card is plugged into the Bus.
* PCI-B always operates at 33Mhz.
*
*/
"clock-frequency"));
} else {
}
/*
* Figure out how we want to display the name
*/
"compatible"));
/* use 'name'-'compatible' */
(char *)value);
} else {
/* just use 'name' */
}
/*
* If this node has children, add the device_type
* of the child to the name value of this card.
*/
(child_name != NULL)) {
"device_type"));
/* add device_type of child to name */
(char *)value);
} else {
/* just add childs name */
}
} else {
}
/*
* If this is a pci-bridge, then add the word
* 'pci-bridge' to it's model.
*/
if (pci_bridge) {
"%s", "pci-bridge");
else
}
/* insert this card in the list to be displayed later */
/*
* If we are dealing with a pci-bridge, we need to move
* down to the children of this bridge if there are any.
*
* If we are not, we are either dealing with a regular
* card (in which case we move onto the sibling of this
* card) or we are dealing with a child of a pci-bridge
* (in which case we move onto the child's siblings or
* if there are no more siblings for this child, we
* move onto the parents siblings).
*
* Once we reach the last child node of a pci-bridge,
* we need to back up the tree to the parents sibling
* node. If our parent has no more siblings, we need
* to check our grand parent for siblings.
*
* If we have no more siblings, we simply point to
* to the child's sibling which moves us onto the next
* bus leaf.
*
* The variable level gets adjusted on some of the
* conditions as this is used to track level within
* the tree we have reached.
*/
if (pci_bridge) {
level++;
} else
} else {
if (level > 0)
level--;
pci_bridge_node)) {
if ((child_pci_bridge_node->sibling) &&
if (level > 0)
level--;
} else if ((pci_bridge_node->sibling) &&
if (level > 1)
else if (level > 0)
level--;
} else
} else
}
} /* end-while */
} /* end-for */
}
/*
* display_ffb
*
* There are no FFB's on a Serengeti, however in the generic library,
* the display_ffb() function is implemented so we have to define an
* empty function here.
*/
/*ARGSUSED0*/
void
{}
static void
{
log_printf("\n", 0);
log_printf("=========================", 0);
" Active Boards for Domain "), 0);
else
log_printf("===========================", 0);
log_printf("\n", 0);
log_printf("\n", 0);
"Condition", "Info", 0);
"------------", "---------",
"----------------------------------------", 0);
}
static void
{
int i, z, ret;
int nlist = 0;
int available_board_count = 0;
&err_string, flags);
for (i = 0; i < nlist; i++) {
continue;
continue;
if (tmp_id[z] == '.')
tmp_id[z] = '/';
}
}
(available_board_count == 0)) {
"There are currently no "
"to this Domain\n"), 0);
}
}
if (board_cfg)
if (err_string)
}
/*
* add_node
*
* This function adds a board node to the board structure where that
* that node's physical component lives.
*/
void
{
char *type;
/* Get the board number of this board from the portid prop */
value =
}
}
/* find the board node with the same board number */
}
/* now attach this prom node to the board list */
/* Insert this node at the end of the list */
else {
p = p->sibling;
}
}
/*
* Print out all the io cards in the list. Also print the column
* headers if told to do so.
*/
void
{
struct io_card *p;
return;
"", "", "", 0);
log_printf("\n", 0);
"Dev,", "", "", 0);
log_printf("\n", 0);
"MHz", "Freq", "Func", "State", "Name", 0);
#ifdef DEBUG
log_printf("Model Notes\n", 0);
#else
log_printf("Model\n", 0);
#endif
"----", "----", "----", "-----",
"--------------------------------", 0);
#ifdef DEBUG
log_printf("---------------------- ", 0);
#endif
log_printf("----------------------\n", 0);
}
log_printf("\n", 0);
}
}
static void
{
}
static void
{
switch (p->pci_bus) {
case 'A':
break;
case 'B':
BUS_SPEED_PRINT(33);
else
} else
BUS_SPEED_PRINT(33);
break;
default:
log_printf(" - ", 0);
break;
}
#ifdef DEBUG
#endif /* DEBUG */
}
void
{
/* printf formats */
/*
* Display the table header for CPUs . Then display the CPU
* frequency, cache size, and processor revision of all cpus.
*/
log_printf("\n", 0);
log_printf("=========================", 0);
log_printf(" CPUs ", 0);
log_printf("=========================", 0);
log_printf("======================", 0);
log_printf("\n", 0);
log_printf("\n", 0);
"Impl.", "Mask", 0);
"-------", "----", 0);
/* Now display all of the cpus on each board */
}
log_printf("\n", 0);
}
static boolean_t
{
int ret, i;
int nlist = 0;
return (FALSE);
else
} else {
}
if (statlist)
if (err_string)
return (rv);
}
/*
* Display the CPUs present on this board.
*/
void
{
int *mid;
int *impl;
int *mask;
int decoded_mask;
int *coreid;
int ecache_size_prev = 0;
/*
* display the CPUs' operating frequency, cache size, impl. field
* and mask revision.
*/
/* Do not display a failed CPU node */
continue;
/* FRU Name */
if (CPU_IMPL_IS_CMP(*impl)) {
"reg"));
continue;
}
/*
* The assumption is made that 2 cores will always be
* listed together in the device tree. If either core
* is "bad" then the FRU will not be listed.
*
* As display_cpus on Serengeti does actually process
* all cpu's per board a copy of the fru_name needs to
* be made as the following core may not be its
* sibling. If this is the case it is assumed that a
* sibling core has failed, so the fru should not be
* displayed.
*
* For the first instance of a core, fru_prev is
* expected to be empty. The current values are then
* stored and the next board->nodes is processed. If
* this is a sibling core, the ecache size it tallied
* and the previous value reset and processing
* continues.
*
* If the following core is not a sibling, the new
* values are stored and the next board->nodes is
* processed.
*/
continue;
} else {
sizeof (fru_prev)) == 0) {
/*
* Jaguar has a split E$, so the size
* for both cores must be added together
* to get the total size for the entire
* chip.
*
* Panther E$ (L3) is logically shared,
* so the total size is equal to the
* core size.
*/
}
ecache_size_prev = 0;
sizeof (fru_prev));
} else {
sizeof (fru_name));
continue;
}
}
}
/*
* If cpu is not configured, do not display it
*/
if (!(cpu_node_configured(cfg_fru_name))) {
continue;
}
/* CPU MID */
if (CPU_IMPL_IS_CMP(*impl)) {
mid_prev = -1;
} else
/* Running frequency */
/* Ecache size */
if (ecache_size == 0)
else
log_printf("%4.1f ",
0);
/* Implementation */
} else {
switch (*impl) {
case CHEETAH_IMPL:
break;
case CHEETAH_PLUS_IMPL:
break;
case JAGUAR_IMPL:
break;
case PANTHER_IMPL:
break;
default:
break;
}
}
/* CPU Mask */
} else {
if (IS_CHEETAH(*impl))
else
decoded_mask = *mask;
log_printf(" %d.%d ",
decoded_mask & 0xf, 0);
}
log_printf("\n", 0);
}
}
/*ARGSUSED3*/
void
struct system_kstat_data *kstats)
{
log_printf("\n", 0);
log_printf("=========================", 0);
log_printf("==================================", 0);
log_printf("\n", 0);
/*
* Get a list of failed parts (ie. devices with a status of
* 'fail') from the OBP device tree and display them.
*/
/* return unless -v option specified */
if (!flag) {
log_printf("\n", 0);
return;
}
/*
* display time of latest powerfail. Not all systems
* have this capability. For those that do not, this
* is just a no-op.
*/
/* Print the PROM revisions here */
}
/*
* local functions - functions that are only needed inside this library
*/
static void
{
char *value;
/* Print the header */
log_printf("\n", 0);
log_printf("=========================", 0);
log_printf("=======================================", 0);
log_printf("\n", 0);
log_printf("\n", 0);
/* Display Prom revision header */
log_printf("System PROM revisions:\n", 0);
log_printf("----------------------\n", 0);
/*
* Display OBP version info
*/
} else {
}
/*
* Display ASIC revisions
*/
log_printf("IO ASIC revisions:\n", 0);
log_printf("------------------\n", 0);
log_printf(" Port\n", 0);
log_printf("FRU Name Model ID Status", 0);
#ifdef DEBUG
log_printf(" Version Notes\n", 0);
#else
log_printf(" Version\n", 0);
#endif
/* ---------FRU Name--Model-----------Port-Status */
log_printf("----------- --------------- ---- ---------- "
#ifdef DEBUG
"------- "
#endif
"-------\n", 0);
/*
* Display SCHIZO version info
*/
/*
* Display sgsbbc version info
*/
}
/*
* This function displays Schizo and Xmits revision of boards
*/
static int
{
int *int_val;
int portid;
char *model;
int version;
int node_id;
#ifdef DEBUG
#endif
int pci_bus;
/*
* rv is used when mode is set to SG_SCHIZO_FAILED.
* We need to signal if a failure is found so that
*
* rv = 0 implies all other cases
*/
int rv = 0;
void *value;
/*
* search this board node for all Schizos
*/
/*
* get the reg property to determine
* whether we are looking at side A or B
*/
int_val = (int *)get_prop_val
int_val ++; /* second integer in array */
}
/* get portid */
int_val = (int *)get_prop_val
continue;
/*
* If this is a new portid and it is PCI bus B,
* we skip onto the PCI bus A. (PCI-A and PCI-B share
* the same portid)
*/
/* status */
status_b = (char *)get_prop_val
#ifdef DEBUG
#endif
continue; /* skip to the next schizo */
}
/*
* This must be side A of the same Schizo.
* Gather all its props and display them.
*/
#ifdef DEBUG
#endif
/* get the node-id */
/* model */
model = (char *)get_prop_val
/* version */
value = (int *)get_prop_val
if (value)
else
int_val = (int *)get_prop_val
else
version = -1;
/* status */
(pnode, "status"));
/*
* Display the data
*/
/* FRU Name */
if (mode == SG_SCHIZO_FAILED) {
if ((strcmp
(status_a, SG_DISABLED) == 0) &&
SG_DISABLED) == 0)) {
log_printf("\tFRU Type : %s\n ",
model, 0);
log_printf("\tLocation : %s\n",
fru_name, 0);
("\tPROM status: %s\n\n",
SG_DISABLED, 0);
rv = 1;
}
}
continue;
}
/*
* This section of code is executed when displaying
* non-failed schizo devices. If the mode is set to
* SG_SCHIZO_FAILED, then this section of code will
* not be executed
*/
else
continue;
/* model */
else
/* portid */
/* status */
/* version */
#ifdef DEBUG
#endif
log_printf("\n", 0);
}
}
return (rv);
}
static void
{
int *int_val;
int portid;
char *model;
char *status;
int revision;
int node_id;
#ifdef DEBUG
char *slot_name;
char *value;
#endif
/*
* search this board node for all sgsbbc's
*/
"SUNW,sgsbbc")) {
/*
* We need to go to this node's parent to
* get a portid to tell us what board it is on
*/
int_val = (int *)get_prop_val
continue;
/* get the node-id */
/* model */
model = (char *)get_prop_val
/* status */
(pnode, "status"));
/* revision */
int_val = (int *)get_prop_val
else
revision = -1;
#ifdef DEBUG
value = (char *)get_prop_val(
/* Skip the 4 byte bitmask */
} else {
}
portid);
#endif
/*
* Display the data
*/
/* FRU Name */
/* model */
else
/* portid */
/* status */
log_printf(" ok ", 0);
else
log_printf(" fail ", 0);
/* revision */
#ifdef DEBUG
#endif
log_printf("\n", 0);
}
}
}
/*ARGSUSED0*/
void
{
}
/*
* display_failed_parts
*
* Display the failed parts in the system. This function looks for
* the status property in all PROM nodes contained in the Sys_tree
* passed in.
*/
int
{
int system_failed = 0;
int bank_failed = 0;
print_flag = TRUE;
/*
* go through all of the OBP nodes looking for
* failed units.
*/
log_printf("\n", 0);
"Failed Field Replaceable Units (FRU) in "
"System:\n"), 0);
log_printf("=========================="
"====================\n", 0);
}
void *status;
/* sanity check of data retreived from PROM */
continue;
}
model = (char *)get_prop_val
/*
* Determine whether FRU is CPU module, Mem Controller,
* PCI card, schizo,xmits or sgsbbc.
*/
/*
* sgsbbc / bootbus-controller
*/
name, 0);
/*
* PCI Bridge if name = pci and it doesn't
* have a portid.
*/
log_printf("\tFRU type : ", 0);
log_printf("PCI Bridge Device\n", 0);
/*
* CPU or memory controller
*/
/*
* For cpu nodes that belong to a CMP, the
* portid is stored in the parent "cmp" node.
*/
if (portid == -1)
log_printf("\tFRU type : ", 0);
log_printf("Memory Controller on ", 0);
log_printf("UltraSPARC module\n", 0);
} else {
/*
* It should only be a PCI card if we get to
* here but lets check to be sure.
*/
int pci_card_found = 0;
/*
* Is our parent a schizo or xmits
*/
parents_model = (char *)get_prop_val
if ((parents_model != NULL) &&
}
/*
* Is our grandparent a schizo xmits
*/
grandparents_model = (char *)get_prop_val
if ((grandparents_model != NULL) &&
"SUNW,schizo") ||
"SUNW,xmits"))) {
}
if (pci_card_found) {
board);
portid % 2);
log_printf("\tFRU type :", 0);
log_printf(" PCI Card\n", 0);
log_printf("\tLocation : %s\n",
fru_name, 0);
}
}
}
}
return (1);
else
return (0);
}
/*
* This routine displays the memory configuration for all boards in the
* system.
*/
/*ARGSUSED0*/
void
{
log_printf("========================= Memory Configuration"
" ===============================\n", 0);
log_printf("\n Logical Logical Logical ", 0);
log_printf("\n Port Bank Bank Bank "
"DIMM Interleave Interleave", 0);
log_printf("\nFRU Name ID Num Size Status "
"Size Factor Segment", 0);
log_printf("\n------------- ---- ---- ------ ----------- "
"------ ---------- ----------", 0);
if (get_us3_mem_regs(bnode)) {
"\nFailed to get memory information.\n"), 0);
return;
}
}
/* Display what we have found */
}
/*
* This function provides Serengeti's formatting of the memory config
* information that get_us3_mem_regs() and display_us3_banks() code has
* gathered. It overrides the generic print_us3_memory_line() code
* which prints an error message.
*/
void
{
log_printf("\n%-13s %2d %2d %4lldMB %11-s %4lldMB "
" %2d-way %d",
}
void
{
log_printf("\tFRU type : ", 0);
log_printf("Physical Memory Bank\n", 0);
log_printf("\tLocation : %s (Logical Bank %2d)\n",
}
/*
* Find the requested board struct in the system device tree.
*
* This function overrides the functionality of the generic find_board()
* function in libprtdiag, but since we need to pass another parameter,
* we cannot simply overlay the symbol table.
*/
static Board_node *
{
}
return (bnode);
}
/*
* Add a board to the system list in order (sorted by NodeID then board#).
* Initialize all pointer fields to NULL.
*/
static Board_node *
{
perror("malloc");
exit(1);
}
} else {
}
return (bnode);
}
/*
* We call do_devinfo() in order to use the libdevinfo device tree
* instead of OBP's device tree.
*/
int
{
}
/*
* return the property value for the Prop passed in depending on
*/
void *
{
return (NULL);
/* Check which tree is being used. */
if (tree == DEVINFO_TREE)
else {
else
}
}
/*
* Search a Prom node and retrieve the property with the correct
*/
Prop *
{
return (NULL);
return (NULL);
/* Check which tree is being used. */
if (tree == DEVINFO_TREE) {
} else {
}
return (prop);
}
/*
* This function searches through the properties of the node passed in
* and returns a pointer to the value of the name property
*/
char *
{
return (NULL);
/* Check which tree is being used. */
if (tree == DEVINFO_TREE) {
} else {
}
}
return (NULL);
}
/*
* This function searches through the properties of the node passed in
* and returns a pointer to the value of the device_type property
*/
char *
{
return (NULL);
/* Check which tree is being used. */
if (tree == DEVINFO_TREE) {
== 0)
} else {
== 0)
}
}
return (NULL);
}
/*
* Take a snapshot of the OBP device tree and walk this snapshot
* to find all failed HW (ie. devices with a status property of
* 'fail'). Call display_failed_parts() to display the failed HW.
*/
void
get_failed_parts(void)
{
int system_failed = 0;
/* set the the system tree fields */
obp_sys_tree.board_cnt = 0;
"open failed"));
return;
}
if ((is_openprom() == 0) || (next(0) == 0)) {
"error encountered."));
return;
}
if (!system_failed) {
"No Hardware failures found in System\n"), 0);
}
promclose();
}
/*
* get_slot_name figures out the slot no. for the card. In the case of
* XMITS slots 2 & 3 and slots 6 & 7 are reversed in slot_name by OBP
* so we need to cater for this to correctly identify the slot no.
*/
static void
{
switch (tmp_ptr[0]) {
case '2':
break;
case '3':
break;
case '6':
break;
case '7':
break;
default:
}
} else
} else
}