#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>
#define JTAG_CSR_BASE ((jtag_csr *)0xF0300000)
#define JTAG_CR 0x08000f0
#define JTAG_CMD 0x0800100
#define JTAG_BUSY_BIT 0x100
#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
#define PRINT_JTAG_ERR 5
#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
#define RING0 0
#define RING1 1
#define RING2 2
#define CPU_TYPE_LEN 12
#define IO_TYPE1_LEN 15
#define IO_TYPE2_LEN 14
#define PCI_TYPE_LEN 16
#define PCI_TYPEA_LEN 110
#define PCI_TYPEB_LEN 104
#define DSK_TYPE_LEN 2
#define IO_TYPE4_LEN 126
#define IO_TYPE5_LEN 110
#define CPU_0_5_LEN 8
#define CPU_1_0_LEN 12
#define FFB_SNG_LEN 6
#define FFB_DBL_LEN 18
#define SRAM_256K 0x00000000
#define SRAM_128K 0x000090E3
#define SRAM_64K_1 0x000000E3
#define SRAM_64K_2 0x01901149
typedef enum {
JTAG_OK = 0,
JTAG_FAIL = -1,
TAP_TIMEOUT = -1,
BAD_ARGS = -2,
BAD_CID = -3,
RING_BROKEN = -4,
INIT_MISMATCH = -5,
LENGTH_MISMATCH = -6
} jtag_error;
typedef u_short jtag_instruction;
typedef u_char jtag_ring;
static int tap_issue_cmd(volatile u_int *, u_int);
#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)
#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)
typedef struct {
u_int *id;
u_char ir_len;
u_char dr_len;
jtag_instruction id_code;
jtag_instruction init_code;
jtag_instruction dump_code;
u_char *init_pdesc;
u_char *fmt_desc;
} jtag_log_comp;
typedef struct {
jtag_log_comp *chip;
short ir_after;
short ir_before;
short by_after;
short by_before;
} jtag_phys_comp;
typedef struct {
int size;
jtag_phys_comp *components;
} jtag_ring_desc;
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;
u_int csr_mid;
u_int csr_midlo;
} fhc_options;
struct fhc_regs {
u_int por;
u_int csr;
u_int rcsr;
u_int bsr;
};
struct bct_fields {
u_int disk1_pres;
u_int disk0_pres;
u_int disk1_id;
u_int disk0_id;
};
typedef u_int *jtag_opt;
#define JTIN_INDEX 0x0F
#define JTIN_INSERT 0x10
#define JTIN_UPDATE 0x20
#define JTIN_COMPARE 0x40
#define JTIN_END 0x80
#define JTSO_END 0x80
#define JTSO_XTRACT 0x40
#define JTSO_ST 0x20
#define JTSO_SHIFT 0x1F
static void jtag_error_print(int, jtag_error);
static int jtag_get_comp_id(volatile u_int *, jtag_phys_comp *);
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);
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 *);
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);
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);
static char jtag_err[] = "JTAG ERROR";
#define IR_LEN 8
#define HM_LEN 4
#define NDP_LEN 2
#define SOC_LEN 4
#define SOCPLUS_LEN 8
#define SIO_LEN 16
#define PSYO_LEN 4
#define CHEO_LEN 4
#define EC_LEN 3
#define FFB_LEN 16
#define THREED_LEN 4
#define BT498_LEN 4
#define IDCODE 0xFFFE
#define INITCODE 0xbe
#define DUMPCODE 0xbe
#define CID_TO_REV(cid) ((cid) >> 28)
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
};
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
};
static u_char dc_init_pdesc[] = {
JTIN_INSERT|1, 0, 0,
JTIN_INSERT|2, 4, 4,
JTIN_INSERT|3, 3, 3,
JTIN_INSERT|0, 1, 2, 3,
JTIN_END|JTIN_UPDATE,
};
static u_char dc_fmt[] = {
JTSO_ST|JTSO_XTRACT|JTSO_END| 0, 0, 4
};
static u_char ac_init_pdesc[] = {
JTIN_INSERT|0, 161, 161, 1,
JTIN_INSERT|7, 159, 160,
JTIN_INSERT|4, 155, 158,
JTIN_INSERT|4, 151, 154,
JTIN_INSERT|6, 146, 146,
JTIN_INSERT|1, 134, 134,
JTIN_INSERT|0, 133, 133, 0,
JTIN_INSERT|2, 135, 135,
JTIN_INSERT|3, 136, 136,
JTIN_INSERT|0, 99, 106, 0xff,
JTIN_INSERT|0, 107, 114, 0xff,
JTIN_INSERT|0, 115, 122, 0xff,
JTIN_INSERT|0, 123, 130, 0xff,
JTIN_INSERT|0, 131, 132, 0xff,
JTIN_INSERT|5, 88, 98,
JTIN_INSERT|12, 76, 87,
JTIN_INSERT|10, 70, 75,
JTIN_INSERT|11, 64, 69,
JTIN_INSERT|8, 32, 63,
JTIN_INSERT|9, 0, 31,
JTIN_END|JTIN_UPDATE,
};
static u_char ac_fmt[] = {
JTSO_XTRACT|17, 148, 162,
JTSO_XTRACT|15, 147, 147,
JTSO_XTRACT|5, 138, 146,
JTSO_ST|JTSO_XTRACT|0, 134, 137,
JTSO_ST|JTSO_XTRACT|22, 133, 133,
JTSO_XTRACT|16, 131, 132,
JTSO_XTRACT|8, 124, 130,
JTSO_XTRACT|4, 122, 123,
JTSO_ST|JTSO_XTRACT|0, 120, 121,
JTSO_XTRACT|28, 116, 119,
JTSO_XTRACT|24, 115, 115,
JTSO_XTRACT|20, 112, 114,
JTSO_XTRACT|12, 107, 111,
JTSO_XTRACT|4, 101, 106,
JTSO_ST|JTSO_XTRACT|0, 99, 100,
JTSO_XTRACT|16, 97, 98,
JTSO_XTRACT|8, 96, 96,
JTSO_ST|JTSO_XTRACT|4, 94, 95,
JTSO_XTRACT|28, 93, 93,
JTSO_XTRACT|24, 92, 92,
JTSO_XTRACT|20, 91, 91,
JTSO_XTRACT|12, 90, 90,
JTSO_XTRACT|8, 89, 89,
JTSO_ST|JTSO_XTRACT|4, 88, 88,
JTSO_XTRACT|16, 76, 87,
JTSO_XTRACT|8, 70, 75,
JTSO_ST|JTSO_XTRACT|0, 64, 69,
JTSO_ST|JTSO_XTRACT|0, 32, 63,
JTSO_ST|JTSO_XTRACT|JTSO_END|0, 0, 31
};
static u_char fhc_init_pdesc[] = {
JTIN_INSERT|0, 41, 41, 0,
JTIN_INSERT|1, 38, 40,
JTIN_INSERT|2, 29, 37,
JTIN_INSERT|3, 26, 28,
JTIN_INSERT|0, 24, 25, 0x0,
JTIN_INSERT|0, 16, 23, 0x0,
JTIN_INSERT|0, 2, 15, 0x0,
JTIN_INSERT|0, 0, 1, 0x0,
JTIN_END|JTIN_UPDATE,
};
static u_char fhc_fmt[] = {
JTSO_ST|JTSO_XTRACT|0, 41, 41,
JTSO_XTRACT|18, 38, 40,
JTSO_XTRACT|8, 29, 37,
JTSO_XTRACT|4, 26, 28,
JTSO_ST|JTSO_XTRACT|0, 24, 25,
JTSO_ST|JTSO_XTRACT|24, 16, 23,
JTSO_XTRACT|5, 2, 15,
JTSO_ST|JTSO_XTRACT|JTSO_END|0, 0, 1,
};
static u_char bct8244_fmt[] = {
JTSO_ST|JTSO_XTRACT|0, 17, 17,
JTSO_ST|JTSO_XTRACT|0, 16, 16,
JTSO_ST|JTSO_XTRACT|0, 12, 15,
JTSO_ST|JTSO_XTRACT|JTSO_END|0, 8, 11,
};
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
};
static jtag_phys_comp cpu_sysbd_ring_components[] = {
{ &chip_ac, 11*IR_LEN, 0, 11, 0 },
{ &chip_dc, 10*IR_LEN, 1*IR_LEN, 10, 1 },
{ &chip_dc, 9*IR_LEN, 2*IR_LEN, 9, 2 },
{ &chip_dc, 8*IR_LEN, 3*IR_LEN, 8, 3 },
{ &chip_dc, 7*IR_LEN, 4*IR_LEN, 7, 4 },
{ &chip_dc, 6*IR_LEN, 5*IR_LEN, 6, 5 },
{ &chip_dc, 5*IR_LEN, 6*IR_LEN, 5, 6 },
{ &chip_dc, 4*IR_LEN, 7*IR_LEN, 4, 7 },
{ &chip_dc, 3*IR_LEN, 8*IR_LEN, 3, 8 },
{ &chip_fhc, 2*IR_LEN, 9*IR_LEN, 2, 9 },
{ &chip_ec, 1*IR_LEN, 10*IR_LEN, 1, 10 },
{ &chip_ec, 0*IR_LEN, 11*IR_LEN, 0, 11 },
};
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 },
{ &chip_ec, 40, 8, 10, 1 },
{ &chip_ec, 37, 11, 9, 2 },
{ &chip_ec, 34, 14, 8, 3 },
{ &chip_ec, 31, 17, 7, 4 },
{ &chip_ec, 28, 20, 6, 5 },
{ &chip_ec, 25, 23, 5, 6 },
{ &chip_ec, 22, 26, 4, 7 },
{ &chip_ec, 19, 29, 3, 8 },
{ &chip_ec, 16, 32, 2, 9 },
{ &chip_sdb, 8, 35, 1, 10 },
{ &chip_sdb, 0, 43, 0, 11 },
};
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 },
{ &chip_ec, 28, 8, 6, 1 },
{ &chip_ec, 25, 11, 5, 2 },
{ &chip_ec, 22, 14, 4, 3 },
{ &chip_ec, 19, 17, 3, 4 },
{ &chip_ec, 16, 20, 2, 5 },
{ &chip_sdb, 8, 23, 1, 6 },
{ &chip_sdb, 0, 31, 0, 7 },
};
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 },
{ &chip_dc, 106, 8, 13, 1 },
{ &chip_dc, 98, 16, 12, 2 },
{ &chip_dc, 90, 24, 11, 3 },
{ &chip_dc, 82, 32, 10, 4 },
{ &chip_dc, 74, 40, 9, 5 },
{ &chip_dc, 66, 48, 8, 6 },
{ &chip_dc, 58, 56, 7, 7 },
{ &chip_dc, 50, 64, 6, 8 },
{ &chip_fhc, 42, 72, 5, 9 },
{ &chip_sio, 26, 80, 4, 10 },
{ &chip_sio, 10, 96, 3, 11 },
{ &chip_hm, 6, 112, 2, 12 },
{ &chip_ndp, 4, 116, 1, 13 },
{ &chip_soc, 0, 118, 0, 14 },
};
static jtag_phys_comp io2_sysbd_ring_components[] = {
{ &chip_ac, 98, 0, 13, 0 },
{ &chip_dc, 90, 8, 12, 1 },
{ &chip_dc, 82, 16, 11, 2 },
{ &chip_dc, 74, 24, 10, 3 },
{ &chip_dc, 66, 32, 9, 4 },
{ &chip_dc, 58, 40, 8, 5 },
{ &chip_dc, 50, 48, 7, 6 },
{ &chip_dc, 42, 56, 6, 7 },
{ &chip_dc, 34, 64, 5, 8 },
{ &chip_fhc, 26, 72, 4, 9 },
{ &chip_sio, 10, 80, 3, 10 },
{ &chip_hm, 6, 96, 2, 11 },
{ &chip_ndp, 4, 100, 1, 12 },
{ &chip_soc, 0, 102, 0, 13 },
};
static jtag_phys_comp io1plus_sysbd_ring_components[] = {
{ &chip_ac, 118, 0, 14, 0 },
{ &chip_dc, 110, 8, 13, 1 },
{ &chip_dc, 102, 16, 12, 2 },
{ &chip_dc, 94, 24, 11, 3 },
{ &chip_dc, 86, 32, 10, 4 },
{ &chip_dc, 78, 40, 9, 5 },
{ &chip_dc, 70, 48, 8, 6 },
{ &chip_dc, 62, 56, 7, 7 },
{ &chip_dc, 54, 64, 6, 8 },
{ &chip_fhc, 46, 72, 5, 9 },
{ &chip_sio, 30, 80, 4, 10 },
{ &chip_sio, 14, 96, 3, 11 },
{ &chip_hm, 10, 112, 2, 12 },
{ &chip_ndp, 8, 116, 1, 13 },
{ &chip_socplus, 0, 118, 0, 14 },
};
static jtag_phys_comp io2plus_sysbd_ring_components[] = {
{ &chip_ac, 102, 0, 13, 0 },
{ &chip_dc, 94, 8, 12, 1 },
{ &chip_dc, 86, 16, 11, 2 },
{ &chip_dc, 78, 24, 10, 3 },
{ &chip_dc, 70, 32, 9, 4 },
{ &chip_dc, 62, 40, 8, 5 },
{ &chip_dc, 54, 48, 7, 6 },
{ &chip_dc, 46, 56, 6, 7 },
{ &chip_dc, 38, 64, 5, 8 },
{ &chip_fhc, 30, 72, 4, 9 },
{ &chip_sio, 14, 80, 3, 10 },
{ &chip_hm, 10, 96, 2, 11 },
{ &chip_ndp, 8, 100, 1, 12 },
{ &chip_socplus, 0, 102, 0, 13 },
};
static jtag_phys_comp io3_sysbd_ring_components[] = {
{ &chip_ac, 102, 0, 15, 0 },
{ &chip_dc, 94, 8, 14, 1 },
{ &chip_dc, 86, 16, 13, 2 },
{ &chip_dc, 78, 24, 12, 3 },
{ &chip_dc, 70, 32, 11, 4 },
{ &chip_dc, 62, 40, 10, 5 },
{ &chip_dc, 54, 48, 9, 6 },
{ &chip_dc, 46, 56, 8, 7 },
{ &chip_dc, 38, 64, 7, 8 },
{ &chip_fhc, 30, 72, 6, 9 },
{ &chip_psyo, 26, 80, 5, 10 },
{ &chip_cheo, 22, 84, 4, 11 },
{ &chip_ndp, 20, 88, 3, 12 },
{ &chip_psyo, 16, 90, 2, 13 },
{ &chip_bct8244, 8, 94, 1, 14 },
{ &chip_bct8244, 0, 102, 0, 15 },
};
static jtag_phys_comp dsk_sysbd_ring_components[] = {
{ &chip_bct8244, 8, 0, 1, 0 },
{ &chip_fhc, 0, 8, 0, 1 },
};
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
};
static jtag_phys_comp ffb_sngl_ring_components[] = {
{ &chip_fbc, 20, 0, 5, 0 },
{ &chip_3dram, 16, 16, 4, 1 },
{ &chip_3dram, 12, 20, 3, 2 },
{ &chip_3dram, 8, 24, 2, 3 },
{ &chip_3dram, 4, 28, 1, 4 },
{ &chip_bt498, 0, 32, 0, 5 },
};
static jtag_phys_comp ffb_dbl_ring_components[] = {
{ &chip_fbc, 84, 0, 17, 0 },
{ &chip_lvt, 76, 16, 16, 1 },
{ &chip_lvt, 68, 24, 15, 2 },
{ &chip_lvt, 60, 32, 14, 3 },
{ &chip_lvt, 52, 40, 13, 4 },
{ &chip_3dram, 48, 48, 12, 5 },
{ &chip_3dram, 44, 52, 11, 6 },
{ &chip_3dram, 40, 56, 10, 7 },
{ &chip_3dram, 36, 60, 9, 8 },
{ &chip_3dram, 32, 64, 8, 9 },
{ &chip_3dram, 28, 68, 7, 10 },
{ &chip_3dram, 24, 72, 6, 11 },
{ &chip_3dram, 20, 76, 5, 12 },
{ &chip_3dram, 16, 80, 4, 13 },
{ &chip_3dram, 12, 84, 3, 14 },
{ &chip_3dram, 8, 88, 2, 15 },
{ &chip_3dram, 4, 92, 1, 16 },
{ &chip_bt498, 0, 96, 0, 17 },
};
static jtag_ring_desc ffb_sngl_ring = {
6, ffb_sngl_ring_components
};
static jtag_ring_desc ffb_dbl_ring = {
18, ffb_dbl_ring_components
};
static jtag_ring_desc *cpu_system_board[] = {
&cpu_sysbd_ring,
&cpu_mod_ring,
&cpu_mod_ring,
};
static jtag_ring_desc *io1_system_board[] = {
&io1_sysbd_ring,
(jtag_ring_desc *) NULL,
(jtag_ring_desc *) NULL,
};
static jtag_ring_desc *io1plus_system_board[] = {
&io1plus_sysbd_ring,
(jtag_ring_desc *) NULL,
(jtag_ring_desc *) NULL,
};
static jtag_ring_desc *io2_system_board[] = {
&io2_sysbd_ring,
(jtag_ring_desc *) NULL,
(jtag_ring_desc *) NULL,
};
static jtag_ring_desc *io2plus_system_board[] = {
&io2plus_sysbd_ring,
(jtag_ring_desc *) NULL,
(jtag_ring_desc *) NULL,
};
static jtag_ring_desc *io3_system_board[] = {
&io3_sysbd_ring,
(jtag_ring_desc *) NULL,
(jtag_ring_desc *) NULL,
};
static jtag_ring_desc *disk_system_board[] = {
&dsk_sysbd_ring,
(jtag_ring_desc *) NULL,
(jtag_ring_desc *) NULL,
};
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;
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;
}
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;
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 = EMPTY_BOARD;
break;
default:
result = UNKNOWN_BOARD;
break;
}
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
return (result);
}
#ifndef RFE_4174486
static int jtag_cpu_scan_enable = 0;
#endif
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;
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);
}
rc = find_chip(rd, &chip_ac, 0);
if (rc != NULL) {
sc->ac_compid = jtag_get_comp_id(jreg, rc);
}
rc = find_chip(rd, &chip_fhc, 0);
if (rc != NULL) {
sc->fhc_compid = jtag_get_comp_id(jreg, rc);
}
switch (sc->type) {
case CPU_BOARD:
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
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);
}
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
switch (len) {
case CPU_0_5_LEN:
cpu->cache_size = 0x80000;
break;
case CPU_1_0_LEN:
cpu->cache_size = 0x100000;
break;
default:
break;
}
#endif
}
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);
}
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;
}
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);
}
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;
}
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:
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);
}
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;
}
}
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);
id = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
if (status < 0) {
return (0);
} else {
return (id);
}
}
static u_int
jtag_bf_extract(u_char *s, int lsb, int msb)
{
u_int result = 0;
ASSERT(s);
for (; msb >= lsb; msb--) {
result = (result << 1) | ((s[msb>>3] >> (msb & 7)) & 1);
}
return (result);
}
static void
jtag_bf_insert(u_char *s, int lsb, int msb, int value)
{
ASSERT(s);
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;
}
}
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);
}
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;
chip = component->chip;
pdesc = chip->init_pdesc;
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);
}
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);
}
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;
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;
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);
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
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) {
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);
}
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);
}
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);
}
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);
}
int
tap_wait(volatile u_int *jreg)
{
TAP_DECLARE;
TAP_WAIT(jreg);
return (JTAG_OK);
}
static int
tap_issue_cmd(volatile u_int *jreg, u_int command)
{
TAP_DECLARE;
*jreg = command;
TAP_WAIT(jreg);
return (JTAG_OK);
}
int
tap_shift_single(volatile u_int *jreg, int data, int nbits)
{
TAP_DECLARE;
TAP_SHIFT(jreg, data, nbits);
return (jtag_data(jreg, nbits));
}
int
tap_shift_multiple(
volatile u_int *jreg,
u_char *data_in,
int nbits,
u_char *data_out)
{
TAP_DECLARE;
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);
}
static int
tap_shift_constant(volatile u_int *jreg, int value, int nbits)
{
TAP_DECLARE;
TAP_WAIT(jreg);
for (; nbits > 0; nbits = nbits - 16) {
int bits_this_pass = nbits > 16 ? 16 : nbits;
TAP_SHIFT(jreg, value, bits_this_pass);
}
return (JTAG_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);
}
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);
}
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);
}
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);
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);
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);
}
static int
jtag_ring_length(volatile u_int *jreg, jtag_ring ring)
{
int status, length;
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);
}
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++) {
TAP_SHIFT_SINGLE(jreg, -1, 1, status);
if (status != 0) {
break;
}
}
TAP_ISSUE_CMD(jreg, JTAG_RUNIDLE, status);
return ((length <= 32) ? length : RING_BROKEN);
}
int
jtag_ring_ir_length(volatile u_int *jreg, jtag_ring ring)
{
int status, length;
status = select_ring(jreg, ring, 1);
if (status < 0) {
cmn_err(CE_WARN, "select error status %x", status);
return (status);
}
TAP_ISSUE_CMD(jreg, JTAG_TAP_RESET, status);
TAP_ISSUE_CMD(jreg, JTAG_SEL_IR, status);
TAP_SHIFT_CONSTANT(jreg, -1, 32 * 16, status);
for (length = 0; length <= 32 * 16; length++) {
TAP_SHIFT_SINGLE(jreg, 0, 1, status);
if (status == 0)
break;
}
TAP_SHIFT_CONSTANT(jreg, -1, 32 * 16, status);
TAP_ISSUE_CMD(jreg, JTAG_RUNIDLE, status);
return ((length <= 32 * 16) ? length : RING_BROKEN);
}
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;
}
}
}