jtag.c revision 29949e866e40b95795203f3ee46f44a197c946e4
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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/types.h>
#include <sys/param.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/ddi_impldefs.h>
#include <sys/obpdefs.h>
#include <sys/cmn_err.h>
#include <sys/errno.h>
#include <sys/debug.h>
#include <sys/fhc.h>
#include <sys/jtag.h>
#include <sys/ac.h>
#include <sys/machsystm.h>
#include <sys/cpu.h>
#include <sys/cpuvar.h>
/*
* Defines for data structures used only in this module. They will
* not be exported to external modules.
*/
/*
* Define the hardware structure of JTAG
*/
#define JTAG_CSR_BASE ((jtag_csr *)0xF0300000)
#define JTAG_CR 0x08000f0
#define JTAG_CMD 0x0800100
/* JTAG status flags */
#define JTAG_BUSY_BIT 0x100
/* JTAG commands */
#define JTAG_SEL_RING 0x6000
#define JTAG_SEL_DR 0x5050
#define JTAG_SEL_IR 0x5068
#define JTAG_SHIFT 0x00A0
#define JTAG_RUNIDLE 0x50C0
#define JTAG_IR_TO_DR 0x50E8
#define JTAG_DR_TO_IR 0x50F4
#define JTAG_TAP_RESET 0x50FF
/*
* 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.
*/
#define PRINT_JTAG_ERR 5
/*
* You must pass in the proper chip masks when calling
* config board()
*/
#define AC_INIT 1
#define DCU1500_INIT 2
#define DCU1600_INIT 2
#define DCU1700_INIT 2
#define DCU1800_INIT 2
#define DCU1900_INIT 2
#define DCU2000_INIT 2
#define DCU2100_INIT 2
#define DCU2200_INIT 2
#define FHC_INIT 4
#define SYSIO_INIT 8
/* scan ring numbers */
#define RING0 0
#define RING1 1
#define RING2 2
/*
* 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
* of the soc+ versions of the 2-SBus and UPA/SBus boards. Argh...
*/
#define CPU_TYPE_LEN 12 /* CPU board ring length */
#define IO_TYPE1_LEN 15 /* 2 sysio 1 HM */
#define IO_TYPE2_LEN 14 /* 1 sysio 1 ffb */
#define PCI_TYPE_LEN 16 /* PCI board ring length */
#define PCI_TYPEA_LEN 110 /* PCI ISP off ring */
#define PCI_TYPEB_LEN 104 /* PCI ISP in ring */
#define DSK_TYPE_LEN 2 /* Disk board ring length */
#define IO_TYPE4_LEN 126 /* 2 sysio soc+ */
#define IO_TYPE5_LEN 110 /* 1 sysio 1 ffb soc+ */
#define CPU_0_5_LEN 8 /* 0.5 Meg Module ring length */
#define CPU_1_0_LEN 12 /* 1 Meg and 2 Meg ring length */
#define FFB_SNG_LEN 6 /* Single bufferef FFB */
#define FFB_DBL_LEN 18 /* Double buffered FFB */
/*
* 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.
*/
#define SRAM_256K 0x00000000
#define SRAM_128K 0x000090E3
#define SRAM_64K_1 0x000000E3
#define SRAM_64K_2 0x01901149
typedef enum {
JTAG_OK = 0, /* no error */
JTAG_FAIL = -1, /* generic JTAG failure */
TAP_TIMEOUT = -1, /* JTAG TAP state machine not responding */
BAD_ARGS = -2, /* incorrect arguments passed by caller */
BAD_CID = -3, /* JTAG component ID does not match */
RING_BROKEN = -4, /* JTAG ring continuity test failed */
INIT_MISMATCH = -5, /* State after initialization not expected */
LENGTH_MISMATCH = -6 /* Ring length does not match expected */
} jtag_error;
typedef u_short jtag_instruction;
typedef u_char jtag_ring; /* format is bbbb rrrr in binary */
/* Internal macros */
static int tap_issue_cmd(volatile u_int *, u_int);
/* TAP register access macros */
/* NOTE the only status is the busy bit (8) */
/* read the jtag data bits */
#define jtag_data(reg, nbits) (*(reg) >> (32 - (nbits)))
#define JTAG_TIMEOUT 0x10000
#define TAP_DECLARE int timeout;
#define TAP_WAIT(reg) timeout = JTAG_TIMEOUT; \
while ((*(reg) & JTAG_BUSY_BIT) != 0) \
if ((--timeout) < 0) \
return (TAP_TIMEOUT)
#define TAP_SHIFT(reg, data, nbits) \
*(reg) = ((data<<16) | ((nbits-1)<<12) | JTAG_SHIFT); \
TAP_WAIT(reg)
/* Error-checking macros to simplify the coding */
#define TAP_ISSUE_CMD(reg, cmd, status) \
status = tap_issue_cmd(reg, cmd); \
if (status < 0) \
return (status)
#define TAP_SHIFT_CONSTANT(reg, val, nbits, status) \
status = tap_shift_constant(reg, val, nbits); \
if (status < 0) \
return (status)
#define TAP_SHIFT_SINGLE(reg, val, nbits, status) \
status = tap_shift_single(reg, val, nbits); \
if (status < 0) \
return (status)
#define TAP_SHIFT_MULTIPLE(reg, in, nbits, out, status) \
status = tap_shift_multiple(reg, in, nbits, out); \
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 {
u_int *id; /* Pointer to component IDs, 0 if no CID */
u_char ir_len; /* number of bits in instruction register */
u_char dr_len; /* number of bits in DR for init/dump */
jtag_instruction id_code; /* instruction to read component ID */
jtag_instruction init_code; /* instruction to write parameters */
jtag_instruction dump_code; /* instruction to read parameters */
u_char *init_pdesc; /* initialization patch descriptors */
u_char *fmt_desc; /* reformat descriptor */
} jtag_log_comp;
/* A jtag_phys_comp describes a component position inside a ring */
typedef struct {
jtag_log_comp *chip; /* pointer to chip descriptor */
short ir_after; /* number of IR bits after chip in ring */
short ir_before; /* number of IR bits before chip in ring */
short by_after; /* number of bypass bits after chip in ring */
short by_before; /* number of bypass bits before chip in ring */
} jtag_phys_comp;
/* Board ring description */
typedef struct {
int size;
jtag_phys_comp *components;
} jtag_ring_desc;
/*
* 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 {
u_int frozen;
u_int reset_a;
u_int reset_b;
u_int board_id;
u_int mask_hwerr;
u_int arb_fast;
u_int node_id;
u_int pcr_hi;
u_int pcr_lo;
u_int pcc_ctl1;
u_int pcc_ctl0;
u_int pcc_tctrl;
} 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 {
u_int frozen;
u_int mask_pe;
u_int mask_oe;
} dc_options;
typedef struct {
u_int csr_hi; /* CSR 20:18 */
u_int csr_mid; /* CSR 16:8 */
u_int csr_midlo; /* CSR 6:4 */
} fhc_options;
struct fhc_regs {
u_int por;
u_int csr;
u_int rcsr;
u_int bsr;
};
/* Structure to capture the scan data from the bct8244's. */
struct bct_fields {
u_int disk1_pres;
u_int disk0_pres;
u_int disk1_id;
u_int disk0_id;
};
/* Collective type for *_options * */
typedef u_int *jtag_opt;
/*
* 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:
*/
#define JTIN_INDEX 0x0F
#define JTIN_INSERT 0x10
#define JTIN_UPDATE 0x20
#define JTIN_COMPARE 0x40
#define JTIN_END 0x80
/*
* 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:
*/
#define JTSO_END 0x80 /* end of table */
#define JTSO_XTRACT 0x40 /* extract & merge [lsb, msb] */
#define JTSO_ST 0x20 /* store & increment */
#define JTSO_SHIFT 0x1F /* shift count for extract & merge */
/*
* Function Declarations
*/
static void jtag_error_print(int, jtag_error);
static int jtag_get_comp_id(volatile u_int *, jtag_phys_comp *);
/*
* Bit-field manipulations
*/
static u_int jtag_bf_extract(u_char *s, int lsb, int msb);
static void jtag_bf_insert(u_char *s, int lsb, int msb, int value);
static void jtag_bf_zero(u_char *s, int nbits);
static int jtag_bf_cmp(u_char *s1, u_char *s2, int nbits);
/*
* Test-access port interface
*/
static int tap_wait(volatile u_int *);
static int tap_shift_single(volatile u_int *, int, int);
static int tap_shift_multiple(volatile u_int *, u_char *, int, u_char *);
/*
* Ring-level interface
*/
static int select_ring(volatile u_int *, jtag_ring, int);
static int jtag_rescan_IR_DR(volatile u_int *, jtag_phys_comp *,
jtag_instruction, u_char *, int, u_char *);
static int jtag_single_IR_DR(volatile u_int *, jtag_phys_comp *,
jtag_instruction, u_char *, int, u_char *);
static int jtag_ring_length(volatile u_int *, jtag_ring);
static int jtag_ring_ir_length(volatile u_int *, jtag_ring);
/*
* Component-level interface
*/
static int jtag_scanout_chip(volatile u_int *, jtag_ring, jtag_phys_comp *,
u_int *);
static int jtag_init_chip(volatile u_int *, jtag_ring, jtag_phys_comp *,
const u_int *, u_char *);
static jtag_phys_comp *find_chip(jtag_ring_desc *, jtag_log_comp *, int);
static void format_chip_data(u_char *, u_int *, u_char *);
static int jtag_init_ac(volatile u_int *, int, enum board_type);
/*
* Data tables.
*
* The JTAG implementation is data table driven. These tables describe
* the chip, ring, and board components.
*/
/*
* Data structures describing the scannable components
*/
static char jtag_err[] = "JTAG ERROR";
/* Constants defining the IR lengths for each of the chips */
#define IR_LEN 8 /* all sunfire asics, spitfire, and sdb are 8 bits */
#define HM_LEN 4 /* happy meal is 4 bits */
#define NDP_LEN 2 /* ndp83840 is 2 bits */
#define SOC_LEN 4 /* SOC is 4 bits */
#define SOCPLUS_LEN 8 /* SOC+ is 8 bits */
#define SIO_LEN 16 /* sysio asic is 16 bits */
#define PSYO_LEN 4 /* psycho asic is 4 bits */
#define CHEO_LEN 4 /* cheerio asic is 4 bits */
#define EC_LEN 3 /* ecache tag rams is 3 bits each */
#define FFB_LEN 16 /* ffb module is 16 bits */
#define THREED_LEN 4 /* IR length for three D rams */
#define BT498_LEN 4 /* IR length for bt 498 chip (ramdac) */
/* Standard instructions */
#define IDCODE 0xFFFE
#define INITCODE 0xbe
#define DUMPCODE 0xbe
#define CID_TO_REV(cid) ((cid) >> 28)
/* ASIC Jag IDs */
static u_int cid_sf[] = {
0x0002502f,
0
};
static u_int cid_sdb[] = {
0x0002602f,
0
};
static u_int cid_fbc[] = {
0x1241906d,
0
};
static u_int cid_lvt[] = {
0x0001d02f,
0
};
static u_int cid_3dram[] = {
0X0E9A103B,
0
};
static u_int cid_bt498[] = {
0x0001d02f,
0
};
static u_int cid_sio[] = {
0x0ef0703b,
0
};
static u_int cid_hm[] = {
0x01792045,
0
};
static u_int cid_ac[] = {
0x10f9e07d,
0
};
static u_int cid_dc[] = {
0x10f9f07d,
0
};
static u_int cid_fhc[] = {
0x10fa007d,
0
};
static u_int cid_psyo[] = {
0x3195401d,
0
};
static u_int cid_cheo[] = {
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.
*/
static u_char ec_init_pdesc[] = {
JTIN_END|JTIN_INSERT|0, 0, 0, 0x0
};
static u_char ec_fmt[] = {
JTSO_ST|JTSO_XTRACT|JTSO_END| 0, 0, 4
};
static u_char sio_init_pdesc[] = {
JTIN_END|JTIN_INSERT|0, 0, 0, 0x0
};
static u_char sio_fmt[] = {
JTSO_ST|JTSO_XTRACT|JTSO_END| 0, 0, 4
};
static u_char psyo_init_pdesc[] = {
JTIN_END|JTIN_INSERT|0, 0, 0, 0x0
};
static u_char psyo_fmt[] = {
JTSO_ST|JTSO_XTRACT|JTSO_END| 0, 0, 4
};
static u_char hm_init_pdesc[] = {
JTIN_END|JTIN_INSERT|0, 0, 0, 0x0
};
static u_char hm_fmt[] = {
JTSO_ST|JTSO_XTRACT|JTSO_END| 0, 0, 4
};
static u_char ndp_init_pdesc[] = {
JTIN_END|JTIN_INSERT|0, 0, 0, 0x0
};
static u_char ndp_fmt[] = {
JTSO_ST|JTSO_XTRACT|JTSO_END| 0, 0, 4
};
static u_char cheo_init_pdesc[] = {
JTIN_END|JTIN_INSERT|0, 0, 0, 0x0
};
static u_char cheo_fmt[] = {
JTSO_ST|JTSO_XTRACT|JTSO_END| 0, 0, 4
};
/* 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.
*/
static u_char dc_init_pdesc[] = {
JTIN_INSERT|1, 0, 0, /* NFZN */
JTIN_INSERT|2, 4, 4, /* Mask PE */
JTIN_INSERT|3, 3, 3, /* Mask OE */
JTIN_INSERT|0, 1, 2, 3, /* W1C Errors */
JTIN_END|JTIN_UPDATE,
};
static u_char dc_fmt[] = {
JTSO_ST|JTSO_XTRACT|JTSO_END| 0, 0, 4 /* DC[4:0] */
};
/*
* 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.
*/
static u_char ac_init_pdesc[] = {
JTIN_INSERT|0, 161, 161, 1, /* BOARD ADDR 40 */
JTIN_INSERT|7, 159, 160, /* BOARD ADDR 39:38, wfi node */
JTIN_INSERT|4, 155, 158, /* BOARD ADDR 37:34 */
JTIN_INSERT|4, 151, 154, /* BOARD ID */
JTIN_INSERT|6, 146, 146, /* ARB_FAST */
JTIN_INSERT|1, 134, 134, /* NFZN */
JTIN_INSERT|0, 133, 133, 0, /* ENWAKPOR */
JTIN_INSERT|2, 135, 135, /* Reset B */
JTIN_INSERT|3, 136, 136, /* Reset A */
JTIN_INSERT|0, 99, 106, 0xff, /* W1C Errors */
JTIN_INSERT|0, 107, 114, 0xff, /* W1C Errors */
JTIN_INSERT|0, 115, 122, 0xff, /* W1C Errors */
JTIN_INSERT|0, 123, 130, 0xff, /* W1C Errors */
JTIN_INSERT|0, 131, 132, 0xff, /* W1C Errors */
JTIN_INSERT|5, 88, 98, /* Error Masks */
JTIN_INSERT|12, 76, 87, /* CNT1_CTL_<27:16> */
JTIN_INSERT|10, 70, 75, /* CNT1_CTL <13:8> */
JTIN_INSERT|11, 64, 69, /* CNT0_CTL <5:0> */
JTIN_INSERT|8, 32, 63, /* CNT1 */
JTIN_INSERT|9, 0, 31, /* CNT0 */
JTIN_END|JTIN_UPDATE, /* Clears counters */
};
static u_char ac_fmt[] = {
JTSO_XTRACT|17, 148, 162, /* BCSR[31:17] */
JTSO_XTRACT|15, 147, 147, /* BSCR[15] */
JTSO_XTRACT|5, 138, 146, /* BSCR[13:5] */
JTSO_ST|JTSO_XTRACT|0, 134, 137, /* BSCR[3:0] */
JTSO_ST|JTSO_XTRACT|22, 133, 133, /* BRSCR[22] */
JTSO_XTRACT|16, 131, 132, /* ESR[49:48] */
JTSO_XTRACT|8, 124, 130, /* ESR[46:40] */
JTSO_XTRACT|4, 122, 123, /* ESR[37:36] */
JTSO_ST|JTSO_XTRACT|0, 120, 121, /* ESR[33:32] */
JTSO_XTRACT|28, 116, 119, /* ESR[31:28] */
JTSO_XTRACT|24, 115, 115, /* ESR[24] */
JTSO_XTRACT|20, 112, 114, /* ESR[22:20] */
JTSO_XTRACT|12, 107, 111, /* ESR[16:12] */
JTSO_XTRACT|4, 101, 106, /* ESR[9:4] */
JTSO_ST|JTSO_XTRACT|0, 99, 100, /* ESR[1:0] */
JTSO_XTRACT|16, 97, 98, /* EMR[49:48] */
JTSO_XTRACT|8, 96, 96, /* EMR[40] */
JTSO_ST|JTSO_XTRACT|4, 94, 95, /* EMR[37:36] */
JTSO_XTRACT|28, 93, 93, /* EMR[28] */
JTSO_XTRACT|24, 92, 92, /* EMR[24] */
JTSO_XTRACT|20, 91, 91, /* EMR[20] */
JTSO_XTRACT|12, 90, 90, /* EMR[12] */
JTSO_XTRACT|8, 89, 89, /* EMR[8] */
JTSO_ST|JTSO_XTRACT|4, 88, 88, /* EMR[4] */
JTSO_XTRACT|16, 76, 87, /* CCR[27:16] */
JTSO_XTRACT|8, 70, 75, /* CCR[13:8] */
JTSO_ST|JTSO_XTRACT|0, 64, 69, /* CCR[5:0] */
JTSO_ST|JTSO_XTRACT|0, 32, 63, /* CNT[63:32] */
JTSO_ST|JTSO_XTRACT|JTSO_END|0, 0, 31 /* CNT[31:0] */
};
/*
*/
/*
* 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.
*/
static u_char fhc_init_pdesc[] = {
JTIN_INSERT|0, 41, 41, 0, /* POR */
JTIN_INSERT|1, 38, 40, /* CSR[20:18] */
JTIN_INSERT|2, 29, 37, /* CSR[16:8] */
JTIN_INSERT|3, 26, 28, /* CSR[6:4] */
JTIN_INSERT|0, 24, 25, 0x0, /* CSR[1:0] */
JTIN_INSERT|0, 16, 23, 0x0, /* RCSR[31:24] */
JTIN_INSERT|0, 2, 15, 0x0, /* BSR[18:5] */
JTIN_INSERT|0, 0, 1, 0x0, /* BSR[1:0] */
JTIN_END|JTIN_UPDATE,
};
static u_char fhc_fmt[] = {
JTSO_ST|JTSO_XTRACT|0, 41, 41, /* POR State */
JTSO_XTRACT|18, 38, 40, /* CSR[20:18] */
JTSO_XTRACT|8, 29, 37, /* CSR[16:8] */
JTSO_XTRACT|4, 26, 28, /* CSR[6:4] */
JTSO_ST|JTSO_XTRACT|0, 24, 25, /* CSR[1:0] */
JTSO_ST|JTSO_XTRACT|24, 16, 23, /* RCSR[31:24] */
JTSO_XTRACT|5, 2, 15, /* BSR[18:5] */
JTSO_ST|JTSO_XTRACT|JTSO_END|0, 0, 1, /* BSR[1:0] */
};
static u_char bct8244_fmt[] = {
JTSO_ST|JTSO_XTRACT|0, 17, 17, /* Disk 1 present */
JTSO_ST|JTSO_XTRACT|0, 16, 16, /* Disk 0 present */
JTSO_ST|JTSO_XTRACT|0, 12, 15, /* Disk 1 Target */
JTSO_ST|JTSO_XTRACT|JTSO_END|0, 8, 11, /* Disk 0 Target */
};
/* A jtag_log_comp describes a component as seen by JTAG. */
static jtag_log_comp chip_ac = {
cid_ac,
IR_LEN, 163,
IDCODE, INITCODE, DUMPCODE,
ac_init_pdesc, ac_fmt
};
static jtag_log_comp chip_bct8244 = {
0,
IR_LEN, 18,
0x2, 0x2, 0x2,
NULL, bct8244_fmt
};
static jtag_log_comp chip_dc = {
cid_dc,
IR_LEN, 5,
IDCODE, INITCODE, DUMPCODE,
dc_init_pdesc, dc_fmt
};
static jtag_log_comp chip_fhc = {
cid_fhc,
IR_LEN, 42,
IDCODE, INITCODE, DUMPCODE,
fhc_init_pdesc, fhc_fmt
};
static jtag_log_comp chip_ec = {
0,
EC_LEN, 42,
1, INITCODE, IDCODE,
ec_init_pdesc, ec_fmt
};
static jtag_log_comp chip_fbc = {
cid_fbc,
FFB_LEN, 42,
0xb000, 0xb000, 0xb000,
NULL, NULL
};
static jtag_log_comp chip_lvt = {
cid_lvt,
IR_LEN, 42,
IDCODE, INITCODE, DUMPCODE,
NULL, NULL
};
static jtag_log_comp chip_3dram = {
cid_3dram,
THREED_LEN, 42,
IDCODE, INITCODE, DUMPCODE,
NULL, NULL
};
static jtag_log_comp chip_bt498 = {
cid_bt498,
BT498_LEN, 42,
IDCODE, INITCODE, DUMPCODE,
NULL, NULL
};
static jtag_log_comp chip_sio = {
cid_sio,
SIO_LEN, 42,
0xb000, 0xb000, 0xb000,
sio_init_pdesc, sio_fmt
};
static jtag_log_comp chip_hm = {
cid_hm,
HM_LEN, 42,
0xe, 0xe, 0xe,
hm_init_pdesc, hm_fmt
};
static jtag_log_comp chip_ndp = {
0,
NDP_LEN, 42,
2, 2, 2,
ndp_init_pdesc, ndp_fmt
};
static jtag_log_comp chip_soc = {
0,
SOC_LEN, 42,
4, 4, 4,
NULL, NULL
};
static jtag_log_comp chip_socplus = {
0,
SOCPLUS_LEN, 42,
0xfe, 4, 4,
NULL, NULL
};
static jtag_log_comp chip_spitfire = {
cid_sf,
IR_LEN, 42,
0xfe, 0xfe, 0xfe,
NULL, NULL
};
static jtag_log_comp chip_sdb = {
cid_sdb,
IR_LEN, 42,
0xfe, 0xfe, 0xfe,
NULL, NULL
};
static jtag_log_comp chip_psyo = {
cid_psyo,
PSYO_LEN, 42,
0xb000, 0xb000, 0xb000,
psyo_init_pdesc, psyo_fmt
};
static jtag_log_comp chip_cheo = {
cid_cheo,
CHEO_LEN, 42,
0xb000, 0xb000, 0xb000,
cheo_init_pdesc, cheo_fmt
};
/*
* 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
*/
static jtag_phys_comp cpu_sysbd_ring_components[] = {
{ &chip_ac, 11*IR_LEN, 0, 11, 0 }, /* AC */
{ &chip_dc, 10*IR_LEN, 1*IR_LEN, 10, 1 }, /* DC 1 */
{ &chip_dc, 9*IR_LEN, 2*IR_LEN, 9, 2 }, /* DC 2 */
{ &chip_dc, 8*IR_LEN, 3*IR_LEN, 8, 3 }, /* DC 3 */
{ &chip_dc, 7*IR_LEN, 4*IR_LEN, 7, 4 }, /* DC 4 */
{ &chip_dc, 6*IR_LEN, 5*IR_LEN, 6, 5 }, /* DC 5 */
{ &chip_dc, 5*IR_LEN, 6*IR_LEN, 5, 6 }, /* DC 6 */
{ &chip_dc, 4*IR_LEN, 7*IR_LEN, 4, 7 }, /* DC 7 */
{ &chip_dc, 3*IR_LEN, 8*IR_LEN, 3, 8 }, /* DC 8 */
{ &chip_fhc, 2*IR_LEN, 9*IR_LEN, 2, 9 }, /* FHC */
{ &chip_ec, 1*IR_LEN, 10*IR_LEN, 1, 10 }, /* RAM 0 */
{ &chip_ec, 0*IR_LEN, 11*IR_LEN, 0, 11 }, /* RAM 1 */
};
static jtag_ring_desc cpu_sysbd_ring = {
12, cpu_sysbd_ring_components
};
static jtag_phys_comp cpu_mod_1m_ring_components[] = {
{ &chip_spitfire, 43, 0, 11, 0 }, /* Spitfire */
{ &chip_ec, 40, 8, 10, 1 }, /* Parity chip */
{ &chip_ec, 37, 11, 9, 2 }, /* Byte 0 */
{ &chip_ec, 34, 14, 8, 3 }, /* Byte 1 */
{ &chip_ec, 31, 17, 7, 4 }, /* Byte 2 */
{ &chip_ec, 28, 20, 6, 5 }, /* Byte 3 */
{ &chip_ec, 25, 23, 5, 6 }, /* Byte 4 */
{ &chip_ec, 22, 26, 4, 7 }, /* Byte 5 */
{ &chip_ec, 19, 29, 3, 8 }, /* Byte 6 */
{ &chip_ec, 16, 32, 2, 9 }, /* Byte 7 */
{ &chip_sdb, 8, 35, 1, 10 }, /* SDB */
{ &chip_sdb, 0, 43, 0, 11 }, /* SDB */
};
static jtag_ring_desc cpu_mod_1m_ring = {
12, cpu_mod_1m_ring_components
};
static jtag_phys_comp cpu_mod_ring_components[] = {
{ &chip_spitfire, 31, 0, 7, 0 }, /* Spitfire */
{ &chip_ec, 28, 8, 6, 1 }, /* Parity chip */
{ &chip_ec, 25, 11, 5, 2 }, /* Byte 0 */
{ &chip_ec, 22, 14, 4, 3 }, /* Byte 1 */
{ &chip_ec, 19, 17, 3, 4 }, /* Byte 2 */
{ &chip_ec, 16, 20, 2, 5 }, /* Byte 3 */
{ &chip_sdb, 8, 23, 1, 6 }, /* SDB */
{ &chip_sdb, 0, 31, 0, 7 }, /* SDB */
};
static jtag_ring_desc cpu_mod_ring = {
8, cpu_mod_ring_components
};
static jtag_phys_comp io1_sysbd_ring_components[] = {
{ &chip_ac, 114, 0, 14, 0 }, /* AC */
{ &chip_dc, 106, 8, 13, 1 }, /* DC 1 */
{ &chip_dc, 98, 16, 12, 2 }, /* DC 2 */
{ &chip_dc, 90, 24, 11, 3 }, /* DC 3 */
{ &chip_dc, 82, 32, 10, 4 }, /* DC 4 */
{ &chip_dc, 74, 40, 9, 5 }, /* DC 5 */
{ &chip_dc, 66, 48, 8, 6 }, /* DC 6 */
{ &chip_dc, 58, 56, 7, 7 }, /* DC 7 */
{ &chip_dc, 50, 64, 6, 8 }, /* DC 8 */
{ &chip_fhc, 42, 72, 5, 9 }, /* FHC */
{ &chip_sio, 26, 80, 4, 10 }, /* SIO 0 */
{ &chip_sio, 10, 96, 3, 11 }, /* SIO 1 */
{ &chip_hm, 6, 112, 2, 12 }, /* HM */
{ &chip_ndp, 4, 116, 1, 13 }, /* NDP */
{ &chip_soc, 0, 118, 0, 14 }, /* SOC */
};
static jtag_phys_comp io2_sysbd_ring_components[] = {
{ &chip_ac, 98, 0, 13, 0 }, /* AC */
{ &chip_dc, 90, 8, 12, 1 }, /* DC 1 */
{ &chip_dc, 82, 16, 11, 2 }, /* DC 2 */
{ &chip_dc, 74, 24, 10, 3 }, /* DC 3 */
{ &chip_dc, 66, 32, 9, 4 }, /* DC 4 */
{ &chip_dc, 58, 40, 8, 5 }, /* DC 5 */
{ &chip_dc, 50, 48, 7, 6 }, /* DC 6 */
{ &chip_dc, 42, 56, 6, 7 }, /* DC 7 */
{ &chip_dc, 34, 64, 5, 8 }, /* DC 8 */
{ &chip_fhc, 26, 72, 4, 9 }, /* FHC */
{ &chip_sio, 10, 80, 3, 10 }, /* SIO */
{ &chip_hm, 6, 96, 2, 11 }, /* HM */
{ &chip_ndp, 4, 100, 1, 12 }, /* NDP */
{ &chip_soc, 0, 102, 0, 13 }, /* SOC */
};
static jtag_phys_comp io1plus_sysbd_ring_components[] = {
{ &chip_ac, 118, 0, 14, 0 }, /* AC */
{ &chip_dc, 110, 8, 13, 1 }, /* DC 1 */
{ &chip_dc, 102, 16, 12, 2 }, /* DC 2 */
{ &chip_dc, 94, 24, 11, 3 }, /* DC 3 */
{ &chip_dc, 86, 32, 10, 4 }, /* DC 4 */
{ &chip_dc, 78, 40, 9, 5 }, /* DC 5 */
{ &chip_dc, 70, 48, 8, 6 }, /* DC 6 */
{ &chip_dc, 62, 56, 7, 7 }, /* DC 7 */
{ &chip_dc, 54, 64, 6, 8 }, /* DC 8 */
{ &chip_fhc, 46, 72, 5, 9 }, /* FHC */
{ &chip_sio, 30, 80, 4, 10 }, /* SIO 0 */
{ &chip_sio, 14, 96, 3, 11 }, /* SIO 1 */
{ &chip_hm, 10, 112, 2, 12 }, /* HM */
{ &chip_ndp, 8, 116, 1, 13 }, /* NDP */
{ &chip_socplus, 0, 118, 0, 14 }, /* SOC+ */
};
static jtag_phys_comp io2plus_sysbd_ring_components[] = {
{ &chip_ac, 102, 0, 13, 0 }, /* AC */
{ &chip_dc, 94, 8, 12, 1 }, /* DC 1 */
{ &chip_dc, 86, 16, 11, 2 }, /* DC 2 */
{ &chip_dc, 78, 24, 10, 3 }, /* DC 3 */
{ &chip_dc, 70, 32, 9, 4 }, /* DC 4 */
{ &chip_dc, 62, 40, 8, 5 }, /* DC 5 */
{ &chip_dc, 54, 48, 7, 6 }, /* DC 6 */
{ &chip_dc, 46, 56, 6, 7 }, /* DC 7 */
{ &chip_dc, 38, 64, 5, 8 }, /* DC 8 */
{ &chip_fhc, 30, 72, 4, 9 }, /* FHC */
{ &chip_sio, 14, 80, 3, 10 }, /* SIO */
{ &chip_hm, 10, 96, 2, 11 }, /* HM */
{ &chip_ndp, 8, 100, 1, 12 }, /* NDP */
{ &chip_socplus, 0, 102, 0, 13 }, /* SOC+ */
};
static jtag_phys_comp io3_sysbd_ring_components[] = {
{ &chip_ac, 102, 0, 15, 0 }, /* AC */
{ &chip_dc, 94, 8, 14, 1 }, /* DC 1 */
{ &chip_dc, 86, 16, 13, 2 }, /* DC 2 */
{ &chip_dc, 78, 24, 12, 3 }, /* DC 3 */
{ &chip_dc, 70, 32, 11, 4 }, /* DC 4 */
{ &chip_dc, 62, 40, 10, 5 }, /* DC 5 */
{ &chip_dc, 54, 48, 9, 6 }, /* DC 6 */
{ &chip_dc, 46, 56, 8, 7 }, /* DC 7 */
{ &chip_dc, 38, 64, 7, 8 }, /* DC 8 */
{ &chip_fhc, 30, 72, 6, 9 }, /* FHC */
{ &chip_psyo, 26, 80, 5, 10 }, /* PSYO 0 */
{ &chip_cheo, 22, 84, 4, 11 }, /* CHEO */
{ &chip_ndp, 20, 88, 3, 12 }, /* NDP */
{ &chip_psyo, 16, 90, 2, 13 }, /* PSYO 1 */
{ &chip_bct8244, 8, 94, 1, 14 }, /* BCT 8244 */
{ &chip_bct8244, 0, 102, 0, 15 }, /* BCT 8244 */
};
static jtag_phys_comp dsk_sysbd_ring_components[] = {
{ &chip_bct8244, 8, 0, 1, 0 }, /* BCT 8244 */
{ &chip_fhc, 0, 8, 0, 1 }, /* FHC */
};
static jtag_ring_desc io1_sysbd_ring = {
15, io1_sysbd_ring_components
};
static jtag_ring_desc io1plus_sysbd_ring = {
15, io1plus_sysbd_ring_components
};
static jtag_ring_desc io2_sysbd_ring = {
14, io2_sysbd_ring_components
};
static jtag_ring_desc io2plus_sysbd_ring = {
14, io2plus_sysbd_ring_components
};
static jtag_ring_desc io3_sysbd_ring = {
16, io3_sysbd_ring_components
};
static jtag_ring_desc dsk_sysbd_ring = {
2, dsk_sysbd_ring_components
};
/*
* 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.
*/
static jtag_phys_comp ffb_sngl_ring_components[] = {
{ &chip_fbc, 20, 0, 5, 0 }, /* FBC */
{ &chip_3dram, 16, 16, 4, 1 }, /* 3DRAM */
{ &chip_3dram, 12, 20, 3, 2 }, /* 3DRAM */
{ &chip_3dram, 8, 24, 2, 3 }, /* 3DRAM */
{ &chip_3dram, 4, 28, 1, 4 }, /* 3DRAM */
{ &chip_bt498, 0, 32, 0, 5 }, /* RAMDAC */
};
static jtag_phys_comp ffb_dbl_ring_components[] = {
{ &chip_fbc, 84, 0, 17, 0 }, /* FBC */
{ &chip_lvt, 76, 16, 16, 1 }, /* LVT */
{ &chip_lvt, 68, 24, 15, 2 }, /* LVT */
{ &chip_lvt, 60, 32, 14, 3 }, /* LVT */
{ &chip_lvt, 52, 40, 13, 4 }, /* LVT */
{ &chip_3dram, 48, 48, 12, 5 }, /* 3DRAM */
{ &chip_3dram, 44, 52, 11, 6 }, /* 3DRAM */
{ &chip_3dram, 40, 56, 10, 7 }, /* 3DRAM */
{ &chip_3dram, 36, 60, 9, 8 }, /* 3DRAM */
{ &chip_3dram, 32, 64, 8, 9 }, /* 3DRAM */
{ &chip_3dram, 28, 68, 7, 10 }, /* 3DRAM */
{ &chip_3dram, 24, 72, 6, 11 }, /* 3DRAM */
{ &chip_3dram, 20, 76, 5, 12 }, /* 3DRAM */
{ &chip_3dram, 16, 80, 4, 13 }, /* 3DRAM */
{ &chip_3dram, 12, 84, 3, 14 }, /* 3DRAM */
{ &chip_3dram, 8, 88, 2, 15 }, /* 3DRAM */
{ &chip_3dram, 4, 92, 1, 16 }, /* 3DRAM */
{ &chip_bt498, 0, 96, 0, 17 }, /* RAMDAC */
};
static jtag_ring_desc ffb_sngl_ring = {
6, ffb_sngl_ring_components
};
static jtag_ring_desc ffb_dbl_ring = {
18, ffb_dbl_ring_components
};
/*
* Board descriptions
*/
static jtag_ring_desc *cpu_system_board[] = {
&cpu_sysbd_ring, /* Ring 0 */
&cpu_mod_ring, /* Ring 1 */
&cpu_mod_ring, /* Ring 2 */
};
static jtag_ring_desc *io1_system_board[] = {
&io1_sysbd_ring, /* Ring 0 */
(jtag_ring_desc *) NULL, /* Ring 1 */
(jtag_ring_desc *) NULL, /* Ring 2 */
};
static jtag_ring_desc *io1plus_system_board[] = {
&io1plus_sysbd_ring, /* Ring 0 */
(jtag_ring_desc *) NULL, /* Ring 1 */
(jtag_ring_desc *) NULL, /* Ring 2 */
};
static jtag_ring_desc *io2_system_board[] = {
&io2_sysbd_ring, /* Ring 0 */
(jtag_ring_desc *) NULL, /* Ring 1 (ffb) */
(jtag_ring_desc *) NULL, /* Ring 2 */
};
static jtag_ring_desc *io2plus_system_board[] = {
&io2plus_sysbd_ring, /* Ring 0 */
(jtag_ring_desc *) NULL, /* Ring 1 (ffb) */
(jtag_ring_desc *) NULL, /* Ring 2 */
};
static jtag_ring_desc *io3_system_board[] = {
&io3_sysbd_ring, /* Ring 0 */
(jtag_ring_desc *) NULL, /* Ring 1 */
(jtag_ring_desc *) NULL, /* Ring 2 */
};
static jtag_ring_desc *disk_system_board[] = {
&dsk_sysbd_ring, /* Ring 0 */
(jtag_ring_desc *) NULL, /* Ring 1 */
(jtag_ring_desc *) NULL, /* Ring 2 */
};
/*
* Function Definitions:
* ---------------------
*/
/* For sunfire there will be a ring descriptor for each type of board */
static jtag_ring_desc *
get_ring_descriptor_bytype(int ring, enum board_type type)
{
switch (type) {
case CPU_BOARD:
return (cpu_system_board[ring & 0xf]);
case IO_2SBUS_BOARD:
return (io1_system_board[ring & 0xf]);
case IO_2SBUS_SOCPLUS_BOARD:
return (io1plus_system_board[ring & 0xf]);
case IO_SBUS_FFB_BOARD:
return (io2_system_board[ring & 0xf]);
case IO_SBUS_FFB_SOCPLUS_BOARD:
return (io2plus_system_board[ring & 0xf]);
case IO_PCI_BOARD:
return (io3_system_board[ring & 0xf]);
case DISK_BOARD:
return (disk_system_board[ring & 0xf]);
default:
return (NULL);
}
}
static void
jtag_check_plus_board(
volatile u_int *jreg,
jtag_ring ring,
jtag_phys_comp *comp,
sysc_cfga_stat_t *sc)
{
struct fhc_regs fhc_data;
/*
* the FHC Board Status Register indicates whether
* the board 100 Mhz capable or not.
*/
fhc_data.bsr = (u_int)0xffffffff;
if ((jtag_scanout_chip(jreg, ring, comp, (u_int *)&fhc_data) >= 0) &&
(FHC_BSR_TO_BD(fhc_data.bsr) == sc->board) &&
ISPLUSBRD(fhc_data.bsr))
sc->plus_board = 1;
}
/*
* Returns (positive) board type if something detected, including
* UNKNOWN_BOARD.
* Returns -1 if nothing there.
*/
enum board_type
jtag_get_board_type(volatile u_int *jreg, sysc_cfga_stat_t *sc)
{
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)
*/
board = sc->board;
ring = (board << 4) | 0;
if ((status = select_ring(jreg, ring, 1)) < 0) {
cmn_err(CE_WARN, "Select ring error %d\n", status);
}
len = jtag_ring_length(jreg, ring);
switch (len) {
case CPU_TYPE_LEN:
result = CPU_BOARD;
jtag_check_plus_board(jreg, ring,
&cpu_sysbd_ring_components[9], sc);
break;
case IO_TYPE1_LEN:
switch (jtag_ring_ir_length(jreg, ring)) {
case RING_BROKEN:
result = UNKNOWN_BOARD;
break;
case IO_TYPE4_LEN:
result = IO_2SBUS_SOCPLUS_BOARD;
jtag_check_plus_board(jreg, ring,
&io1plus_sysbd_ring_components[9], sc);
break;
default:
result = IO_2SBUS_BOARD;
jtag_check_plus_board(jreg, ring,
&io1_sysbd_ring_components[9], sc);
break;
}
break;
case IO_TYPE2_LEN:
switch (jtag_ring_ir_length(jreg, ring)) {
case RING_BROKEN:
result = UNKNOWN_BOARD;
break;
case IO_TYPE5_LEN:
result = IO_SBUS_FFB_SOCPLUS_BOARD;
jtag_check_plus_board(jreg, ring,
&io2plus_sysbd_ring_components[9], sc);
break;
default:
result = IO_SBUS_FFB_BOARD;
jtag_check_plus_board(jreg, ring,
&io2_sysbd_ring_components[9], sc);
break;
}
break;
case PCI_TYPE_LEN:
switch (jtag_ring_ir_length(jreg, ring)) {
case RING_BROKEN:
result = UNKNOWN_BOARD;
break;
case PCI_TYPEA_LEN:
result = IO_PCI_BOARD;
jtag_check_plus_board(jreg, ring,
&io3_sysbd_ring_components[9], sc);
break;
case PCI_TYPEB_LEN:
default:
result = UNKNOWN_BOARD;
break;
}
break;
case DSK_TYPE_LEN:
result = DISK_BOARD;
break;
case RING_BROKEN:
result = -1;
break;
default:
result = UNKNOWN_BOARD;
break;
}
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
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
jtag_get_board_info(volatile u_int *jreg, sysc_cfga_stat_t *sc)
{
jtag_ring_desc *rd;
jtag_phys_comp *rc;
int status;
int ring;
int len;
int i;
struct cpu_info *cpu;
struct bct_fields bct_data;
/* fill in the board info structure */
ring = sc->board << 4;
if ((status = select_ring(jreg, ring, 1)) < 0) {
return (status);
}
rd = get_ring_descriptor_bytype(ring, sc->type);
if (rd == NULL) {
return (JTAG_FAIL);
}
/* scan in the generic data common to all board types. */
/* get the AC component ID */
rc = find_chip(rd, &chip_ac, 0);
if (rc != NULL) {
sc->ac_compid = jtag_get_comp_id(jreg, rc);
}
/* get the FHC component ID */
rc = find_chip(rd, &chip_fhc, 0);
if (rc != NULL) {
sc->fhc_compid = jtag_get_comp_id(jreg, rc);
}
/* Now scan the board type dependent components */
switch (sc->type) {
case CPU_BOARD:
/*
* first determine the cache size of each module, then
* use that ring descriptor.
*/
for (i = 0, cpu = &sc->bd.cpu[i]; i < 2; i++, cpu++) {
bzero(cpu, sizeof (*cpu));
#ifndef RFE_4174486
if (!jtag_cpu_scan_enable)
continue;
#endif /* RFE_4174486 */
if (select_ring(jreg, ring | (i + 1), 1) < 0) {
continue;
}
len = jtag_ring_length(jreg, ring | (i + 1));
switch (len) {
case CPU_0_5_LEN:
rd = &cpu_mod_ring;
cpu->cpu_detected = 1;
break;
case CPU_1_0_LEN:
rd = &cpu_mod_1m_ring;
cpu->cpu_detected = 1;
break;
case RING_BROKEN:
default:
rd = NULL;
break;
}
if (!cpu->cpu_detected)
continue;
if (rd != NULL) {
rc = find_chip(rd, &chip_spitfire, 0);
if (rc != NULL) {
cpu->cpu_compid =
jtag_get_comp_id(jreg, rc);
}
/*
* Do not get the component ID from the
* first E$ chip. This is the tag chip
* and does not help determine cache size.
*/
rc = find_chip(rd, &chip_ec, 1);
if (rc != NULL) {
cpu->ec_compid =
jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_sdb, 0);
if (rc != NULL) {
cpu->sdb0_compid =
jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_sdb, 1);
if (rc != NULL) {
cpu->sdb1_compid =
jtag_get_comp_id(jreg, rc);
}
}
#ifdef RFE_4174486
/* Work out Ecache size. */
switch (len) {
case CPU_0_5_LEN:
cpu->cache_size = 0x80000;
break;
case CPU_1_0_LEN:
/* default cache size for 9 SRAM chips */
cpu->cache_size = 0x100000;
break;
default:
break;
}
#endif /* RFE_4174486 */
}
break;
case IO_2SBUS_BOARD:
rc = find_chip(rd, &chip_sio, 0);
if (rc != NULL) {
sc->bd.io1.sio0_compid =
jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_sio, 1);
if (rc != NULL) {
sc->bd.io1.sio1_compid =
jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_hm, 0);
if (rc != NULL) {
sc->bd.io1.hme_compid = jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_soc, 0);
if (rc != NULL) {
sc->bd.io1.soc_compid = jtag_get_comp_id(jreg, rc);
}
break;
case IO_2SBUS_SOCPLUS_BOARD:
rc = find_chip(rd, &chip_sio, 0);
if (rc != NULL) {
sc->bd.io1.sio0_compid =
jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_sio, 1);
if (rc != NULL) {
sc->bd.io1.sio1_compid =
jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_hm, 0);
if (rc != NULL) {
sc->bd.io1.hme_compid = jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_socplus, 0);
if (rc != NULL) {
sc->bd.io1plus.socplus_compid =
jtag_get_comp_id(jreg, rc);
}
break;
case IO_SBUS_FFB_BOARD:
rc = find_chip(rd, &chip_sio, 0);
if (rc != NULL) {
sc->bd.io2.sio1_compid = jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_hm, 0);
if (rc != NULL) {
sc->bd.io2.hme_compid = jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_soc, 0);
if (rc != NULL) {
sc->bd.io2.soc_compid = jtag_get_comp_id(jreg, rc);
}
/* Now scan for an FFB board */
if (select_ring(jreg, ring | 1, 1) < 0) {
len = RING_BROKEN;
} else {
len = jtag_ring_length(jreg, ring | 1);
}
switch (len) {
case FFB_SNG_LEN:
rd = &ffb_sngl_ring;
sc->bd.io2.ffb_size = FFB_SINGLE;
break;
case FFB_DBL_LEN:
rd = &ffb_dbl_ring;
sc->bd.io2.ffb_size = FFB_DOUBLE;
break;
case RING_BROKEN:
rd = NULL;
sc->bd.io2.ffb_size = FFB_NOT_FOUND;
break;
default:
rd = NULL;
sc->bd.io2.ffb_size = FFB_FAILED;
break;
}
/* Now scan out the FBC component ID */
if (rd != NULL) {
rc = find_chip(rd, &chip_fbc, 0);
}
if (rc != NULL) {
sc->bd.io2.fbc_compid = jtag_get_comp_id(jreg, rc);
}
break;
case IO_SBUS_FFB_SOCPLUS_BOARD:
rc = find_chip(rd, &chip_sio, 0);
if (rc != NULL) {
sc->bd.io2.sio1_compid = jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_hm, 0);
if (rc != NULL) {
sc->bd.io2.hme_compid = jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_socplus, 0);
if (rc != NULL) {
sc->bd.io2plus.socplus_compid =
jtag_get_comp_id(jreg, rc);
}
/* Now scan for an FFB board */
if (select_ring(jreg, ring | 1, 1) < 0) {
len = RING_BROKEN;
} else {
len = jtag_ring_length(jreg, ring | 1);
}
switch (len) {
case FFB_SNG_LEN:
rd = &ffb_sngl_ring;
sc->bd.io2.ffb_size = FFB_SINGLE;
break;
case FFB_DBL_LEN:
rd = &ffb_dbl_ring;
sc->bd.io2.ffb_size = FFB_DOUBLE;
break;
case RING_BROKEN:
rd = NULL;
sc->bd.io2.ffb_size = FFB_NOT_FOUND;
break;
default:
rd = NULL;
sc->bd.io2.ffb_size = FFB_FAILED;
break;
}
/* Now scan out the FBC component ID */
if (rd != NULL) {
rc = find_chip(rd, &chip_fbc, 0);
}
if (rc != NULL) {
sc->bd.io2.fbc_compid = jtag_get_comp_id(jreg, rc);
}
break;
case IO_PCI_BOARD:
rc = find_chip(rd, &chip_psyo, 0);
if (rc != NULL) {
sc->bd.io3.psyo0_compid =
jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_psyo, 1);
if (rc != NULL) {
sc->bd.io3.psyo1_compid =
jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_cheo, 0);
if (rc != NULL) {
sc->bd.io3.cheo_compid = jtag_get_comp_id(jreg, rc);
}
break;
case DISK_BOARD:
/*
* Scan the BCT8244 to get the disk drive info out of
* the chip.
*/
if (jtag_scanout_chip(jreg, ring,
&dsk_sysbd_ring_components[0], (u_int *)&bct_data) < 0) {
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
return (-1);
}
if ((bct_data.disk0_pres && 0x1) == 0) {
sc->bd.dsk.disk_pres[0] = 1;
sc->bd.dsk.disk_id[0] = 0xf & ~bct_data.disk0_id;
} else {
sc->bd.dsk.disk_pres[0] = 0;
}
if ((bct_data.disk1_pres && 0x1) == 0) {
sc->bd.dsk.disk_pres[1] = 1;
sc->bd.dsk.disk_id[1] = 0xf & ~bct_data.disk1_id;
} else {
sc->bd.dsk.disk_pres[1] = 0;
}
break;
default:
break;
}
return (JTAG_OK);
}
static jtag_phys_comp *
find_chip(jtag_ring_desc *rd, jtag_log_comp *chip, int instance)
{
int i;
int found = 0;
jtag_phys_comp *rc;
for (i = rd->size, rc = rd->components; i != 0; rc++, i--) {
if (rc->chip == chip) {
if (found == instance) {
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
jtag_error_print(int ring, jtag_error code)
{
char *ring_str = "System Board";
switch (code) {
case JTAG_OK :
break;
case TAP_TIMEOUT :
cmn_err(CE_WARN, "%s : TAP controller timeout\n", jtag_err);
break;
case BAD_ARGS :
cmn_err(CE_WARN,
"%s : routine reports bad args: Board %d, %s Ring\n",
jtag_err, ring >> 4, ring_str);
break;
case BAD_CID :
cmn_err(CE_WARN,
"%s : Bad component ID detected: Board %d, %s Ring\n",
jtag_err, ring >> 4, ring_str);
break;
case RING_BROKEN :
cmn_err(CE_WARN, "%s : ring broken: Board %d, %s Ring\n",
jtag_err, ring >> 4, ring_str);
break;
case INIT_MISMATCH:
cmn_err(CE_WARN,
"%s : State after init not expected: Board %d, "
"%s Ring\n", jtag_err, ring >> 4, ring_str);
break;
case LENGTH_MISMATCH :
cmn_err(CE_WARN,
"%s : Scan Chain Length mismatch: Board %d,"
" %s Ring\n",
jtag_err, ring >> 4, ring_str);
break;
} /* end of switch on code */
} /* end of jtag_error_print() */
static int
jtag_get_comp_id(volatile u_int *jreg, jtag_phys_comp *comp)
{
u_char b[4];
u_int id;
int status;
status = jtag_single_IR_DR(jreg, comp, comp->chip->id_code,
b, 32, b);
/* Reorder the bytes of the ID read out */
id = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
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
jtag_bf_extract(u_char *s, int lsb, int msb)
{
u_int result = 0;
ASSERT(s);
/*
* lsb and msb are assumed to be within string,
* and to span 32 bits at most
*/
for (; msb >= lsb; msb--) {
result = (result << 1) | ((s[msb>>3] >> (msb & 7)) & 1);
}
return (result);
}
/*
* jtag_bf_insert()
*
* This routine is used to build bit strings for scanning into the
* shadow chains of ASICs.
*/
static void
jtag_bf_insert(u_char *s, int lsb, int msb, int value)
{
ASSERT(s);
/*
* lsb and msb are assumed to be within string,
* and to span 32 bits at most
*/
for (; msb >= lsb; lsb++) {
s[lsb>>3] = (s[lsb>>3] & ~ (1 << (lsb & 7))) |
((value & 1) << (lsb & 7));
value = value >> 1;
}
}
/*
*
*/
static void
jtag_bf_zero(u_char *s, int nbits)
{
int nbytes = (nbits+7)>>3;
while (nbytes-- != 0) {
*s++ = 0;
}
}
/*
* Return 0 if equal, != 0 else
*/
static int
jtag_bf_cmp(u_char *s1, u_char *s2, int nbits)
{
int mask;
for (nbits -= 8; nbits > 0; nbits -= 8) {
if (*s1++ != *s2++) {
return (-1);
}
mask = 0xFF >> (-nbits);
if ((*s1++ & mask) != (*s2++ & mask)) {
return (-1);
}
}
return (0);
}
/*
* Generic chip-level top routines
*/
static int
jtag_init_chip(
volatile u_int *jreg,
jtag_ring ring,
jtag_phys_comp *component,
const u_int *pval,
u_char scan_out[32])
{
int status;
jtag_log_comp *chip;
u_char scan_in[32];
u_char *pdesc;
status = select_ring(jreg, ring, 1);
if (status < 0) {
return (status);
}
pval = pval - 1; /* adjust pval since indices start at 1 */
chip = component->chip;
pdesc = chip->init_pdesc;
/* Zero out the scan-in area */
jtag_bf_zero(scan_in, 8*32);
jtag_bf_zero(scan_out, 8*32);
for (;;) {
u_int flags, lsb, msb, patch;
flags = *pdesc++;
if ((flags & JTIN_INSERT) != 0) {
lsb = *pdesc++;
msb = *pdesc++;
if ((flags & JTIN_INDEX) != 0) {
patch = pval[flags & JTIN_INDEX];
} else {
patch = *pdesc++;
}
jtag_bf_insert(scan_in, lsb, msb, patch);
}
if ((flags & JTIN_UPDATE) != 0) {
status = jtag_single_IR_DR(jreg, component,
chip->init_code, scan_in, chip->dr_len,
scan_out);
if (status < 0) {
return (status);
}
if ((status = select_ring(jreg, ring, 1)) < 0) {
return (status);
}
}
if ((flags & JTIN_COMPARE) != 0) {
if (jtag_bf_cmp(scan_in, scan_out, chip->dr_len) != 0)
return (INIT_MISMATCH);
}
if ((flags & JTIN_END) != 0) {
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
jtag_scanout_chip(
volatile u_int *jreg,
jtag_ring ring,
jtag_phys_comp *component,
u_int *result)
{
int status;
jtag_log_comp *chip;
u_char scan_in[32];
u_char scan_out[32];
u_char *p;
u_int value;
int bytes_used = 0;
if ((status = select_ring(jreg, ring, 1)) < 0) {
return (status);
}
chip = component->chip;
p = chip->fmt_desc;
if (p == NULL) {
return (bytes_used);
}
status = jtag_rescan_IR_DR(jreg, component, chip->dump_code, scan_in,
chip->dr_len, scan_out);
if (status < 0) {
return (status);
}
if ((status = select_ring(jreg, ring, 1)) < 0) {
return (status);
}
for (value = 0; ; ) {
u_char cmd = *p++;
if ((cmd & JTSO_XTRACT) != 0) {
u_int lsb, msb;
lsb = *p++;
msb = *p++;
value |= jtag_bf_extract(scan_out, lsb, msb) <<
(cmd & JTSO_SHIFT);
}
if ((cmd & JTSO_ST) != 0) {
*result++ = value;
bytes_used += 4;
value = 0;
}
if ((cmd & JTSO_END) != 0) {
break;
}
}
return (bytes_used);
}
/*
* Set the AC into hotplug mode upon insertion
*/
static int
jtag_init_ac(volatile u_int *jreg, int bid, enum board_type brdtype)
{
int rc = JTAG_OK;
int status;
int ring = (bid << 4);
ac_options ac_opt;
u_char scan_out[64];
uint_t cs_value;
if (brdtype == UNKNOWN_BOARD)
return (rc);
ac_opt.frozen = 0; /* 0 = frozen */
ac_opt.reset_a = 1;
ac_opt.reset_b = 1;
ac_opt.board_id = bid;
ac_opt.mask_hwerr = (uint_t)-1;
ac_opt.node_id = 3;
/* Get a good AC BCSR value from the board we are running on. */
cs_value = ldphysio(AC_BCSR(FHC_CPU2BOARD(CPU->cpu_id)));
ac_opt.arb_fast = (cs_value & AC_ARB_FAST) ? 1 : 0;
ac_opt.pcr_hi = 0;
ac_opt.pcr_lo = 0x80000000LL - 0x9ac4 - (bid << 3);
ac_opt.pcc_ctl0 = 0x3f;
ac_opt.pcc_ctl1 = 0x3f;
ac_opt.pcc_tctrl = (1 << 11); /* TREN */
if ((brdtype == CPU_BOARD) || (brdtype == MEM_BOARD)) {
rc = jtag_init_chip(jreg, ring, &cpu_sysbd_ring_components[0],
(jtag_opt)&ac_opt, scan_out);
} else if (brdtype == IO_2SBUS_BOARD) {
rc = jtag_init_chip(jreg, ring, &io1_sysbd_ring_components[0],
(jtag_opt)&ac_opt, scan_out);
} else if (brdtype == IO_2SBUS_SOCPLUS_BOARD) {
rc = jtag_init_chip(jreg, ring,
&io1plus_sysbd_ring_components[0],
(jtag_opt)&ac_opt, scan_out);
} else if (brdtype == IO_SBUS_FFB_BOARD) {
rc = jtag_init_chip(jreg, ring, &io2_sysbd_ring_components[0],
(jtag_opt)&ac_opt, scan_out);
} else if (brdtype == IO_SBUS_FFB_SOCPLUS_BOARD) {
rc = jtag_init_chip(jreg, ring,
&io2plus_sysbd_ring_components[0],
(jtag_opt)&ac_opt, scan_out);
} else if (brdtype == IO_PCI_BOARD) {
rc = jtag_init_chip(jreg, ring, &io3_sysbd_ring_components[0],
(jtag_opt)&ac_opt, scan_out);
} else {
cmn_err(CE_NOTE, " jtag_init_ac() Board %d"
" unsupported type %2X", bid, brdtype);
}
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
if (rc != JTAG_OK) {
jtag_error_print(ring, rc);
}
return (rc);
}
#define EN_LOC_FATAL 0x02
#define MOD_OFF 0x80
#define ACDC_OFF 0x40
#define EPDA_OFF 0x10
#define EPDB_OFF 0x08
#define NOT_BRD_PRESENT 0x02
#define NOT_BRD_LED_LEFT 0x04
#define BRD_LED_MID 0x02
#define BRD_LED_RIGHT 0x01
/*
* Each board has an FHC asic.
*/
int
jtag_powerdown_board(volatile u_int *jreg, int board, enum board_type type,
u_int *fhc_csr, u_int *fhc_bsr, int intr)
{
int rc = JTAG_OK;
fhc_options fhc_opt;
struct fhc_regs fhc_data;
u_char scan_out[32];
int status;
int ring;
if (type == UNKNOWN_BOARD) {
sysc_cfga_stat_t asc;
bzero(&asc, sizeof (asc));
asc.board = board;
type = jtag_get_board_type(jreg, &asc);
}
if (!intr)
(void) jtag_init_ac(jreg, board, type);
ring = board << 4;
fhc_opt.csr_hi = 0;
fhc_opt.csr_mid = MOD_OFF | EPDA_OFF | EPDB_OFF | NOT_BRD_PRESENT;
if (intr) {
/*
* by not setting NOT_BRD_PRESENT we can simulate a board
* insertion
*/
fhc_opt.csr_mid &= ~NOT_BRD_PRESENT;
}
fhc_opt.csr_midlo = NOT_BRD_LED_LEFT | BRD_LED_MID;
if ((type == CPU_BOARD) || (type == MEM_BOARD)) {
rc = jtag_init_chip(jreg, ring, &cpu_sysbd_ring_components[9],
(jtag_opt)&fhc_opt, scan_out);
} else if (type == IO_2SBUS_BOARD) {
rc = jtag_init_chip(jreg, ring, &io1_sysbd_ring_components[9],
(jtag_opt)&fhc_opt, scan_out);
} else if (type == IO_2SBUS_SOCPLUS_BOARD) {
rc = jtag_init_chip(jreg, ring,
&io1plus_sysbd_ring_components[9],
(jtag_opt)&fhc_opt, scan_out);
} else if (type == IO_SBUS_FFB_BOARD) {
rc = jtag_init_chip(jreg, ring, &io2_sysbd_ring_components[9],
(jtag_opt)&fhc_opt, scan_out);
} else if (type == IO_SBUS_FFB_SOCPLUS_BOARD) {
rc = jtag_init_chip(jreg, ring,
&io2plus_sysbd_ring_components[9],
(jtag_opt)&fhc_opt, scan_out);
} else if (type == IO_PCI_BOARD) {
rc = jtag_init_chip(jreg, ring, &io3_sysbd_ring_components[9],
(jtag_opt)&fhc_opt, scan_out);
} else if (type == UNKNOWN_BOARD) {
rc = jtag_init_chip(jreg, ring, &cpu_sysbd_ring_components[9],
(jtag_opt)&fhc_opt, scan_out);
} else {
cmn_err(CE_WARN, "Unsupported Board type %2X\n",
fhc_bd_type(board));
}
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
if (rc != JTAG_OK) {
jtag_error_print(ring, rc);
}
/* Reformat the FHC shadow chain scan data */
format_chip_data(chip_fhc.fmt_desc, (u_int *)&fhc_data,
scan_out);
*fhc_csr = fhc_data.csr;
*fhc_bsr = fhc_data.bsr;
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
jtag_init_disk_board(volatile u_int *jreg, int board,
u_int *fhc_csr, u_int *fhc_bsr)
{
int rc = JTAG_OK;
fhc_options fhc_opt;
struct fhc_regs fhc_data;
u_char scan_out[32];
int status;
int ring;
ring = board << 4;
fhc_opt.csr_hi = 0;
fhc_opt.csr_mid = NOT_BRD_PRESENT;
fhc_opt.csr_midlo = NOT_BRD_LED_LEFT | BRD_LED_MID;
rc = jtag_init_chip(jreg, ring, &dsk_sysbd_ring_components[1],
(jtag_opt)&fhc_opt, scan_out);
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
if (rc != JTAG_OK) {
jtag_error_print(ring, rc);
return (-1);
}
/* Reformat the FHC shadow chain scan data */
format_chip_data(chip_fhc.fmt_desc, (u_int *)&fhc_data,
scan_out);
*fhc_csr = fhc_data.csr;
*fhc_bsr = fhc_data.bsr;
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
tap_wait(volatile u_int *jreg)
{
TAP_DECLARE;
TAP_WAIT(jreg);
return (JTAG_OK);
}
/*
* Send a TAP command, wait for completion.
* Return <0 if error, >=0 if OK.
*/
static int
tap_issue_cmd(volatile u_int *jreg, u_int command)
{
TAP_DECLARE;
*jreg = command;
TAP_WAIT(jreg);
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
tap_shift_single(volatile u_int *jreg, int data, int nbits)
{
/* Return <0 if error, >0 (16-bit data) if OK */
TAP_DECLARE;
TAP_SHIFT(jreg, data, nbits);
return (jtag_data(jreg, nbits));
}
/*
* Shift the required number of bits from in into the component,
* retrieve the bits shifted out.
* Return <0 if error, >=0 if OK.
*/
int
tap_shift_multiple(
volatile u_int *jreg,
u_char *data_in,
int nbits,
u_char *data_out) /* data_out may be NULL if not needed */
{
TAP_DECLARE;
/*
* The loop is done a byte at a time to avoid stepping out
* of the caller's buffer
*/
for (; nbits > 0; nbits = nbits - 8) {
int bits_this_pass = nbits > 8 ? 8 : nbits;
TAP_SHIFT(jreg, *data_in++, bits_this_pass);
if (data_out != NULL) {
*data_out = jtag_data(jreg, bits_this_pass);
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
tap_shift_constant(volatile u_int *jreg, int value, int nbits)
{
TAP_DECLARE;
TAP_WAIT(jreg);
/*
* The loop is done a half-word at a time
*/
for (; nbits > 0; nbits = nbits - 16) {
int bits_this_pass = nbits > 16 ? 16 : nbits;
TAP_SHIFT(jreg, value, bits_this_pass);
}
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
select_ring(volatile u_int *jreg, jtag_ring ring, int reset)
{
int status;
jtag_ring jring;
status = tap_wait(jreg);
if (status < 0) {
return (status);
}
/* Translate a Physical Board number to a JTAG board number */
jring = ((u_int)(ring & 0x10) << 3) | ((u_int)(ring & 0xE0) >> 1) |
(ring & 0xF);
status = tap_issue_cmd(jreg, (jring << 16) | JTAG_SEL_RING);
if (status < 0) {
return (status);
}
if (reset != 0) {
status = tap_issue_cmd(jreg, JTAG_TAP_RESET);
}
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
jtag_single_IR_DR(
volatile u_int *jreg,
jtag_phys_comp *component,
jtag_instruction instr,
u_char *in,
int nbits,
u_char *out)
{
int status;
TAP_ISSUE_CMD(jreg, JTAG_SEL_IR, status);
TAP_SHIFT_CONSTANT(jreg, -1, component->ir_after, status);
TAP_SHIFT_SINGLE(jreg, instr, component->chip->ir_len, status);
TAP_SHIFT_CONSTANT(jreg, -1, component->ir_before, status);
TAP_ISSUE_CMD(jreg, JTAG_IR_TO_DR, status);
TAP_SHIFT_CONSTANT(jreg, 0, component->by_after, status);
TAP_SHIFT_MULTIPLE(jreg, in, nbits, out, status);
TAP_SHIFT_CONSTANT(jreg, 0, component->by_before, status);
TAP_ISSUE_CMD(jreg, JTAG_RUNIDLE, 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
jtag_rescan_IR_DR(
volatile u_int *jreg,
jtag_phys_comp *component,
jtag_instruction instr,
u_char *in,
int nbits,
u_char *out)
{
int status, i;
u_char tmp[32];
for (i = 0; i < 32; i++)
tmp[i] = 0;
TAP_ISSUE_CMD(jreg, JTAG_SEL_IR, status);
TAP_SHIFT_CONSTANT(jreg, -1, component->ir_after, status);
TAP_SHIFT_SINGLE(jreg, instr, component->chip->ir_len, status);
TAP_SHIFT_CONSTANT(jreg, -1, component->ir_before, status);
TAP_ISSUE_CMD(jreg, JTAG_IR_TO_DR, status);
/* scan the chip out */
TAP_SHIFT_CONSTANT(jreg, 0, component->by_after, status);
TAP_SHIFT_MULTIPLE(jreg, tmp, nbits, out, status);
TAP_SHIFT_CONSTANT(jreg, 0, component->by_before, status);
/* re scan the chip */
TAP_SHIFT_CONSTANT(jreg, 0, component->by_after, status);
TAP_SHIFT_MULTIPLE(jreg, out, nbits, tmp, status);
TAP_SHIFT_CONSTANT(jreg, 0, component->by_before, status);
TAP_ISSUE_CMD(jreg, JTAG_RUNIDLE, status);
return (status);
}
/*
* Return the number of components of the current ring, or <0 if failed
*/
static int
jtag_ring_length(volatile u_int *jreg, jtag_ring ring)
{
int status, length;
/*
* 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
*/
status = select_ring(jreg, ring, 1);
if (status < 0) {
cmn_err(CE_WARN, "select ring error jtag status %x\n",
status);
return (status);
}
TAP_ISSUE_CMD(jreg, JTAG_SEL_DR, status);
TAP_SHIFT_SINGLE(jreg, -1, 8, 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!
*/
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
TAP_ISSUE_CMD(jreg, JTAG_SEL_IR, status);
TAP_SHIFT_CONSTANT(jreg, -1, 32*16, status);
TAP_ISSUE_CMD(jreg, JTAG_IR_TO_DR, status);
TAP_SHIFT_CONSTANT(jreg, 0, 32, status);
for (length = 0; length <= 33; length++) { /* bit by bit */
TAP_SHIFT_SINGLE(jreg, -1, 1, status);
if (status != 0) {
break;
}
}
TAP_ISSUE_CMD(jreg, JTAG_RUNIDLE, status);
/* more than 32 components ??? */
return ((length <= 32) ? length : RING_BROKEN);
}
/*
* Return the total number of instruction register bits in the
* current ring, or < 0 if failed.
*/
int
jtag_ring_ir_length(volatile u_int *jreg, jtag_ring ring)
{
int status, length;
/*
* 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
*/
status = select_ring(jreg, ring, 1);
if (status < 0) {
cmn_err(CE_WARN, "select error status %x", status);
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
*/
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
TAP_ISSUE_CMD(jreg, JTAG_SEL_IR, status);
/* 1 fill, look for 0 */
TAP_SHIFT_CONSTANT(jreg, -1, 32 * 16, status);
for (length = 0; length <= 32 * 16; length++) { /* bit by bit */
TAP_SHIFT_SINGLE(jreg, 0, 1, status);
if (status == 0)
break;
}
/* bypass should be safe */
TAP_SHIFT_CONSTANT(jreg, -1, 32 * 16, status);
TAP_ISSUE_CMD(jreg, JTAG_RUNIDLE, status);
/* more than 32*16 ir bits ??? */
return ((length <= 32 * 16) ? length : RING_BROKEN);
}
/*
* 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
format_chip_data(u_char *fmt, u_int *datap, u_char *scan_out)
{
u_int value;
for (value = 0; ; ) {
u_char cmd = *fmt++;
if ((cmd & JTSO_XTRACT) != 0) {
u_int lsb, msb;
lsb = *fmt++;
msb = *fmt++;
value |= jtag_bf_extract(scan_out, lsb, msb) <<
(cmd & JTSO_SHIFT);
}
if ((cmd & JTSO_ST) != 0) {
*datap++ = value;
value = 0;
}
if ((cmd & JTSO_END) != 0) {
break;
}
}
}