/*
* 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 1999 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/ddi_impldefs.h>
#include <sys/machsystm.h>
/*
* Defines for data structures used only in this module. They will
* not be exported to external modules.
*/
/*
* Define the hardware structure of JTAG
*/
/* JTAG status flags */
/* JTAG commands */
/*
* Definitions of data types.
*
*/
/*
* Most routines in this interface return a negative value when
* an error occurs. In the normal case, the routines return a non-negative
* value, which may be of interest to the caller. The following enumeration
* provides the meaning of each error return code.
*/
/*
* When calling verify_jtag_chip, you must pass PRINT_ERR if you
* want the cmn_err call to occur. This is because sometimes
* when we verify rings, (checking for NPB's) we do not want to
* print error messages.
*/
/*
* You must pass in the proper chip masks when calling
* config board()
*/
/* scan ring numbers */
#define RING0 0
/*
* Scan ring 0 lengths. Boards are typed by their scan ring length. This
* is inherently flawed if a new board type has the same number of
* components as one of the original boards.
*
* The inherently flawed scenario now exists with the introduction
*/
/*
* Component IDs of various SRAM chips. The only way to distinguish between
* 1M, 2M, and 4M Ecache is via the component IDs of the SRAMs.
*/
typedef enum {
} jtag_error;
/* Internal macros */
/* TAP register access macros */
/* NOTE the only status is the busy bit (8) */
/* read the jtag data bits */
while ((*(reg) & JTAG_BUSY_BIT) != 0) \
if ((--timeout) < 0) \
return (TAP_TIMEOUT)
/* Error-checking macros to simplify the coding */
if (status < 0) \
return (status)
if (status < 0) \
return (status)
if (status < 0) \
return (status)
if (status < 0) \
return (status)
/*
* A jtag_log_comp describes a component as seen by JTAG.
*
* Since there are multiple versions & revision for a single
* component, this can be a bit complicated...
*
* The implementation assumes that all components which can be used
* interchangeably have the exact same programming model regarding
* JTAG programming. Then, interchangeable components differ only by
* their component IDs. The field id points to a NULL-terminated list
* of component IDs. Allowable component IDs may differ only in the rev
* number, which must be higher than or equal to the one in the list.
*
* The init_pdesc field points to a byte string which describes how to
* initialize the component. The structure of this byte string is not
* exported (see the implementation of jtag_init_chip).
*
* The fmt_desc field points to a byte string which describes how to
* convert the scan-out format to the more usual DCSR format. The
* structure of this string is not exported (see the implementation
* of jtag_scanout_chip).
*/
typedef struct {
/* A jtag_phys_comp describes a component position inside a ring */
typedef struct {
/* Board ring description */
typedef struct {
int size;
/*
* Initialization options
*
* These data types describe the options for each type of component
* internally to the jtag_init_*_ring routines. They can all be
* recast into arrays of unsigned integers.
*
* Note that these types DEPEND on the *_init_pdesc structures, which
* use indices to the components of the *_options types. As a result,
* the data structure & the type must be modified simultaneously,
* although this dependency is not immediately visible. This is ugly,
* but it makes the initialization routines much more readable.
*/
typedef struct {
} ac_options;
struct ac_regs {
unsigned int bcsr;
unsigned int brscr;
unsigned int esr_hi;
unsigned int esr_lo;
unsigned int emr_hi;
unsigned int emr_lo;
unsigned int ccr;
unsigned int cntr_hi;
unsigned int cntr_lo;
};
typedef struct {
} dc_options;
typedef struct {
} fhc_options;
struct fhc_regs {
};
/* Structure to capture the scan data from the bct8244's. */
struct bct_fields {
};
/* Collective type for *_options * */
/*
* The following definitions are the action flags used in the byte
* string which is used to describe component initialization. The
* only piece of code which understands those flags is jtag_init_chip.
*
* Initializing a component consists of scanning successive values
* into the component. The data for each pass is obtained by applying
* successive patches to a reference pattern. The patch descriptors
* are a byte string which form a succession of operations. The first
* byte of an operation is a set of flags defining the action:
*/
/*
* When JTIN_INSERT is specified, the flag byte is followed by
* two bytes indicating the lsb and msb of the field to be updated, and
* the JTIN_INDEX part of the flags indicate which value should be
* inserted: if JTIN_INDEX is zero, the value to insert is the next
* byte in the aray, extended to a 32-bit word; if JTIN_INDEX is
* non-zero, the value to insert is at word offset index in the patch
* array passed to jtag_init_chip.
*/
/*
* The fmt_desc field points to a reformat table which converts the
* scan-out format to the standard DSCR-style format. The format descriptor
* is a byte string, with special bytes indicating functional operations
* as indicated by bit fields in the following table:
*/
/*
* Function Declarations
*/
static void jtag_error_print(int, jtag_error);
/*
* Bit-field manipulations
*/
/*
* Test-access port interface
*/
static int tap_shift_single(volatile u_int *, int, int);
/*
* Ring-level interface
*/
/*
* Component-level interface
*/
u_int *);
/*
* Data tables.
*
* The JTAG implementation is data table driven. These tables describe
* the chip, ring, and board components.
*/
/*
* Data structures describing the scannable components
*/
/* Constants defining the IR lengths for each of the chips */
/* Standard instructions */
/* ASIC Jag IDs */
0x0002502f,
0
};
0x0002602f,
0
};
0x1241906d,
0
};
0x0001d02f,
0
};
0X0E9A103B,
0
};
0x0001d02f,
0
};
0x0ef0703b,
0
};
0x01792045,
0
};
0x10f9e07d,
0
};
0x10f9f07d,
0
};
0x10fa007d,
0
};
0x3195401d,
0
};
0x11791022,
0
};
/*
* NOTE the following chips are ignored for the most part by the POST JTAG
* If if is later determined that scan data may be of interest then we need
* to fill in the blanks below.
*/
};
};
};
};
};
};
};
};
};
};
};
};
/* The main ASCIS of interest are the AC, DC and FHC */
/*
* The initialization of DC is as follows:
*
* Do NOT change the following data structure without checking
* _options in jtag_private.h, which depends on it.
*/
};
};
/*
* The initialization of AC is as follows:
*
* Do NOT change the following data structure without checking
* _options in jtag_private.h, which depends on it.
*/
};
};
/*
*/
/*
* The following structure has three variable elements, as noted
* by the 1,2 and 3 digits or'ed in with the JTIN_INSERT flags.
* The number nad position of these elements must correspond with
* the fhc_ structure apssed into fhc_chip_init.
*/
};
};
};
/* A jtag_log_comp describes a component as seen by JTAG. */
IR_LEN, 163,
};
0,
IR_LEN, 18,
0x2, 0x2, 0x2,
};
IR_LEN, 5,
};
IR_LEN, 42,
};
0,
EC_LEN, 42,
};
FFB_LEN, 42,
0xb000, 0xb000, 0xb000,
};
IR_LEN, 42,
};
THREED_LEN, 42,
};
BT498_LEN, 42,
};
SIO_LEN, 42,
0xb000, 0xb000, 0xb000,
};
HM_LEN, 42,
0xe, 0xe, 0xe,
};
0,
NDP_LEN, 42,
2, 2, 2,
};
0,
SOC_LEN, 42,
4, 4, 4,
};
0,
SOCPLUS_LEN, 42,
0xfe, 4, 4,
};
IR_LEN, 42,
0xfe, 0xfe, 0xfe,
};
IR_LEN, 42,
0xfe, 0xfe, 0xfe,
};
PSYO_LEN, 42,
0xb000, 0xb000, 0xb000,
};
CHEO_LEN, 42,
0xb000, 0xb000, 0xb000,
};
/*
* Ring descriptions for sunfire boards
*
* For each ring, there is a generic type descriptor which describes
* the order of chips in the static data structure describing the
* ring.
*
* Rings are described by an array of physical components, and are
* recast into the specific ring type by routines which use them, see
* for example the jtag_init_*_ring routines.
*
* Although the ring data structures are declared as jtag_phys_comp[],
* the components must be ordered as required by the corresponding
* *_*_ring type (in jtag_private.h).
*/
/*
* Data structures describing the system board rings
*/
};
};
};
};
};
};
};
};
};
};
};
};
};
};
};
};
};
};
/*
* Ring descriptors for single and double buffered FFB boards.
* Note - Only the FBC has a component ID register. None of the
* other chips on the FFB board has one, so do not check them.
*/
};
};
};
};
/*
* Board descriptions
*/
&cpu_sysbd_ring, /* Ring 0 */
&cpu_mod_ring, /* Ring 1 */
&cpu_mod_ring, /* Ring 2 */
};
&io1_sysbd_ring, /* Ring 0 */
};
&io1plus_sysbd_ring, /* Ring 0 */
};
&io2_sysbd_ring, /* Ring 0 */
};
&io2plus_sysbd_ring, /* Ring 0 */
};
&io3_sysbd_ring, /* Ring 0 */
};
&dsk_sysbd_ring, /* Ring 0 */
};
/*
* Function Definitions:
* ---------------------
*/
/* For sunfire there will be a ring descriptor for each type of board */
static jtag_ring_desc *
{
switch (type) {
case CPU_BOARD:
case IO_2SBUS_BOARD:
case IO_2SBUS_SOCPLUS_BOARD:
case IO_SBUS_FFB_BOARD:
case IO_PCI_BOARD:
case DISK_BOARD:
default:
return (NULL);
}
}
static void
{
/*
* the FHC Board Status Register indicates whether
* the board 100 Mhz capable or not.
*/
}
/*
* Returns (positive) board type if something detected, including
* UNKNOWN_BOARD.
* Returns -1 if nothing there.
*/
enum board_type
{
int len;
int ring;
int result;
int board;
int status;
/*
* Select Board Ring 0 to scan. This contains the AC, FHC,
* and DC ASICs
*/
/*
* Ring number is JTAG Board (7:4) and ring number (3:0)
*/
}
switch (len) {
case CPU_TYPE_LEN:
break;
case IO_TYPE1_LEN:
case RING_BROKEN:
break;
case IO_TYPE4_LEN:
break;
default:
break;
}
break;
case IO_TYPE2_LEN:
case RING_BROKEN:
break;
case IO_TYPE5_LEN:
break;
default:
break;
}
break;
case PCI_TYPE_LEN:
case RING_BROKEN:
break;
case PCI_TYPEA_LEN:
break;
case PCI_TYPEB_LEN:
default:
break;
}
break;
case DSK_TYPE_LEN:
result = DISK_BOARD;
break;
case RING_BROKEN:
result = -1;
break;
default:
break;
}
return (result);
}
#ifndef RFE_4174486
/*
* Until the RFE is fully investigated the likelyhood is that the
* CPU frequency may be incorrectly displayed. Coupled with the lack of
* Ecache size information and no information at all unless the
* CPU board is physically plugged in, the default is not to get any
* CPU information.
* This patchable flag is provided so that more testing can be done
* without re-compilation.
*/
static int jtag_cpu_scan_enable = 0;
#endif /* RFE_4174486 */
int
{
int status;
int ring;
int len;
int i;
/* fill in the board info structure */
return (status);
}
return (JTAG_FAIL);
}
/* scan in the generic data common to all board types. */
/* get the AC component ID */
}
/* get the FHC component ID */
}
/* Now scan the board type dependent components */
case CPU_BOARD:
/*
* first determine the cache size of each module, then
* use that ring descriptor.
*/
#ifndef RFE_4174486
if (!jtag_cpu_scan_enable)
continue;
#endif /* RFE_4174486 */
continue;
}
switch (len) {
case CPU_0_5_LEN:
rd = &cpu_mod_ring;
break;
case CPU_1_0_LEN:
rd = &cpu_mod_1m_ring;
break;
case RING_BROKEN:
default:
break;
}
if (!cpu->cpu_detected)
continue;
cpu->cpu_compid =
}
/*
* Do not get the component ID from the
* first E$ chip. This is the tag chip
* and does not help determine cache size.
*/
}
cpu->sdb0_compid =
}
cpu->sdb1_compid =
}
}
#ifdef RFE_4174486
/* Work out Ecache size. */
switch (len) {
case CPU_0_5_LEN:
break;
case CPU_1_0_LEN:
/* default cache size for 9 SRAM chips */
break;
default:
break;
}
#endif /* RFE_4174486 */
}
break;
case IO_2SBUS_BOARD:
}
}
}
}
break;
case IO_2SBUS_SOCPLUS_BOARD:
}
}
}
}
break;
case IO_SBUS_FFB_BOARD:
}
}
}
/* Now scan for an FFB board */
len = RING_BROKEN;
} else {
}
switch (len) {
case FFB_SNG_LEN:
rd = &ffb_sngl_ring;
break;
case FFB_DBL_LEN:
rd = &ffb_dbl_ring;
break;
case RING_BROKEN:
break;
default:
break;
}
/* Now scan out the FBC component ID */
}
}
break;
}
}
}
/* Now scan for an FFB board */
len = RING_BROKEN;
} else {
}
switch (len) {
case FFB_SNG_LEN:
rd = &ffb_sngl_ring;
break;
case FFB_DBL_LEN:
rd = &ffb_dbl_ring;
break;
case RING_BROKEN:
break;
default:
break;
}
/* Now scan out the FBC component ID */
}
}
break;
case IO_PCI_BOARD:
}
}
}
break;
case DISK_BOARD:
/*
* Scan the BCT8244 to get the disk drive info out of
* the chip.
*/
return (-1);
}
} else {
}
} else {
}
break;
default:
break;
}
return (JTAG_OK);
}
static jtag_phys_comp *
{
int i;
int found = 0;
return (rc);
} else {
found++;
}
}
}
return (NULL);
}
/*
* Function jtag_error() :
*
* This function centrailizes the use of the JTAG error strings.
* It should be called with the JTAG error code anytime the programmer
* wants to print the type of JTAG error encountered. Just call with the
* error code returned by the JTAG function. If no error occurred, nothing
* is printed.
*/
static void
{
switch (code) {
case JTAG_OK :
break;
case TAP_TIMEOUT :
break;
case BAD_ARGS :
"%s : routine reports bad args: Board %d, %s Ring\n",
break;
case BAD_CID :
"%s : Bad component ID detected: Board %d, %s Ring\n",
break;
case RING_BROKEN :
break;
case INIT_MISMATCH:
"%s : State after init not expected: Board %d, "
break;
case LENGTH_MISMATCH :
"%s : Scan Chain Length mismatch: Board %d,"
" %s Ring\n",
break;
} /* end of switch on code */
} /* end of jtag_error_print() */
static int
{
u_char b[4];
int status;
b, 32, b);
/* Reorder the bytes of the ID read out */
if (status < 0) {
return (0);
} else {
return (id);
}
}
/*
* Bit-manipulation routines
*/
/*
* jtag_bf_extract()
*
* This routine extracts bit strings from JTAG data scanout strings. This
* routine is used to decode data scanned out of chips via JTAG.
*/
static u_int
{
ASSERT(s);
/*
* lsb and msb are assumed to be within string,
* and to span 32 bits at most
*/
}
return (result);
}
/*
* jtag_bf_insert()
*
* This routine is used to build bit strings for scanning into the
* shadow chains of ASICs.
*/
static void
{
ASSERT(s);
/*
* lsb and msb are assumed to be within string,
* and to span 32 bits at most
*/
}
}
/*
*
*/
static void
{
while (nbytes-- != 0) {
*s++ = 0;
}
}
/*
* Return 0 if equal, != 0 else
*/
static int
{
int mask;
return (-1);
}
return (-1);
}
}
return (0);
}
/*
* Generic chip-level top routines
*/
static int
{
int status;
if (status < 0) {
return (status);
}
/* Zero out the scan-in area */
for (;;) {
if ((flags & JTIN_INSERT) != 0) {
if ((flags & JTIN_INDEX) != 0) {
} else {
}
}
if ((flags & JTIN_UPDATE) != 0) {
scan_out);
if (status < 0) {
return (status);
}
return (status);
}
}
if ((flags & JTIN_COMPARE) != 0) {
return (INIT_MISMATCH);
}
break;
}
}
return (JTAG_OK); /* all is OK... */
}
/*
* Dump the info from a chip.
* Return the number of bytes used, or <0 if failed
*/
static int
{
int status;
u_char *p;
int bytes_used = 0;
return (status);
}
if (p == NULL) {
return (bytes_used);
}
if (status < 0) {
return (status);
}
return (status);
}
for (value = 0; ; ) {
if ((cmd & JTSO_XTRACT) != 0) {
lsb = *p++;
msb = *p++;
(cmd & JTSO_SHIFT);
}
bytes_used += 4;
value = 0;
}
break;
}
}
return (bytes_used);
}
/*
* Set the AC into hotplug mode upon insertion
*/
static int
{
int status;
if (brdtype == UNKNOWN_BOARD)
return (rc);
/* Get a good AC BCSR value from the board we are running on. */
} else if (brdtype == IO_2SBUS_BOARD) {
} else if (brdtype == IO_2SBUS_SOCPLUS_BOARD) {
} else if (brdtype == IO_SBUS_FFB_BOARD) {
} else if (brdtype == IO_SBUS_FFB_SOCPLUS_BOARD) {
} else if (brdtype == IO_PCI_BOARD) {
} else {
}
}
return (rc);
}
/*
* Each board has an FHC asic.
*/
int
{
int status;
int ring;
if (type == UNKNOWN_BOARD) {
}
if (!intr)
if (intr) {
/*
* by not setting NOT_BRD_PRESENT we can simulate a board
* insertion
*/
}
} else if (type == IO_2SBUS_BOARD) {
} else if (type == IO_2SBUS_SOCPLUS_BOARD) {
} else if (type == IO_SBUS_FFB_BOARD) {
} else if (type == IO_SBUS_FFB_SOCPLUS_BOARD) {
} else if (type == IO_PCI_BOARD) {
} else if (type == UNKNOWN_BOARD) {
} else {
fhc_bd_type(board));
}
}
/* Reformat the FHC shadow chain scan data */
scan_out);
return (rc);
}
/*
* This function performs the fhc initialization for a disk board. The
* hotplug variable tells the function whether to put the LED into low
* power mode or not.
*/
int
{
int status;
int ring;
return (-1);
}
/* Reformat the FHC shadow chain scan data */
scan_out);
return (0);
}
/*
* NOTES:
* 1. Scan data streams are little-endian sequences of bytes: byte 0
* will provide the 8 lsb of the scan chain, and so on. If the last
* byte is not full (count not a multiple of 8), the least significant
* bits are used.
* 2. All procedures assume that the JTAG control register
* is non-busy on entry, and return with the control register
* non-busy. It is a good idea to call tap_wait as part of the JTAG
* sanity check sequence to verify there is no obvious malfunction.
*/
/*
* Non-data TAP commands
*/
/*
* Wait for the TAP to be idle.
* Return <0 if error, >=0 if OK.
*/
int
{
return (JTAG_OK);
}
/*
* Send a TAP command, wait for completion.
* Return <0 if error, >=0 if OK.
*/
static int
{
return (JTAG_OK);
}
/*
* Data TAP commands
*/
/*
* Shift 1 to 16 bits into the component.
* Return <0 if error, the shifted out bits (always >=0) if OK.
*/
int
{
/* Return <0 if error, >0 (16-bit data) if OK */
}
/*
* Shift the required number of bits from in into the component,
* retrieve the bits shifted out.
* Return <0 if error, >=0 if OK.
*/
int
int nbits,
{
/*
* The loop is done a byte at a time to avoid stepping out
* of the caller's buffer
*/
data_out++;
}
}
return (JTAG_OK);
}
/*
* Shift the required number of bits of the specified
* value into the selected register. Note that this routine makes
* sense only for value = 0 and value = -1.
* Return <0 if error, >=0 if OK.
*/
static int
{
/*
* The loop is done a half-word at a time
*/
}
return (JTAG_OK);
}
/*
* Ring-level commands
*/
/*
* Select the required ring. Reset it if required (reset != 0).
* Return <0 if error, >=0 if OK.
*/
static int
{
int status;
if (status < 0) {
return (status);
}
/* Translate a Physical Board number to a JTAG board number */
(ring & 0xF);
if (status < 0) {
return (status);
}
if (reset != 0) {
}
return (status);
}
/*
* Shift the specified instruction into the component, then
* shift the required data in & retrieve the data out.
* Return <0 if error, >=0 if OK.
*/
static int
int nbits,
{
int status;
return (status);
}
/*
* jtag_rescan_IR_DR()
*
* This function is used in order to rescan the DC ASICs when taking
* them out of the frozen state. This is necessary because of a problem
* when taking DCs out of the frozen state. Sometimes the operation must
* be retryed.
*
* TODO - Eliminate the *in input parameter if able to.
*/
/* ARGSUSED */
static int
int nbits,
{
int status, i;
for (i = 0; i < 32; i++)
tmp[i] = 0;
/* scan the chip out */
/* re scan the chip */
return (status);
}
/*
* Return the number of components of the current ring, or <0 if failed
*/
static int
{
/*
* Reset the ring & check that there is a component
* This is based on the fact that TAP reset forces the IDCODE,
* or BYPASS (with 0 preloaded) if there is no ID
*/
if (status < 0) {
status);
return (status);
}
if (status == 0xFF) {
return (RING_BROKEN); /* no CID detected */
}
/*
* Put all components in BYPASS. This assumes the chain has
* at most 32 components, and that each IR is at most 16-bits.
* Note that the algorithm depends on the bypass FF to be cleared
* on a tap reset!
*/
if (status != 0) {
break;
}
}
/* more than 32 components ??? */
}
/*
* Return the total number of instruction register bits in the
* current ring, or < 0 if failed.
*/
int
{
/*
* Reset the ring & check that there is a component
* This is based on the fact that TAP reset forces the IDCODE,
* or BYPASS (with 0 preloaded) if there is no ID
*/
if (status < 0) {
return (status);
}
/*
* Reset, Select IR, Shift in all 1's assuming the chain has
* at most 32 components, and that each IR is at most 16-bits.
* Then shift in 0's and count until a 0 comes out.
* And cleanup by flushing with all 1's before reset or idle
* --- FATAL's if you don't as you go through update-ir state
*/
/* 1 fill, look for 0 */
if (status == 0)
break;
}
/* bypass should be safe */
/* more than 32*16 ir bits ??? */
}
/*
* Format the jtag shadow scan data from scan_out bit string and store
* in the array on u_ints. The datap represents the registers from
* the chip under scan.
* XXX - How to represent 64 bit registers here?
*/
static void
{
for (value = 0; ; ) {
if ((cmd & JTSO_XTRACT) != 0) {
(cmd & JTSO_SHIFT);
}
value = 0;
}
break;
}
}
}