17532SSean.Ye@Sun.COM /*
27532SSean.Ye@Sun.COM * CDDL HEADER START
37532SSean.Ye@Sun.COM *
47532SSean.Ye@Sun.COM * The contents of this file are subject to the terms of the
57532SSean.Ye@Sun.COM * Common Development and Distribution License (the "License").
67532SSean.Ye@Sun.COM * You may not use this file except in compliance with the License.
77532SSean.Ye@Sun.COM *
87532SSean.Ye@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97532SSean.Ye@Sun.COM * or http://www.opensolaris.org/os/licensing.
107532SSean.Ye@Sun.COM * See the License for the specific language governing permissions
117532SSean.Ye@Sun.COM * and limitations under the License.
127532SSean.Ye@Sun.COM *
137532SSean.Ye@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147532SSean.Ye@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157532SSean.Ye@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167532SSean.Ye@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177532SSean.Ye@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187532SSean.Ye@Sun.COM *
197532SSean.Ye@Sun.COM * CDDL HEADER END
207532SSean.Ye@Sun.COM */
217532SSean.Ye@Sun.COM
227532SSean.Ye@Sun.COM /*
23*12726SJakub.Jermar@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
247532SSean.Ye@Sun.COM */
257532SSean.Ye@Sun.COM
267532SSean.Ye@Sun.COM #include <sys/types.h>
277532SSean.Ye@Sun.COM #include <sys/cmn_err.h>
287532SSean.Ye@Sun.COM #include <sys/errno.h>
297532SSean.Ye@Sun.COM #include <sys/log.h>
307532SSean.Ye@Sun.COM #include <sys/systm.h>
317532SSean.Ye@Sun.COM #include <sys/modctl.h>
327532SSean.Ye@Sun.COM #include <sys/errorq.h>
337532SSean.Ye@Sun.COM #include <sys/controlregs.h>
347532SSean.Ye@Sun.COM #include <sys/fm/util.h>
357532SSean.Ye@Sun.COM #include <sys/fm/protocol.h>
367532SSean.Ye@Sun.COM #include <sys/sysevent.h>
377532SSean.Ye@Sun.COM #include <sys/pghw.h>
387532SSean.Ye@Sun.COM #include <sys/cyclic.h>
397532SSean.Ye@Sun.COM #include <sys/pci_cfgspace.h>
407532SSean.Ye@Sun.COM #include <sys/mc_intel.h>
417532SSean.Ye@Sun.COM #include <sys/smbios.h>
427532SSean.Ye@Sun.COM #include <sys/pci.h>
437532SSean.Ye@Sun.COM #include <sys/pcie.h>
447532SSean.Ye@Sun.COM #include "nb5000.h"
457532SSean.Ye@Sun.COM #include "nb_log.h"
467532SSean.Ye@Sun.COM #include "dimm_phys.h"
477532SSean.Ye@Sun.COM #include "rank.h"
487532SSean.Ye@Sun.COM
497532SSean.Ye@Sun.COM int nb_hw_memory_scrub_enable = 1;
507532SSean.Ye@Sun.COM static int nb_sw_scrub_disabled = 0;
517532SSean.Ye@Sun.COM
527532SSean.Ye@Sun.COM int nb_5000_memory_controller = 0;
537532SSean.Ye@Sun.COM int nb_number_memory_controllers = NB_5000_MAX_MEM_CONTROLLERS;
5410049SVuong.Nguyen@Sun.COM int nb_channels_per_branch = NB_MAX_CHANNELS_PER_BRANCH;
557532SSean.Ye@Sun.COM int nb_dimms_per_channel = 0;
567532SSean.Ye@Sun.COM
577532SSean.Ye@Sun.COM nb_dimm_t **nb_dimms;
587532SSean.Ye@Sun.COM int nb_ndimm;
597532SSean.Ye@Sun.COM uint32_t nb_chipset;
607532SSean.Ye@Sun.COM enum nb_memory_mode nb_mode;
617532SSean.Ye@Sun.COM bank_select_t nb_banks[NB_MAX_MEM_BRANCH_SELECT];
627532SSean.Ye@Sun.COM rank_select_t nb_ranks[NB_5000_MAX_MEM_CONTROLLERS][NB_MAX_MEM_RANK_SELECT];
637532SSean.Ye@Sun.COM uint32_t top_of_low_memory;
647532SSean.Ye@Sun.COM uint8_t spare_rank[NB_5000_MAX_MEM_CONTROLLERS];
657532SSean.Ye@Sun.COM
668037SAdrian.Frost@Sun.COM extern int nb_no_smbios;
678037SAdrian.Frost@Sun.COM
687532SSean.Ye@Sun.COM errorq_t *nb_queue;
697532SSean.Ye@Sun.COM kmutex_t nb_mutex;
707532SSean.Ye@Sun.COM
718037SAdrian.Frost@Sun.COM static int nb_dimm_slots;
728037SAdrian.Frost@Sun.COM
739783SAdrian.Frost@Sun.COM static uint32_t nb_err0_int;
749783SAdrian.Frost@Sun.COM static uint32_t nb_err1_int;
759783SAdrian.Frost@Sun.COM static uint32_t nb_err2_int;
769783SAdrian.Frost@Sun.COM static uint32_t nb_mcerr_int;
777532SSean.Ye@Sun.COM static uint32_t nb_emask_int;
787532SSean.Ye@Sun.COM
797532SSean.Ye@Sun.COM static uint32_t nb_err0_fbd;
807532SSean.Ye@Sun.COM static uint32_t nb_err1_fbd;
817532SSean.Ye@Sun.COM static uint32_t nb_err2_fbd;
827532SSean.Ye@Sun.COM static uint32_t nb_mcerr_fbd;
837532SSean.Ye@Sun.COM static uint32_t nb_emask_fbd;
847532SSean.Ye@Sun.COM
8510049SVuong.Nguyen@Sun.COM static uint32_t nb_err0_mem;
8610049SVuong.Nguyen@Sun.COM static uint32_t nb_err1_mem;
8710049SVuong.Nguyen@Sun.COM static uint32_t nb_err2_mem;
8810049SVuong.Nguyen@Sun.COM static uint32_t nb_mcerr_mem;
8910049SVuong.Nguyen@Sun.COM static uint32_t nb_emask_mem;
9010049SVuong.Nguyen@Sun.COM
917532SSean.Ye@Sun.COM static uint16_t nb_err0_fsb;
927532SSean.Ye@Sun.COM static uint16_t nb_err1_fsb;
937532SSean.Ye@Sun.COM static uint16_t nb_err2_fsb;
947532SSean.Ye@Sun.COM static uint16_t nb_mcerr_fsb;
957532SSean.Ye@Sun.COM static uint16_t nb_emask_fsb;
967532SSean.Ye@Sun.COM
977532SSean.Ye@Sun.COM static uint16_t nb_err0_thr;
987532SSean.Ye@Sun.COM static uint16_t nb_err1_thr;
997532SSean.Ye@Sun.COM static uint16_t nb_err2_thr;
1007532SSean.Ye@Sun.COM static uint16_t nb_mcerr_thr;
1017532SSean.Ye@Sun.COM static uint16_t nb_emask_thr;
1027532SSean.Ye@Sun.COM
1037532SSean.Ye@Sun.COM static uint32_t emask_uncor_pex[NB_PCI_DEV];
1047532SSean.Ye@Sun.COM static uint32_t emask_cor_pex[NB_PCI_DEV];
1057532SSean.Ye@Sun.COM static uint32_t emask_rp_pex[NB_PCI_DEV];
1067532SSean.Ye@Sun.COM static uint32_t docmd_pex[NB_PCI_DEV];
1077532SSean.Ye@Sun.COM static uint32_t uncerrsev[NB_PCI_DEV];
1087532SSean.Ye@Sun.COM
1099783SAdrian.Frost@Sun.COM static uint32_t l_mcerr_int;
1107532SSean.Ye@Sun.COM static uint32_t l_mcerr_fbd;
11110049SVuong.Nguyen@Sun.COM static uint32_t l_mcerr_mem;
1127532SSean.Ye@Sun.COM static uint16_t l_mcerr_fsb;
1137532SSean.Ye@Sun.COM static uint16_t l_mcerr_thr;
1147532SSean.Ye@Sun.COM
1157532SSean.Ye@Sun.COM uint_t nb5000_emask_fbd = EMASK_5000_FBD_RES;
1167532SSean.Ye@Sun.COM uint_t nb5400_emask_fbd = 0;
1177532SSean.Ye@Sun.COM int nb5000_reset_emask_fbd = 1;
1187532SSean.Ye@Sun.COM uint_t nb5000_mask_poll_fbd = EMASK_FBD_NF;
1197532SSean.Ye@Sun.COM uint_t nb5000_mask_bios_fbd = EMASK_FBD_FATAL;
1207532SSean.Ye@Sun.COM uint_t nb5400_mask_poll_fbd = EMASK_5400_FBD_NF;
1217532SSean.Ye@Sun.COM uint_t nb5400_mask_bios_fbd = EMASK_5400_FBD_FATAL;
12210668SVuong.Nguyen@Sun.COM uint_t nb7300_mask_poll_fbd = EMASK_7300_FBD_NF;
12310668SVuong.Nguyen@Sun.COM uint_t nb7300_mask_bios_fbd = EMASK_7300_FBD_FATAL;
1247532SSean.Ye@Sun.COM
12510049SVuong.Nguyen@Sun.COM int nb5100_reset_emask_mem = 1;
12610049SVuong.Nguyen@Sun.COM uint_t nb5100_mask_poll_mem = EMASK_MEM_NF;
12710049SVuong.Nguyen@Sun.COM
1287532SSean.Ye@Sun.COM uint_t nb5000_emask_fsb = 0;
1297532SSean.Ye@Sun.COM int nb5000_reset_emask_fsb = 1;
1307532SSean.Ye@Sun.COM uint_t nb5000_mask_poll_fsb = EMASK_FSB_NF;
1317532SSean.Ye@Sun.COM uint_t nb5000_mask_bios_fsb = EMASK_FSB_FATAL;
1327532SSean.Ye@Sun.COM
13310668SVuong.Nguyen@Sun.COM uint_t nb5100_emask_int = EMASK_INT_5100;
1349783SAdrian.Frost@Sun.COM uint_t nb5400_emask_int = EMASK_INT_5400;
1357532SSean.Ye@Sun.COM
1367532SSean.Ye@Sun.COM uint_t nb7300_emask_int = EMASK_INT_7300;
1377532SSean.Ye@Sun.COM uint_t nb7300_emask_int_step0 = EMASK_INT_7300_STEP_0;
1387532SSean.Ye@Sun.COM uint_t nb5000_emask_int = EMASK_INT_5000;
1397532SSean.Ye@Sun.COM int nb5000_reset_emask_int = 1;
1407532SSean.Ye@Sun.COM uint_t nb5000_mask_poll_int = EMASK_INT_NF;
1417532SSean.Ye@Sun.COM uint_t nb5000_mask_bios_int = EMASK_INT_FATAL;
14210668SVuong.Nguyen@Sun.COM uint_t nb5100_mask_poll_int = EMASK_INT_5100_NF;
14310668SVuong.Nguyen@Sun.COM uint_t nb5100_mask_bios_int = EMASK_INT_5100_FATAL;
1447532SSean.Ye@Sun.COM
1457532SSean.Ye@Sun.COM uint_t nb_mask_poll_thr = EMASK_THR_NF;
1467532SSean.Ye@Sun.COM uint_t nb_mask_bios_thr = EMASK_THR_FATAL;
1477532SSean.Ye@Sun.COM
1487532SSean.Ye@Sun.COM int nb5000_reset_uncor_pex = 0;
1497532SSean.Ye@Sun.COM uint_t nb5000_mask_uncor_pex = 0;
1507532SSean.Ye@Sun.COM int nb5000_reset_cor_pex = 0;
1517532SSean.Ye@Sun.COM uint_t nb5000_mask_cor_pex = 0xffffffff;
1527532SSean.Ye@Sun.COM uint32_t nb5000_rp_pex = 0x1;
1537532SSean.Ye@Sun.COM
1547532SSean.Ye@Sun.COM int nb_mask_mc_set;
1557532SSean.Ye@Sun.COM
1567532SSean.Ye@Sun.COM typedef struct find_dimm_label {
1577532SSean.Ye@Sun.COM void (*label_function)(int, char *, int);
1587532SSean.Ye@Sun.COM } find_dimm_label_t;
1597532SSean.Ye@Sun.COM
1607532SSean.Ye@Sun.COM static void x8450_dimm_label(int, char *, int);
16110049SVuong.Nguyen@Sun.COM static void cp3250_dimm_label(int, char *, int);
1627532SSean.Ye@Sun.COM
1637532SSean.Ye@Sun.COM static struct platform_label {
1647532SSean.Ye@Sun.COM const char *sys_vendor; /* SMB_TYPE_SYSTEM vendor prefix */
1657532SSean.Ye@Sun.COM const char *sys_product; /* SMB_TYPE_SYSTEM product prefix */
1667532SSean.Ye@Sun.COM find_dimm_label_t dimm_label;
1677532SSean.Ye@Sun.COM int dimms_per_channel;
1687532SSean.Ye@Sun.COM } platform_label[] = {
1697532SSean.Ye@Sun.COM { "SUN MICROSYSTEMS", "SUN BLADE X8450 SERVER MODULE",
1707532SSean.Ye@Sun.COM x8450_dimm_label, 8 },
17110049SVuong.Nguyen@Sun.COM { "MiTAC,Shunde", "CP3250", cp3250_dimm_label, 0 },
1727532SSean.Ye@Sun.COM { NULL, NULL, NULL, 0 }
1737532SSean.Ye@Sun.COM };
1747532SSean.Ye@Sun.COM
1757532SSean.Ye@Sun.COM static unsigned short
read_spd(int bus)1767532SSean.Ye@Sun.COM read_spd(int bus)
1777532SSean.Ye@Sun.COM {
1787532SSean.Ye@Sun.COM unsigned short rt = 0;
1797532SSean.Ye@Sun.COM int branch = bus >> 1;
1807532SSean.Ye@Sun.COM int channel = bus & 1;
1817532SSean.Ye@Sun.COM
1827532SSean.Ye@Sun.COM rt = SPD_RD(branch, channel);
1837532SSean.Ye@Sun.COM
1847532SSean.Ye@Sun.COM return (rt);
1857532SSean.Ye@Sun.COM }
1867532SSean.Ye@Sun.COM
1877532SSean.Ye@Sun.COM static void
write_spdcmd(int bus,uint32_t val)1887532SSean.Ye@Sun.COM write_spdcmd(int bus, uint32_t val)
1897532SSean.Ye@Sun.COM {
1907532SSean.Ye@Sun.COM int branch = bus >> 1;
1917532SSean.Ye@Sun.COM int channel = bus & 1;
1927532SSean.Ye@Sun.COM SPDCMD_WR(branch, channel, val);
1937532SSean.Ye@Sun.COM }
1947532SSean.Ye@Sun.COM
1957532SSean.Ye@Sun.COM static int
read_spd_eeprom(int bus,int slave,int addr)1967532SSean.Ye@Sun.COM read_spd_eeprom(int bus, int slave, int addr)
1977532SSean.Ye@Sun.COM {
1987532SSean.Ye@Sun.COM int retry = 4;
1997532SSean.Ye@Sun.COM int wait;
2007532SSean.Ye@Sun.COM int spd;
2017532SSean.Ye@Sun.COM uint32_t cmd;
2027532SSean.Ye@Sun.COM
2037532SSean.Ye@Sun.COM for (;;) {
2047532SSean.Ye@Sun.COM wait = 1000;
2057532SSean.Ye@Sun.COM for (;;) {
2067532SSean.Ye@Sun.COM spd = read_spd(bus);
2077532SSean.Ye@Sun.COM if ((spd & SPD_BUSY) == 0)
2087532SSean.Ye@Sun.COM break;
2097532SSean.Ye@Sun.COM if (--wait == 0)
2107532SSean.Ye@Sun.COM return (-1);
2117532SSean.Ye@Sun.COM drv_usecwait(10);
2127532SSean.Ye@Sun.COM }
2137532SSean.Ye@Sun.COM cmd = SPD_EEPROM_WRITE | SPD_ADDR(slave, addr);
2147532SSean.Ye@Sun.COM write_spdcmd(bus, cmd);
2157532SSean.Ye@Sun.COM wait = 1000;
2167532SSean.Ye@Sun.COM for (;;) {
2177532SSean.Ye@Sun.COM spd = read_spd(bus);
2187532SSean.Ye@Sun.COM if ((spd & SPD_BUSY) == 0)
2197532SSean.Ye@Sun.COM break;
2207532SSean.Ye@Sun.COM if (--wait == 0) {
2217532SSean.Ye@Sun.COM spd = SPD_BUS_ERROR;
2227532SSean.Ye@Sun.COM break;
2237532SSean.Ye@Sun.COM }
2247532SSean.Ye@Sun.COM drv_usecwait(10);
2257532SSean.Ye@Sun.COM }
2267532SSean.Ye@Sun.COM while ((spd & SPD_BUS_ERROR) == 0 &&
2277532SSean.Ye@Sun.COM (spd & (SPD_READ_DATA_VALID|SPD_BUSY)) !=
2287532SSean.Ye@Sun.COM SPD_READ_DATA_VALID) {
2297532SSean.Ye@Sun.COM spd = read_spd(bus);
2307532SSean.Ye@Sun.COM if (--wait == 0)
2317532SSean.Ye@Sun.COM return (-1);
2327532SSean.Ye@Sun.COM }
2337532SSean.Ye@Sun.COM if ((spd & SPD_BUS_ERROR) == 0)
2347532SSean.Ye@Sun.COM break;
2357532SSean.Ye@Sun.COM if (--retry == 0)
2367532SSean.Ye@Sun.COM return (-1);
2377532SSean.Ye@Sun.COM }
2387532SSean.Ye@Sun.COM return (spd & 0xff);
2397532SSean.Ye@Sun.COM }
2407532SSean.Ye@Sun.COM
2417532SSean.Ye@Sun.COM static void
nb_fini()2427532SSean.Ye@Sun.COM nb_fini()
2437532SSean.Ye@Sun.COM {
2447532SSean.Ye@Sun.COM int i, j;
24510049SVuong.Nguyen@Sun.COM int nchannels = nb_number_memory_controllers * nb_channels_per_branch;
2467532SSean.Ye@Sun.COM nb_dimm_t **dimmpp;
2477532SSean.Ye@Sun.COM nb_dimm_t *dimmp;
2487532SSean.Ye@Sun.COM
2497532SSean.Ye@Sun.COM dimmpp = nb_dimms;
2507532SSean.Ye@Sun.COM for (i = 0; i < nchannels; i++) {
2517532SSean.Ye@Sun.COM for (j = 0; j < nb_dimms_per_channel; j++) {
2527532SSean.Ye@Sun.COM dimmp = *dimmpp;
2537532SSean.Ye@Sun.COM if (dimmp) {
2547532SSean.Ye@Sun.COM kmem_free(dimmp, sizeof (nb_dimm_t));
2557532SSean.Ye@Sun.COM *dimmpp = NULL;
2567532SSean.Ye@Sun.COM }
257*12726SJakub.Jermar@Sun.COM dimmpp++;
2587532SSean.Ye@Sun.COM }
2597532SSean.Ye@Sun.COM }
2608037SAdrian.Frost@Sun.COM kmem_free(nb_dimms, sizeof (nb_dimm_t *) * nb_dimm_slots);
2617532SSean.Ye@Sun.COM nb_dimms = NULL;
2627532SSean.Ye@Sun.COM dimm_fini();
2637532SSean.Ye@Sun.COM }
2647532SSean.Ye@Sun.COM
2657532SSean.Ye@Sun.COM void
nb_scrubber_enable()2667532SSean.Ye@Sun.COM nb_scrubber_enable()
2677532SSean.Ye@Sun.COM {
2687532SSean.Ye@Sun.COM uint32_t mc;
2697532SSean.Ye@Sun.COM
2707532SSean.Ye@Sun.COM if (!nb_hw_memory_scrub_enable)
2717532SSean.Ye@Sun.COM return;
2727532SSean.Ye@Sun.COM
2737532SSean.Ye@Sun.COM mc = MC_RD();
2747532SSean.Ye@Sun.COM if ((mc & MC_MIRROR) != 0) /* mirror mode */
2757532SSean.Ye@Sun.COM mc |= MC_PATROL_SCRUB;
2767532SSean.Ye@Sun.COM else
2777532SSean.Ye@Sun.COM mc |= MC_PATROL_SCRUB|MC_DEMAND_SCRUB;
2787532SSean.Ye@Sun.COM MC_WR(mc);
2797532SSean.Ye@Sun.COM
2807532SSean.Ye@Sun.COM if (nb_sw_scrub_disabled++)
2817532SSean.Ye@Sun.COM cmi_mc_sw_memscrub_disable();
2827532SSean.Ye@Sun.COM }
2837532SSean.Ye@Sun.COM
28410049SVuong.Nguyen@Sun.COM static void
fbd_eeprom(int channel,int dimm,nb_dimm_t * dp)28510049SVuong.Nguyen@Sun.COM fbd_eeprom(int channel, int dimm, nb_dimm_t *dp)
2867532SSean.Ye@Sun.COM {
2877532SSean.Ye@Sun.COM int i, t;
2887532SSean.Ye@Sun.COM int spd_sz;
2897532SSean.Ye@Sun.COM
2907532SSean.Ye@Sun.COM t = read_spd_eeprom(channel, dimm, 0) & 0xf;
2917532SSean.Ye@Sun.COM if (t == 1)
2927532SSean.Ye@Sun.COM spd_sz = 128;
2937532SSean.Ye@Sun.COM else if (t == 2)
2947532SSean.Ye@Sun.COM spd_sz = 176;
2957532SSean.Ye@Sun.COM else
2967532SSean.Ye@Sun.COM spd_sz = 256;
2977532SSean.Ye@Sun.COM dp->manufacture_id = read_spd_eeprom(channel, dimm, 117) |
2987532SSean.Ye@Sun.COM (read_spd_eeprom(channel, dimm, 118) << 8);
2997532SSean.Ye@Sun.COM dp->manufacture_location = read_spd_eeprom(channel, dimm, 119);
3007532SSean.Ye@Sun.COM dp->serial_number =
3017532SSean.Ye@Sun.COM (read_spd_eeprom(channel, dimm, 122) << 24) |
3027532SSean.Ye@Sun.COM (read_spd_eeprom(channel, dimm, 123) << 16) |
3037532SSean.Ye@Sun.COM (read_spd_eeprom(channel, dimm, 124) << 8) |
3047532SSean.Ye@Sun.COM read_spd_eeprom(channel, dimm, 125);
3057532SSean.Ye@Sun.COM t = read_spd_eeprom(channel, dimm, 121);
3067532SSean.Ye@Sun.COM dp->manufacture_week = (t >> 4) * 10 + (t & 0xf);
3077532SSean.Ye@Sun.COM dp->manufacture_year = read_spd_eeprom(channel, dimm, 120);
3087532SSean.Ye@Sun.COM if (spd_sz > 128) {
3097532SSean.Ye@Sun.COM for (i = 0; i < sizeof (dp->part_number); i++) {
3107532SSean.Ye@Sun.COM dp->part_number[i] =
3117532SSean.Ye@Sun.COM read_spd_eeprom(channel, dimm, 128 + i);
3127532SSean.Ye@Sun.COM }
3137532SSean.Ye@Sun.COM for (i = 0; i < sizeof (dp->revision); i++) {
3147532SSean.Ye@Sun.COM dp->revision[i] =
3157532SSean.Ye@Sun.COM read_spd_eeprom(channel, dimm, 146 + i);
3167532SSean.Ye@Sun.COM }
3177532SSean.Ye@Sun.COM }
31810049SVuong.Nguyen@Sun.COM }
31910049SVuong.Nguyen@Sun.COM
32010049SVuong.Nguyen@Sun.COM /* read the manR of the DDR2 dimm */
32110049SVuong.Nguyen@Sun.COM static void
ddr2_eeprom(int channel,int dimm,nb_dimm_t * dp)32210049SVuong.Nguyen@Sun.COM ddr2_eeprom(int channel, int dimm, nb_dimm_t *dp)
32310049SVuong.Nguyen@Sun.COM {
32410049SVuong.Nguyen@Sun.COM int i, t;
32510049SVuong.Nguyen@Sun.COM int slave;
32610049SVuong.Nguyen@Sun.COM
32710049SVuong.Nguyen@Sun.COM slave = channel & 0x1 ? dimm + 4 : dimm;
32810049SVuong.Nguyen@Sun.COM
32910049SVuong.Nguyen@Sun.COM /* byte[3]: number of row addresses */
33010049SVuong.Nguyen@Sun.COM dp->nrow = read_spd_eeprom(channel, slave, 3) & 0x1f;
33110049SVuong.Nguyen@Sun.COM
33210049SVuong.Nguyen@Sun.COM /* byte[4]: number of column addresses */
33310049SVuong.Nguyen@Sun.COM dp->ncolumn = read_spd_eeprom(channel, slave, 4) & 0xf;
33410049SVuong.Nguyen@Sun.COM
33510049SVuong.Nguyen@Sun.COM /* byte[5]: numranks; 0 means one rank */
33610049SVuong.Nguyen@Sun.COM dp->nranks = (read_spd_eeprom(channel, slave, 5) & 0x3) + 1;
33710049SVuong.Nguyen@Sun.COM
33810049SVuong.Nguyen@Sun.COM /* byte[6]: data width */
33910049SVuong.Nguyen@Sun.COM dp->width = (read_spd_eeprom(channel, slave, 6) >> 5) << 2;
34010049SVuong.Nguyen@Sun.COM
34110049SVuong.Nguyen@Sun.COM /* byte[17]: number of banks */
34210049SVuong.Nguyen@Sun.COM dp->nbanks = read_spd_eeprom(channel, slave, 17);
34310049SVuong.Nguyen@Sun.COM
34410049SVuong.Nguyen@Sun.COM dp->dimm_size = DIMMSIZE(dp->nrow, dp->ncolumn, dp->nranks, dp->nbanks,
34510049SVuong.Nguyen@Sun.COM dp->width);
34610049SVuong.Nguyen@Sun.COM
34710049SVuong.Nguyen@Sun.COM /* manufacture-id - byte[64-65] */
34810049SVuong.Nguyen@Sun.COM dp->manufacture_id = read_spd_eeprom(channel, slave, 64) |
34910049SVuong.Nguyen@Sun.COM (read_spd_eeprom(channel, dimm, 65) << 8);
35010049SVuong.Nguyen@Sun.COM
35110049SVuong.Nguyen@Sun.COM /* location - byte[72] */
35210049SVuong.Nguyen@Sun.COM dp->manufacture_location = read_spd_eeprom(channel, slave, 72);
35310049SVuong.Nguyen@Sun.COM
35410049SVuong.Nguyen@Sun.COM /* serial number - byte[95-98] */
35510049SVuong.Nguyen@Sun.COM dp->serial_number =
35610049SVuong.Nguyen@Sun.COM (read_spd_eeprom(channel, slave, 98) << 24) |
35710049SVuong.Nguyen@Sun.COM (read_spd_eeprom(channel, slave, 97) << 16) |
35810049SVuong.Nguyen@Sun.COM (read_spd_eeprom(channel, slave, 96) << 8) |
35910049SVuong.Nguyen@Sun.COM read_spd_eeprom(channel, slave, 95);
36010049SVuong.Nguyen@Sun.COM
36110049SVuong.Nguyen@Sun.COM /* week - byte[94] */
36210049SVuong.Nguyen@Sun.COM t = read_spd_eeprom(channel, slave, 94);
36310049SVuong.Nguyen@Sun.COM dp->manufacture_week = (t >> 4) * 10 + (t & 0xf);
36410049SVuong.Nguyen@Sun.COM /* week - byte[93] */
36510049SVuong.Nguyen@Sun.COM t = read_spd_eeprom(channel, slave, 93);
36610049SVuong.Nguyen@Sun.COM dp->manufacture_year = (t >> 4) * 10 + (t & 0xf) + 2000;
36710049SVuong.Nguyen@Sun.COM
36810049SVuong.Nguyen@Sun.COM /* part number - byte[73-81] */
36910049SVuong.Nguyen@Sun.COM for (i = 0; i < 8; i++) {
37010049SVuong.Nguyen@Sun.COM dp->part_number[i] = read_spd_eeprom(channel, slave, 73 + i);
37110049SVuong.Nguyen@Sun.COM }
37210049SVuong.Nguyen@Sun.COM
37310049SVuong.Nguyen@Sun.COM /* revision - byte[91-92] */
37410049SVuong.Nguyen@Sun.COM for (i = 0; i < 2; i++) {
37510049SVuong.Nguyen@Sun.COM dp->revision[i] = read_spd_eeprom(channel, slave, 91 + i);
37610049SVuong.Nguyen@Sun.COM }
37710049SVuong.Nguyen@Sun.COM }
37810049SVuong.Nguyen@Sun.COM
37910049SVuong.Nguyen@Sun.COM static boolean_t
nb_dimm_present(int channel,int dimm)38010049SVuong.Nguyen@Sun.COM nb_dimm_present(int channel, int dimm)
38110049SVuong.Nguyen@Sun.COM {
38210049SVuong.Nguyen@Sun.COM boolean_t rc = B_FALSE;
38310049SVuong.Nguyen@Sun.COM
38410049SVuong.Nguyen@Sun.COM if (nb_chipset == INTEL_NB_5100) {
38510049SVuong.Nguyen@Sun.COM int t, slave;
38610049SVuong.Nguyen@Sun.COM slave = channel & 0x1 ? dimm + 4 : dimm;
38710049SVuong.Nguyen@Sun.COM /* read the type field from the dimm and check for DDR2 type */
38810049SVuong.Nguyen@Sun.COM if ((t = read_spd_eeprom(channel, slave, SPD_MEM_TYPE)) == -1)
38910049SVuong.Nguyen@Sun.COM return (B_FALSE);
39010049SVuong.Nguyen@Sun.COM rc = (t & 0xf) == SPD_DDR2;
39110049SVuong.Nguyen@Sun.COM } else {
39210049SVuong.Nguyen@Sun.COM rc = MTR_PRESENT(MTR_RD(channel, dimm)) != 0;
39310049SVuong.Nguyen@Sun.COM }
39410049SVuong.Nguyen@Sun.COM
39510049SVuong.Nguyen@Sun.COM return (rc);
39610049SVuong.Nguyen@Sun.COM }
39710049SVuong.Nguyen@Sun.COM
39810049SVuong.Nguyen@Sun.COM static nb_dimm_t *
nb_ddr2_dimm_init(int channel,int dimm,int start_rank)39910049SVuong.Nguyen@Sun.COM nb_ddr2_dimm_init(int channel, int dimm, int start_rank)
40010049SVuong.Nguyen@Sun.COM {
40110049SVuong.Nguyen@Sun.COM nb_dimm_t *dp;
40210049SVuong.Nguyen@Sun.COM
40310049SVuong.Nguyen@Sun.COM if (nb_dimm_present(channel, dimm) == B_FALSE)
40410049SVuong.Nguyen@Sun.COM return (NULL);
40510049SVuong.Nguyen@Sun.COM
40610049SVuong.Nguyen@Sun.COM dp = kmem_zalloc(sizeof (nb_dimm_t), KM_SLEEP);
40710049SVuong.Nguyen@Sun.COM
40810049SVuong.Nguyen@Sun.COM ddr2_eeprom(channel, dimm, dp);
40910049SVuong.Nguyen@Sun.COM
41010049SVuong.Nguyen@Sun.COM /* The 1st rank of the dimm takes on this value */
41110049SVuong.Nguyen@Sun.COM dp->start_rank = (uint8_t)start_rank;
41210049SVuong.Nguyen@Sun.COM
41310049SVuong.Nguyen@Sun.COM dp->mtr_present = 1;
41410049SVuong.Nguyen@Sun.COM
41510049SVuong.Nguyen@Sun.COM return (dp);
41610049SVuong.Nguyen@Sun.COM }
41710049SVuong.Nguyen@Sun.COM
41810049SVuong.Nguyen@Sun.COM static nb_dimm_t *
nb_fbd_dimm_init(int channel,int dimm,uint16_t mtr)41910049SVuong.Nguyen@Sun.COM nb_fbd_dimm_init(int channel, int dimm, uint16_t mtr)
42010049SVuong.Nguyen@Sun.COM {
42110049SVuong.Nguyen@Sun.COM nb_dimm_t *dp;
42210049SVuong.Nguyen@Sun.COM int t;
42310049SVuong.Nguyen@Sun.COM
42410049SVuong.Nguyen@Sun.COM if (MTR_PRESENT(mtr) == 0)
42510049SVuong.Nguyen@Sun.COM return (NULL);
42610049SVuong.Nguyen@Sun.COM t = read_spd_eeprom(channel, dimm, SPD_MEM_TYPE) & 0xf;
42710049SVuong.Nguyen@Sun.COM
42810049SVuong.Nguyen@Sun.COM /* check for the dimm type */
42910049SVuong.Nguyen@Sun.COM if (t != SPD_FBDIMM)
43010049SVuong.Nguyen@Sun.COM return (NULL);
43110049SVuong.Nguyen@Sun.COM
43210049SVuong.Nguyen@Sun.COM dp = kmem_zalloc(sizeof (nb_dimm_t), KM_SLEEP);
43310049SVuong.Nguyen@Sun.COM
43410049SVuong.Nguyen@Sun.COM fbd_eeprom(channel, dimm, dp);
43510049SVuong.Nguyen@Sun.COM
4367532SSean.Ye@Sun.COM dp->mtr_present = MTR_PRESENT(mtr);
43710049SVuong.Nguyen@Sun.COM dp->start_rank = dimm << 1;
4387532SSean.Ye@Sun.COM dp->nranks = MTR_NUMRANK(mtr);
4397532SSean.Ye@Sun.COM dp->nbanks = MTR_NUMBANK(mtr);
4407532SSean.Ye@Sun.COM dp->ncolumn = MTR_NUMCOL(mtr);
4417532SSean.Ye@Sun.COM dp->nrow = MTR_NUMROW(mtr);
4427532SSean.Ye@Sun.COM dp->width = MTR_WIDTH(mtr);
4437532SSean.Ye@Sun.COM dp->dimm_size = MTR_DIMMSIZE(mtr);
4447532SSean.Ye@Sun.COM
4457532SSean.Ye@Sun.COM return (dp);
4467532SSean.Ye@Sun.COM }
4477532SSean.Ye@Sun.COM
4487532SSean.Ye@Sun.COM static uint64_t
mc_range(int controller,uint64_t base)4497532SSean.Ye@Sun.COM mc_range(int controller, uint64_t base)
4507532SSean.Ye@Sun.COM {
4517532SSean.Ye@Sun.COM int i;
4527532SSean.Ye@Sun.COM uint64_t limit = 0;
4537532SSean.Ye@Sun.COM
4547532SSean.Ye@Sun.COM for (i = 0; i < NB_MEM_BRANCH_SELECT; i++) {
4557532SSean.Ye@Sun.COM if (nb_banks[i].way[controller] && base >= nb_banks[i].base &&
4567532SSean.Ye@Sun.COM base < nb_banks[i].limit) {
4577532SSean.Ye@Sun.COM limit = nb_banks[i].limit;
4587532SSean.Ye@Sun.COM if (base <= top_of_low_memory &&
4597532SSean.Ye@Sun.COM limit > top_of_low_memory) {
4607532SSean.Ye@Sun.COM limit -= TLOW_MAX - top_of_low_memory;
4617532SSean.Ye@Sun.COM }
4627532SSean.Ye@Sun.COM if (nb_banks[i].way[0] && nb_banks[i].way[1] &&
4637532SSean.Ye@Sun.COM nb_mode != NB_MEMORY_MIRROR) {
4647532SSean.Ye@Sun.COM limit = limit / 2;
4657532SSean.Ye@Sun.COM }
4667532SSean.Ye@Sun.COM }
4677532SSean.Ye@Sun.COM }
4687532SSean.Ye@Sun.COM return (limit);
4697532SSean.Ye@Sun.COM }
4707532SSean.Ye@Sun.COM
4717532SSean.Ye@Sun.COM void
nb_mc_init()4727532SSean.Ye@Sun.COM nb_mc_init()
4737532SSean.Ye@Sun.COM {
4747532SSean.Ye@Sun.COM uint16_t tolm;
4757532SSean.Ye@Sun.COM uint16_t mir;
4767532SSean.Ye@Sun.COM uint32_t hole_base;
4777532SSean.Ye@Sun.COM uint32_t hole_size;
4787532SSean.Ye@Sun.COM uint32_t dmir;
4797532SSean.Ye@Sun.COM uint64_t base;
4807532SSean.Ye@Sun.COM uint64_t limit;
4817532SSean.Ye@Sun.COM uint8_t way0, way1, rank0, rank1, rank2, rank3, branch_interleave;
4827532SSean.Ye@Sun.COM int i, j, k;
4837532SSean.Ye@Sun.COM uint8_t interleave;
4847532SSean.Ye@Sun.COM
4857532SSean.Ye@Sun.COM base = 0;
4867532SSean.Ye@Sun.COM tolm = TOLM_RD();
4877532SSean.Ye@Sun.COM top_of_low_memory = ((uint32_t)(tolm >> 12) & 0xf) << 28;
4887532SSean.Ye@Sun.COM for (i = 0; i < NB_MEM_BRANCH_SELECT; i++) {
4897532SSean.Ye@Sun.COM mir = MIR_RD(i);
4907532SSean.Ye@Sun.COM limit = (uint64_t)(mir >> 4) << 28;
4917532SSean.Ye@Sun.COM way0 = mir & 1;
4927532SSean.Ye@Sun.COM way1 = (mir >> 1) & 1;
4937532SSean.Ye@Sun.COM if (way0 == 0 && way1 == 0) {
4947532SSean.Ye@Sun.COM way0 = 1;
4957532SSean.Ye@Sun.COM way1 = 1;
4967532SSean.Ye@Sun.COM }
4977532SSean.Ye@Sun.COM if (limit > top_of_low_memory)
4987532SSean.Ye@Sun.COM limit += TLOW_MAX - top_of_low_memory;
4997532SSean.Ye@Sun.COM nb_banks[i].base = base;
5007532SSean.Ye@Sun.COM nb_banks[i].limit = limit;
5017532SSean.Ye@Sun.COM nb_banks[i].way[0] = way0;
5027532SSean.Ye@Sun.COM nb_banks[i].way[1] = way1;
5037532SSean.Ye@Sun.COM base = limit;
5047532SSean.Ye@Sun.COM }
5057532SSean.Ye@Sun.COM for (i = 0; i < nb_number_memory_controllers; i++) {
5067532SSean.Ye@Sun.COM base = 0;
5077532SSean.Ye@Sun.COM
5087532SSean.Ye@Sun.COM for (j = 0; j < NB_MEM_RANK_SELECT; j++) {
5097532SSean.Ye@Sun.COM dmir = DMIR_RD(i, j);
5107532SSean.Ye@Sun.COM limit = ((uint64_t)(dmir >> 16) & 0xff) << 28;
5117532SSean.Ye@Sun.COM if (limit == 0) {
5127532SSean.Ye@Sun.COM limit = mc_range(i, base);
5137532SSean.Ye@Sun.COM }
5147532SSean.Ye@Sun.COM branch_interleave = 0;
5157532SSean.Ye@Sun.COM hole_base = 0;
5167532SSean.Ye@Sun.COM hole_size = 0;
5177532SSean.Ye@Sun.COM DMIR_RANKS(dmir, rank0, rank1, rank2, rank3);
5187532SSean.Ye@Sun.COM if (rank0 == rank1)
5197532SSean.Ye@Sun.COM interleave = 1;
5207532SSean.Ye@Sun.COM else if (rank0 == rank2)
5217532SSean.Ye@Sun.COM interleave = 2;
5227532SSean.Ye@Sun.COM else
5237532SSean.Ye@Sun.COM interleave = 4;
5247532SSean.Ye@Sun.COM if (nb_mode != NB_MEMORY_MIRROR &&
5257532SSean.Ye@Sun.COM nb_mode != NB_MEMORY_SINGLE_CHANNEL) {
5267532SSean.Ye@Sun.COM for (k = 0; k < NB_MEM_BRANCH_SELECT; k++) {
5277532SSean.Ye@Sun.COM if (base >= nb_banks[k].base &&
5287532SSean.Ye@Sun.COM base < nb_banks[k].limit) {
5297532SSean.Ye@Sun.COM if (nb_banks[i].way[0] &&
5307532SSean.Ye@Sun.COM nb_banks[i].way[1]) {
5317532SSean.Ye@Sun.COM interleave *= 2;
5327532SSean.Ye@Sun.COM limit *= 2;
5337532SSean.Ye@Sun.COM branch_interleave = 1;
5347532SSean.Ye@Sun.COM }
5357532SSean.Ye@Sun.COM break;
5367532SSean.Ye@Sun.COM }
5377532SSean.Ye@Sun.COM }
5387532SSean.Ye@Sun.COM }
5397532SSean.Ye@Sun.COM if (base < top_of_low_memory &&
5407532SSean.Ye@Sun.COM limit > top_of_low_memory) {
5417532SSean.Ye@Sun.COM hole_base = top_of_low_memory;
5427532SSean.Ye@Sun.COM hole_size = TLOW_MAX - top_of_low_memory;
5437532SSean.Ye@Sun.COM limit += hole_size;
5447532SSean.Ye@Sun.COM } else if (base > top_of_low_memory) {
5457532SSean.Ye@Sun.COM limit += TLOW_MAX - top_of_low_memory;
5467532SSean.Ye@Sun.COM }
5477532SSean.Ye@Sun.COM nb_ranks[i][j].base = base;
5487532SSean.Ye@Sun.COM nb_ranks[i][j].limit = limit;
5497532SSean.Ye@Sun.COM nb_ranks[i][j].rank[0] = rank0;
5507532SSean.Ye@Sun.COM nb_ranks[i][j].rank[1] = rank1;
5517532SSean.Ye@Sun.COM nb_ranks[i][j].rank[2] = rank2;
5527532SSean.Ye@Sun.COM nb_ranks[i][j].rank[3] = rank3;
5537532SSean.Ye@Sun.COM nb_ranks[i][j].interleave = interleave;
5547532SSean.Ye@Sun.COM nb_ranks[i][j].branch_interleave = branch_interleave;
5557532SSean.Ye@Sun.COM nb_ranks[i][j].hole_base = hole_base;
5567532SSean.Ye@Sun.COM nb_ranks[i][j].hole_size = hole_size;
5577532SSean.Ye@Sun.COM if (limit > base) {
5587532SSean.Ye@Sun.COM if (rank0 != rank1) {
5597532SSean.Ye@Sun.COM dimm_add_rank(i, rank1,
5607532SSean.Ye@Sun.COM branch_interleave, 1, base,
5617532SSean.Ye@Sun.COM hole_base, hole_size, interleave,
5627532SSean.Ye@Sun.COM limit);
5637532SSean.Ye@Sun.COM if (rank0 != rank2) {
5647532SSean.Ye@Sun.COM dimm_add_rank(i, rank2,
5657532SSean.Ye@Sun.COM branch_interleave, 2, base,
5667532SSean.Ye@Sun.COM hole_base, hole_size,
5677532SSean.Ye@Sun.COM interleave, limit);
5687532SSean.Ye@Sun.COM dimm_add_rank(i, rank3,
5697532SSean.Ye@Sun.COM branch_interleave, 3, base,
5707532SSean.Ye@Sun.COM hole_base, hole_size,
5717532SSean.Ye@Sun.COM interleave, limit);
5727532SSean.Ye@Sun.COM }
5737532SSean.Ye@Sun.COM }
5747532SSean.Ye@Sun.COM }
5757532SSean.Ye@Sun.COM base = limit;
5767532SSean.Ye@Sun.COM }
5777532SSean.Ye@Sun.COM }
5787532SSean.Ye@Sun.COM }
5797532SSean.Ye@Sun.COM
5807532SSean.Ye@Sun.COM void
nb_used_spare_rank(int branch,int bad_rank)5817532SSean.Ye@Sun.COM nb_used_spare_rank(int branch, int bad_rank)
5827532SSean.Ye@Sun.COM {
5837532SSean.Ye@Sun.COM int i;
5847532SSean.Ye@Sun.COM int j;
5857532SSean.Ye@Sun.COM
5867532SSean.Ye@Sun.COM for (i = 0; i < NB_MEM_RANK_SELECT; i++) {
5877532SSean.Ye@Sun.COM for (j = 0; j < NB_RANKS_IN_SELECT; j++) {
5887532SSean.Ye@Sun.COM if (nb_ranks[branch][i].rank[j] == bad_rank) {
5897532SSean.Ye@Sun.COM nb_ranks[branch][i].rank[j] =
5907532SSean.Ye@Sun.COM spare_rank[branch];
5917532SSean.Ye@Sun.COM i = NB_MEM_RANK_SELECT;
5927532SSean.Ye@Sun.COM break;
5937532SSean.Ye@Sun.COM }
5947532SSean.Ye@Sun.COM }
5957532SSean.Ye@Sun.COM }
5967532SSean.Ye@Sun.COM }
5977532SSean.Ye@Sun.COM
5987532SSean.Ye@Sun.COM find_dimm_label_t *
find_dimms_per_channel()5997532SSean.Ye@Sun.COM find_dimms_per_channel()
6007532SSean.Ye@Sun.COM {
6017532SSean.Ye@Sun.COM struct platform_label *pl;
6027532SSean.Ye@Sun.COM smbios_info_t si;
6037532SSean.Ye@Sun.COM smbios_system_t sy;
6047532SSean.Ye@Sun.COM id_t id;
6058037SAdrian.Frost@Sun.COM int i, j;
6067532SSean.Ye@Sun.COM find_dimm_label_t *rt = NULL;
6077532SSean.Ye@Sun.COM
6088037SAdrian.Frost@Sun.COM if (ksmbios != NULL && nb_no_smbios == 0) {
6097532SSean.Ye@Sun.COM if ((id = smbios_info_system(ksmbios, &sy)) != SMB_ERR &&
6107532SSean.Ye@Sun.COM smbios_info_common(ksmbios, id, &si) != SMB_ERR) {
6117532SSean.Ye@Sun.COM for (pl = platform_label; pl->sys_vendor; pl++) {
6127532SSean.Ye@Sun.COM if (strncmp(pl->sys_vendor,
6137532SSean.Ye@Sun.COM si.smbi_manufacturer,
6147532SSean.Ye@Sun.COM strlen(pl->sys_vendor)) == 0 &&
6157532SSean.Ye@Sun.COM strncmp(pl->sys_product, si.smbi_product,
6167532SSean.Ye@Sun.COM strlen(pl->sys_product)) == 0) {
6177532SSean.Ye@Sun.COM nb_dimms_per_channel =
6187532SSean.Ye@Sun.COM pl->dimms_per_channel;
6197532SSean.Ye@Sun.COM rt = &pl->dimm_label;
6207532SSean.Ye@Sun.COM break;
6217532SSean.Ye@Sun.COM }
6227532SSean.Ye@Sun.COM }
6237532SSean.Ye@Sun.COM }
6247532SSean.Ye@Sun.COM }
6257532SSean.Ye@Sun.COM if (nb_dimms_per_channel == 0) {
6268037SAdrian.Frost@Sun.COM /*
6278037SAdrian.Frost@Sun.COM * Scan all memory channels if we find a channel which has more
6288037SAdrian.Frost@Sun.COM * dimms then we have seen before set nb_dimms_per_channel to
6298037SAdrian.Frost@Sun.COM * the number of dimms on the channel
6308037SAdrian.Frost@Sun.COM */
6318037SAdrian.Frost@Sun.COM for (i = 0; i < nb_number_memory_controllers; i++) {
6328037SAdrian.Frost@Sun.COM for (j = nb_dimms_per_channel;
6338037SAdrian.Frost@Sun.COM j < NB_MAX_DIMMS_PER_CHANNEL; j++) {
63410049SVuong.Nguyen@Sun.COM if (nb_dimm_present(i, j))
6358037SAdrian.Frost@Sun.COM nb_dimms_per_channel = j + 1;
6368037SAdrian.Frost@Sun.COM }
6377532SSean.Ye@Sun.COM }
6387532SSean.Ye@Sun.COM }
6397532SSean.Ye@Sun.COM return (rt);
6407532SSean.Ye@Sun.COM }
6417532SSean.Ye@Sun.COM
6429783SAdrian.Frost@Sun.COM struct smb_dimm_rec {
6439783SAdrian.Frost@Sun.COM int dimms;
6449783SAdrian.Frost@Sun.COM int slots;
6459783SAdrian.Frost@Sun.COM int populated;
6469783SAdrian.Frost@Sun.COM nb_dimm_t **dimmpp;
6479783SAdrian.Frost@Sun.COM };
6489783SAdrian.Frost@Sun.COM
6497532SSean.Ye@Sun.COM static int
dimm_label(smbios_hdl_t * shp,const smbios_struct_t * sp,void * arg)6507532SSean.Ye@Sun.COM dimm_label(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
6517532SSean.Ye@Sun.COM {
6529783SAdrian.Frost@Sun.COM struct smb_dimm_rec *rp = (struct smb_dimm_rec *)arg;
6539783SAdrian.Frost@Sun.COM nb_dimm_t ***dimmpp;
6547532SSean.Ye@Sun.COM nb_dimm_t *dimmp;
6557532SSean.Ye@Sun.COM smbios_memdevice_t md;
6567532SSean.Ye@Sun.COM
6579783SAdrian.Frost@Sun.COM dimmpp = &rp->dimmpp;
6587532SSean.Ye@Sun.COM if (sp->smbstr_type == SMB_TYPE_MEMDEVICE) {
6598037SAdrian.Frost@Sun.COM if (*dimmpp >= &nb_dimms[nb_dimm_slots])
6608037SAdrian.Frost@Sun.COM return (-1);
6617532SSean.Ye@Sun.COM dimmp = **dimmpp;
6628037SAdrian.Frost@Sun.COM if (smbios_info_memdevice(shp, sp->smbstr_id, &md) == 0 &&
6638037SAdrian.Frost@Sun.COM md.smbmd_dloc != NULL) {
6648037SAdrian.Frost@Sun.COM if (md.smbmd_size) {
6659783SAdrian.Frost@Sun.COM if (dimmp == NULL &&
6669783SAdrian.Frost@Sun.COM (rp->slots == nb_dimm_slots ||
6679783SAdrian.Frost@Sun.COM rp->dimms < rp->populated)) {
6689783SAdrian.Frost@Sun.COM (*dimmpp)++;
6699783SAdrian.Frost@Sun.COM return (0);
6709783SAdrian.Frost@Sun.COM }
6718037SAdrian.Frost@Sun.COM /*
6728037SAdrian.Frost@Sun.COM * if there is no physical dimm for this smbios
6738037SAdrian.Frost@Sun.COM * record it is because this system has less
6748037SAdrian.Frost@Sun.COM * physical slots than the controller supports
6758037SAdrian.Frost@Sun.COM * so skip empty slots to find the slot this
6768037SAdrian.Frost@Sun.COM * smbios record belongs too
6778037SAdrian.Frost@Sun.COM */
6788037SAdrian.Frost@Sun.COM while (dimmp == NULL) {
6799783SAdrian.Frost@Sun.COM (*dimmpp)++;
6808037SAdrian.Frost@Sun.COM if (*dimmpp >= &nb_dimms[nb_dimm_slots])
6818037SAdrian.Frost@Sun.COM return (-1);
6829783SAdrian.Frost@Sun.COM dimmp = **dimmpp;
6838037SAdrian.Frost@Sun.COM }
6848037SAdrian.Frost@Sun.COM (void) snprintf(dimmp->label,
6858037SAdrian.Frost@Sun.COM sizeof (dimmp->label), "%s", md.smbmd_dloc);
6868037SAdrian.Frost@Sun.COM (*dimmpp)++;
6878037SAdrian.Frost@Sun.COM }
6887532SSean.Ye@Sun.COM }
6897532SSean.Ye@Sun.COM }
6907532SSean.Ye@Sun.COM return (0);
6917532SSean.Ye@Sun.COM }
6927532SSean.Ye@Sun.COM
6939783SAdrian.Frost@Sun.COM static int
check_memdevice(smbios_hdl_t * shp,const smbios_struct_t * sp,void * arg)6949783SAdrian.Frost@Sun.COM check_memdevice(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
6959783SAdrian.Frost@Sun.COM {
6969783SAdrian.Frost@Sun.COM struct smb_dimm_rec *rp = (struct smb_dimm_rec *)arg;
6979783SAdrian.Frost@Sun.COM smbios_memdevice_t md;
6989783SAdrian.Frost@Sun.COM
6999783SAdrian.Frost@Sun.COM if (sp->smbstr_type == SMB_TYPE_MEMDEVICE) {
7009783SAdrian.Frost@Sun.COM if (smbios_info_memdevice(shp, sp->smbstr_id, &md) == 0) {
7019783SAdrian.Frost@Sun.COM rp->slots++;
7029783SAdrian.Frost@Sun.COM if (md.smbmd_size) {
7039783SAdrian.Frost@Sun.COM rp->populated++;
7049783SAdrian.Frost@Sun.COM }
7059783SAdrian.Frost@Sun.COM }
7069783SAdrian.Frost@Sun.COM }
7079783SAdrian.Frost@Sun.COM return (0);
7089783SAdrian.Frost@Sun.COM }
7099783SAdrian.Frost@Sun.COM
7107532SSean.Ye@Sun.COM void
nb_smbios()7117532SSean.Ye@Sun.COM nb_smbios()
7127532SSean.Ye@Sun.COM {
7139783SAdrian.Frost@Sun.COM struct smb_dimm_rec r;
7149783SAdrian.Frost@Sun.COM int i;
7157532SSean.Ye@Sun.COM
7168037SAdrian.Frost@Sun.COM if (ksmbios != NULL && nb_no_smbios == 0) {
7179783SAdrian.Frost@Sun.COM r.dimms = 0;
7189783SAdrian.Frost@Sun.COM r.slots = 0;
7199783SAdrian.Frost@Sun.COM r.populated = 0;
7209783SAdrian.Frost@Sun.COM r.dimmpp = nb_dimms;
7219783SAdrian.Frost@Sun.COM for (i = 0; i < nb_dimm_slots; i++) {
7229783SAdrian.Frost@Sun.COM if (nb_dimms[i] != NULL)
7239783SAdrian.Frost@Sun.COM r.dimms++;
7249783SAdrian.Frost@Sun.COM }
7259783SAdrian.Frost@Sun.COM (void) smbios_iter(ksmbios, check_memdevice, &r);
7269783SAdrian.Frost@Sun.COM (void) smbios_iter(ksmbios, dimm_label, &r);
7277532SSean.Ye@Sun.COM }
7287532SSean.Ye@Sun.COM }
7297532SSean.Ye@Sun.COM
7307532SSean.Ye@Sun.COM static void
x8450_dimm_label(int dimm,char * label,int label_sz)7317532SSean.Ye@Sun.COM x8450_dimm_label(int dimm, char *label, int label_sz)
7327532SSean.Ye@Sun.COM {
7337532SSean.Ye@Sun.COM int channel = dimm >> 3;
7347532SSean.Ye@Sun.COM
7357532SSean.Ye@Sun.COM dimm = dimm & 0x7;
7367532SSean.Ye@Sun.COM (void) snprintf(label, label_sz, "D%d", (dimm * 4) + channel);
7377532SSean.Ye@Sun.COM }
7387532SSean.Ye@Sun.COM
73910049SVuong.Nguyen@Sun.COM /*
74010049SVuong.Nguyen@Sun.COM * CP3250 DIMM labels
74110049SVuong.Nguyen@Sun.COM * Channel Dimm Label
74210049SVuong.Nguyen@Sun.COM * 0 0 A0
74310049SVuong.Nguyen@Sun.COM * 1 0 B0
74410049SVuong.Nguyen@Sun.COM * 0 1 A1
74510049SVuong.Nguyen@Sun.COM * 1 1 B1
74610049SVuong.Nguyen@Sun.COM * 0 2 A2
74710049SVuong.Nguyen@Sun.COM * 1 2 B2
74810049SVuong.Nguyen@Sun.COM */
7497532SSean.Ye@Sun.COM static void
cp3250_dimm_label(int dimm,char * label,int label_sz)75010049SVuong.Nguyen@Sun.COM cp3250_dimm_label(int dimm, char *label, int label_sz)
75110049SVuong.Nguyen@Sun.COM {
75210049SVuong.Nguyen@Sun.COM int channel = dimm / nb_dimms_per_channel;
75310049SVuong.Nguyen@Sun.COM
75410049SVuong.Nguyen@Sun.COM dimm = dimm % nb_dimms_per_channel;
75510049SVuong.Nguyen@Sun.COM (void) snprintf(label, label_sz, "%c%d", channel == 0 ? 'A' : 'B',
75610049SVuong.Nguyen@Sun.COM dimm);
75710049SVuong.Nguyen@Sun.COM }
75810049SVuong.Nguyen@Sun.COM
75910049SVuong.Nguyen@Sun.COM /*
76010049SVuong.Nguyen@Sun.COM * Map the rank id to dimm id of a channel
76110049SVuong.Nguyen@Sun.COM * For the 5100 chipset, walk through the dimm list of channel the check if
76210049SVuong.Nguyen@Sun.COM * the given rank id is within the rank range assigned to the dimm.
76310049SVuong.Nguyen@Sun.COM * For other chipsets, the dimm is rank/2.
76410049SVuong.Nguyen@Sun.COM */
76510049SVuong.Nguyen@Sun.COM int
nb_rank2dimm(int channel,int rank)76610049SVuong.Nguyen@Sun.COM nb_rank2dimm(int channel, int rank)
76710049SVuong.Nguyen@Sun.COM {
76810049SVuong.Nguyen@Sun.COM int i;
76910049SVuong.Nguyen@Sun.COM nb_dimm_t **dimmpp = nb_dimms;
77010049SVuong.Nguyen@Sun.COM
77110049SVuong.Nguyen@Sun.COM if (nb_chipset != INTEL_NB_5100)
77210049SVuong.Nguyen@Sun.COM return (rank >> 1);
77310049SVuong.Nguyen@Sun.COM
77410049SVuong.Nguyen@Sun.COM dimmpp += channel * nb_dimms_per_channel;
77510049SVuong.Nguyen@Sun.COM for (i = 0; i < nb_dimms_per_channel; i++) {
77610049SVuong.Nguyen@Sun.COM if ((rank >= dimmpp[i]->start_rank) &&
77710049SVuong.Nguyen@Sun.COM (rank < dimmpp[i]->start_rank + dimmpp[i]->nranks)) {
77810049SVuong.Nguyen@Sun.COM return (i);
77910049SVuong.Nguyen@Sun.COM }
78010049SVuong.Nguyen@Sun.COM }
78110049SVuong.Nguyen@Sun.COM return (-1);
78210049SVuong.Nguyen@Sun.COM }
78310049SVuong.Nguyen@Sun.COM
78410049SVuong.Nguyen@Sun.COM static void
nb_ddr2_dimms_init(find_dimm_label_t * label_function)78510049SVuong.Nguyen@Sun.COM nb_ddr2_dimms_init(find_dimm_label_t *label_function)
78610049SVuong.Nguyen@Sun.COM {
78710049SVuong.Nguyen@Sun.COM int i, j;
78810049SVuong.Nguyen@Sun.COM int start_rank;
78910049SVuong.Nguyen@Sun.COM uint32_t spcpc;
79010049SVuong.Nguyen@Sun.COM uint8_t spcps;
79110049SVuong.Nguyen@Sun.COM nb_dimm_t **dimmpp;
79210049SVuong.Nguyen@Sun.COM
79310049SVuong.Nguyen@Sun.COM nb_dimm_slots = nb_number_memory_controllers * nb_channels_per_branch *
79410049SVuong.Nguyen@Sun.COM nb_dimms_per_channel;
79510049SVuong.Nguyen@Sun.COM nb_dimms = (nb_dimm_t **)kmem_zalloc(sizeof (nb_dimm_t *) *
79610049SVuong.Nguyen@Sun.COM nb_dimm_slots, KM_SLEEP);
79710049SVuong.Nguyen@Sun.COM dimmpp = nb_dimms;
79810049SVuong.Nguyen@Sun.COM nb_mode = NB_MEMORY_NORMAL;
79910049SVuong.Nguyen@Sun.COM for (i = 0; i < nb_number_memory_controllers; i++) {
80010049SVuong.Nguyen@Sun.COM if (nb_mode == NB_MEMORY_NORMAL) {
80110049SVuong.Nguyen@Sun.COM spcpc = SPCPC_RD(i);
80210049SVuong.Nguyen@Sun.COM spcps = SPCPS_RD(i);
80310049SVuong.Nguyen@Sun.COM if ((spcpc & SPCPC_SPARE_ENABLE) != 0 &&
80410049SVuong.Nguyen@Sun.COM (spcps & SPCPS_SPARE_DEPLOYED) != 0)
80510049SVuong.Nguyen@Sun.COM nb_mode = NB_MEMORY_SPARE_RANK;
80610049SVuong.Nguyen@Sun.COM spare_rank[i] = SPCPC_SPRANK(spcpc);
80710049SVuong.Nguyen@Sun.COM }
80810049SVuong.Nguyen@Sun.COM
80910049SVuong.Nguyen@Sun.COM /* The 1st dimm of a channel starts at rank 0 */
81010049SVuong.Nguyen@Sun.COM start_rank = 0;
81110049SVuong.Nguyen@Sun.COM
81210049SVuong.Nguyen@Sun.COM for (j = 0; j < nb_dimms_per_channel; j++) {
81310049SVuong.Nguyen@Sun.COM dimmpp[j] = nb_ddr2_dimm_init(i, j, start_rank);
81410049SVuong.Nguyen@Sun.COM if (dimmpp[j]) {
81510049SVuong.Nguyen@Sun.COM nb_ndimm ++;
81610049SVuong.Nguyen@Sun.COM if (label_function) {
81710049SVuong.Nguyen@Sun.COM label_function->label_function(
81810049SVuong.Nguyen@Sun.COM (i * nb_dimms_per_channel) + j,
81910049SVuong.Nguyen@Sun.COM dimmpp[j]->label,
82010049SVuong.Nguyen@Sun.COM sizeof (dimmpp[j]->label));
82110049SVuong.Nguyen@Sun.COM }
82210049SVuong.Nguyen@Sun.COM start_rank += dimmpp[j]->nranks;
82310049SVuong.Nguyen@Sun.COM /*
82410049SVuong.Nguyen@Sun.COM * add an extra rank because
82510049SVuong.Nguyen@Sun.COM * single-ranked dimm still takes on two ranks.
82610049SVuong.Nguyen@Sun.COM */
82710049SVuong.Nguyen@Sun.COM if (dimmpp[j]->nranks & 0x1)
82810049SVuong.Nguyen@Sun.COM start_rank++;
82910049SVuong.Nguyen@Sun.COM }
83010049SVuong.Nguyen@Sun.COM }
83110049SVuong.Nguyen@Sun.COM dimmpp += nb_dimms_per_channel;
83210049SVuong.Nguyen@Sun.COM }
83310049SVuong.Nguyen@Sun.COM
83410049SVuong.Nguyen@Sun.COM /*
83510049SVuong.Nguyen@Sun.COM * single channel is supported.
83610049SVuong.Nguyen@Sun.COM */
83710049SVuong.Nguyen@Sun.COM if (nb_ndimm > 0 && nb_ndimm <= nb_dimms_per_channel) {
83810049SVuong.Nguyen@Sun.COM nb_mode = NB_MEMORY_SINGLE_CHANNEL;
83910049SVuong.Nguyen@Sun.COM }
84010049SVuong.Nguyen@Sun.COM }
84110049SVuong.Nguyen@Sun.COM
84210049SVuong.Nguyen@Sun.COM static void
nb_fbd_dimms_init(find_dimm_label_t * label_function)84310049SVuong.Nguyen@Sun.COM nb_fbd_dimms_init(find_dimm_label_t *label_function)
8447532SSean.Ye@Sun.COM {
8457532SSean.Ye@Sun.COM int i, j, k, l;
8467532SSean.Ye@Sun.COM uint16_t mtr;
8477532SSean.Ye@Sun.COM uint32_t mc, mca;
8487532SSean.Ye@Sun.COM uint32_t spcpc;
8497532SSean.Ye@Sun.COM uint8_t spcps;
8507532SSean.Ye@Sun.COM nb_dimm_t **dimmpp;
8517532SSean.Ye@Sun.COM
8527532SSean.Ye@Sun.COM mca = MCA_RD();
8537532SSean.Ye@Sun.COM mc = MC_RD();
8547532SSean.Ye@Sun.COM if (mca & MCA_SCHDIMM) /* single-channel mode */
8557532SSean.Ye@Sun.COM nb_mode = NB_MEMORY_SINGLE_CHANNEL;
8567532SSean.Ye@Sun.COM else if ((mc & MC_MIRROR) != 0) /* mirror mode */
8577532SSean.Ye@Sun.COM nb_mode = NB_MEMORY_MIRROR;
8587532SSean.Ye@Sun.COM else
8597532SSean.Ye@Sun.COM nb_mode = NB_MEMORY_NORMAL;
8608037SAdrian.Frost@Sun.COM nb_dimm_slots = nb_number_memory_controllers * 2 * nb_dimms_per_channel;
8617532SSean.Ye@Sun.COM nb_dimms = (nb_dimm_t **)kmem_zalloc(sizeof (nb_dimm_t *) *
8628037SAdrian.Frost@Sun.COM nb_dimm_slots, KM_SLEEP);
8637532SSean.Ye@Sun.COM dimmpp = nb_dimms;
8647532SSean.Ye@Sun.COM for (i = 0; i < nb_number_memory_controllers; i++) {
8657532SSean.Ye@Sun.COM if (nb_mode == NB_MEMORY_NORMAL) {
8667532SSean.Ye@Sun.COM spcpc = SPCPC_RD(i);
8677532SSean.Ye@Sun.COM spcps = SPCPS_RD(i);
8687532SSean.Ye@Sun.COM if ((spcpc & SPCPC_SPARE_ENABLE) != 0 &&
8697532SSean.Ye@Sun.COM (spcps & SPCPS_SPARE_DEPLOYED) != 0)
8707532SSean.Ye@Sun.COM nb_mode = NB_MEMORY_SPARE_RANK;
8717532SSean.Ye@Sun.COM spare_rank[i] = SPCPC_SPRANK(spcpc);
8727532SSean.Ye@Sun.COM }
8737532SSean.Ye@Sun.COM for (j = 0; j < nb_dimms_per_channel; j++) {
8747532SSean.Ye@Sun.COM mtr = MTR_RD(i, j);
8757532SSean.Ye@Sun.COM k = i * 2;
87610049SVuong.Nguyen@Sun.COM dimmpp[j] = nb_fbd_dimm_init(k, j, mtr);
8777532SSean.Ye@Sun.COM if (dimmpp[j]) {
8787532SSean.Ye@Sun.COM nb_ndimm ++;
8797532SSean.Ye@Sun.COM if (label_function) {
8807532SSean.Ye@Sun.COM label_function->label_function(
8817532SSean.Ye@Sun.COM (k * nb_dimms_per_channel) + j,
8827532SSean.Ye@Sun.COM dimmpp[j]->label,
8837532SSean.Ye@Sun.COM sizeof (dimmpp[j]->label));
8847532SSean.Ye@Sun.COM }
8857532SSean.Ye@Sun.COM }
8867532SSean.Ye@Sun.COM dimmpp[j + nb_dimms_per_channel] =
88710049SVuong.Nguyen@Sun.COM nb_fbd_dimm_init(k + 1, j, mtr);
8887532SSean.Ye@Sun.COM l = j + nb_dimms_per_channel;
8897532SSean.Ye@Sun.COM if (dimmpp[l]) {
8907532SSean.Ye@Sun.COM if (label_function) {
8917532SSean.Ye@Sun.COM label_function->label_function(
8927532SSean.Ye@Sun.COM (k * nb_dimms_per_channel) + l,
8937532SSean.Ye@Sun.COM dimmpp[l]->label,
8947532SSean.Ye@Sun.COM sizeof (dimmpp[l]->label));
8957532SSean.Ye@Sun.COM }
8967532SSean.Ye@Sun.COM nb_ndimm ++;
8977532SSean.Ye@Sun.COM }
8987532SSean.Ye@Sun.COM }
8997532SSean.Ye@Sun.COM dimmpp += nb_dimms_per_channel * 2;
9007532SSean.Ye@Sun.COM }
90110049SVuong.Nguyen@Sun.COM }
90210049SVuong.Nguyen@Sun.COM
90310049SVuong.Nguyen@Sun.COM static void
nb_dimms_init(find_dimm_label_t * label_function)90410049SVuong.Nguyen@Sun.COM nb_dimms_init(find_dimm_label_t *label_function)
90510049SVuong.Nguyen@Sun.COM {
90610049SVuong.Nguyen@Sun.COM if (nb_chipset == INTEL_NB_5100)
90710049SVuong.Nguyen@Sun.COM nb_ddr2_dimms_init(label_function);
90810049SVuong.Nguyen@Sun.COM else
90910049SVuong.Nguyen@Sun.COM nb_fbd_dimms_init(label_function);
91010049SVuong.Nguyen@Sun.COM
9117532SSean.Ye@Sun.COM if (label_function == NULL)
9127532SSean.Ye@Sun.COM nb_smbios();
9137532SSean.Ye@Sun.COM }
9147532SSean.Ye@Sun.COM
9157848SKrishna.Elango@Sun.COM /* Setup the ESI port registers to enable SERR for southbridge */
9167532SSean.Ye@Sun.COM static void
nb_pex_init()9177532SSean.Ye@Sun.COM nb_pex_init()
9187532SSean.Ye@Sun.COM {
9197848SKrishna.Elango@Sun.COM int i = 0; /* ESI port */
9207848SKrishna.Elango@Sun.COM uint16_t regw;
9217532SSean.Ye@Sun.COM
9227848SKrishna.Elango@Sun.COM emask_uncor_pex[i] = EMASK_UNCOR_PEX_RD(i);
9237848SKrishna.Elango@Sun.COM emask_cor_pex[i] = EMASK_COR_PEX_RD(i);
9247848SKrishna.Elango@Sun.COM emask_rp_pex[i] = EMASK_RP_PEX_RD(i);
9257848SKrishna.Elango@Sun.COM docmd_pex[i] = PEX_ERR_DOCMD_RD(i);
9267848SKrishna.Elango@Sun.COM uncerrsev[i] = UNCERRSEV_RD(i);
9277848SKrishna.Elango@Sun.COM
9287848SKrishna.Elango@Sun.COM if (nb5000_reset_uncor_pex)
9297848SKrishna.Elango@Sun.COM EMASK_UNCOR_PEX_WR(i, nb5000_mask_uncor_pex);
9307848SKrishna.Elango@Sun.COM if (nb5000_reset_cor_pex)
9317848SKrishna.Elango@Sun.COM EMASK_COR_PEX_WR(i, nb5000_mask_cor_pex);
9329783SAdrian.Frost@Sun.COM if (nb_chipset == INTEL_NB_5400) {
9339783SAdrian.Frost@Sun.COM /* disable masking of ERR pins used by DOCMD */
9349783SAdrian.Frost@Sun.COM PEX_ERR_PIN_MASK_WR(i, 0x10);
9357848SKrishna.Elango@Sun.COM }
9367532SSean.Ye@Sun.COM
9377848SKrishna.Elango@Sun.COM /* RP error message (CE/NFE/FE) detect mask */
9387848SKrishna.Elango@Sun.COM EMASK_RP_PEX_WR(i, nb5000_rp_pex);
9397532SSean.Ye@Sun.COM
9407848SKrishna.Elango@Sun.COM /* Command Register - Enable SERR */
9417848SKrishna.Elango@Sun.COM regw = nb_pci_getw(0, i, 0, PCI_CONF_COMM, 0);
9427848SKrishna.Elango@Sun.COM nb_pci_putw(0, i, 0, PCI_CONF_COMM,
9437848SKrishna.Elango@Sun.COM regw | PCI_COMM_SERR_ENABLE);
9447532SSean.Ye@Sun.COM
9457848SKrishna.Elango@Sun.COM /* Root Control Register - SERR on NFE/FE */
9467848SKrishna.Elango@Sun.COM PEXROOTCTL_WR(i, PCIE_ROOTCTL_SYS_ERR_ON_NFE_EN |
9477848SKrishna.Elango@Sun.COM PCIE_ROOTCTL_SYS_ERR_ON_FE_EN);
9487532SSean.Ye@Sun.COM
9497848SKrishna.Elango@Sun.COM /* AER UE Mask - Mask UR */
9507848SKrishna.Elango@Sun.COM UNCERRMSK_WR(i, PCIE_AER_UCE_UR);
9517532SSean.Ye@Sun.COM }
9527532SSean.Ye@Sun.COM
9537532SSean.Ye@Sun.COM static void
nb_pex_fini()9547532SSean.Ye@Sun.COM nb_pex_fini()
9557532SSean.Ye@Sun.COM {
9567848SKrishna.Elango@Sun.COM int i = 0; /* ESI port */
9577532SSean.Ye@Sun.COM
9587848SKrishna.Elango@Sun.COM EMASK_UNCOR_PEX_WR(i, emask_uncor_pex[i]);
9597848SKrishna.Elango@Sun.COM EMASK_COR_PEX_WR(i, emask_cor_pex[i]);
9607848SKrishna.Elango@Sun.COM EMASK_RP_PEX_WR(i, emask_rp_pex[i]);
9617848SKrishna.Elango@Sun.COM PEX_ERR_DOCMD_WR(i, docmd_pex[i]);
9627532SSean.Ye@Sun.COM
9637848SKrishna.Elango@Sun.COM if (nb5000_reset_uncor_pex)
9647848SKrishna.Elango@Sun.COM EMASK_UNCOR_PEX_WR(i, nb5000_mask_uncor_pex);
9657848SKrishna.Elango@Sun.COM if (nb5000_reset_cor_pex)
9667848SKrishna.Elango@Sun.COM EMASK_COR_PEX_WR(i, nb5000_mask_cor_pex);
9677532SSean.Ye@Sun.COM }
9687532SSean.Ye@Sun.COM
9697532SSean.Ye@Sun.COM void
nb_int_init()9707532SSean.Ye@Sun.COM nb_int_init()
9717532SSean.Ye@Sun.COM {
9729783SAdrian.Frost@Sun.COM uint32_t err0_int;
9739783SAdrian.Frost@Sun.COM uint32_t err1_int;
9749783SAdrian.Frost@Sun.COM uint32_t err2_int;
9759783SAdrian.Frost@Sun.COM uint32_t mcerr_int;
9767532SSean.Ye@Sun.COM uint32_t emask_int;
97710668SVuong.Nguyen@Sun.COM uint32_t nb_mask_bios_int;
97810668SVuong.Nguyen@Sun.COM uint32_t nb_mask_poll_int;
9797532SSean.Ye@Sun.COM uint16_t stepping;
9807532SSean.Ye@Sun.COM
98110668SVuong.Nguyen@Sun.COM if (nb_chipset == INTEL_NB_5100) {
98210668SVuong.Nguyen@Sun.COM nb_mask_bios_int = nb5100_mask_bios_int;
98310668SVuong.Nguyen@Sun.COM nb_mask_poll_int = nb5100_mask_poll_int;
98410668SVuong.Nguyen@Sun.COM } else {
98510668SVuong.Nguyen@Sun.COM nb_mask_bios_int = nb5000_mask_bios_int;
98610668SVuong.Nguyen@Sun.COM nb_mask_poll_int = nb5000_mask_poll_int;
98710668SVuong.Nguyen@Sun.COM }
9887532SSean.Ye@Sun.COM err0_int = ERR0_INT_RD();
9897532SSean.Ye@Sun.COM err1_int = ERR1_INT_RD();
9907532SSean.Ye@Sun.COM err2_int = ERR2_INT_RD();
9917532SSean.Ye@Sun.COM mcerr_int = MCERR_INT_RD();
9927532SSean.Ye@Sun.COM emask_int = EMASK_INT_RD();
9937532SSean.Ye@Sun.COM
9947532SSean.Ye@Sun.COM nb_err0_int = err0_int;
9957532SSean.Ye@Sun.COM nb_err1_int = err1_int;
9967532SSean.Ye@Sun.COM nb_err2_int = err2_int;
9977532SSean.Ye@Sun.COM nb_mcerr_int = mcerr_int;
9987532SSean.Ye@Sun.COM nb_emask_int = emask_int;
9997532SSean.Ye@Sun.COM
10009783SAdrian.Frost@Sun.COM ERR0_INT_WR(ERR_INT_ALL);
10019783SAdrian.Frost@Sun.COM ERR1_INT_WR(ERR_INT_ALL);
10029783SAdrian.Frost@Sun.COM ERR2_INT_WR(ERR_INT_ALL);
10039783SAdrian.Frost@Sun.COM MCERR_INT_WR(ERR_INT_ALL);
10049783SAdrian.Frost@Sun.COM EMASK_INT_WR(ERR_INT_ALL);
10057532SSean.Ye@Sun.COM
100610668SVuong.Nguyen@Sun.COM mcerr_int &= ~nb_mask_bios_int;
100710668SVuong.Nguyen@Sun.COM mcerr_int |= nb_mask_bios_int & (~err0_int | ~err1_int | ~err2_int);
100810668SVuong.Nguyen@Sun.COM mcerr_int |= nb_mask_poll_int;
100910668SVuong.Nguyen@Sun.COM err0_int |= nb_mask_poll_int;
101010668SVuong.Nguyen@Sun.COM err1_int |= nb_mask_poll_int;
101110668SVuong.Nguyen@Sun.COM err2_int |= nb_mask_poll_int;
10127532SSean.Ye@Sun.COM
10137532SSean.Ye@Sun.COM l_mcerr_int = mcerr_int;
10147532SSean.Ye@Sun.COM ERR0_INT_WR(err0_int);
10157532SSean.Ye@Sun.COM ERR1_INT_WR(err1_int);
10167532SSean.Ye@Sun.COM ERR2_INT_WR(err2_int);
10177532SSean.Ye@Sun.COM MCERR_INT_WR(mcerr_int);
10187532SSean.Ye@Sun.COM if (nb5000_reset_emask_int) {
10197532SSean.Ye@Sun.COM if (nb_chipset == INTEL_NB_7300) {
10207532SSean.Ye@Sun.COM stepping = NB5000_STEPPING();
10217532SSean.Ye@Sun.COM if (stepping == 0)
10227532SSean.Ye@Sun.COM EMASK_5000_INT_WR(nb7300_emask_int_step0);
10237532SSean.Ye@Sun.COM else
10247532SSean.Ye@Sun.COM EMASK_5000_INT_WR(nb7300_emask_int);
10257532SSean.Ye@Sun.COM } else if (nb_chipset == INTEL_NB_5400) {
10267532SSean.Ye@Sun.COM EMASK_5400_INT_WR(nb5400_emask_int |
10277532SSean.Ye@Sun.COM (emask_int & EMASK_INT_RES));
102810668SVuong.Nguyen@Sun.COM } else if (nb_chipset == INTEL_NB_5100) {
102910668SVuong.Nguyen@Sun.COM EMASK_5000_INT_WR(nb5100_emask_int);
10307532SSean.Ye@Sun.COM } else {
10317532SSean.Ye@Sun.COM EMASK_5000_INT_WR(nb5000_emask_int);
10327532SSean.Ye@Sun.COM }
10337532SSean.Ye@Sun.COM } else {
10347532SSean.Ye@Sun.COM EMASK_INT_WR(nb_emask_int);
10357532SSean.Ye@Sun.COM }
10367532SSean.Ye@Sun.COM }
10377532SSean.Ye@Sun.COM
10387532SSean.Ye@Sun.COM void
nb_int_fini()10397532SSean.Ye@Sun.COM nb_int_fini()
10407532SSean.Ye@Sun.COM {
10419783SAdrian.Frost@Sun.COM ERR0_INT_WR(ERR_INT_ALL);
10429783SAdrian.Frost@Sun.COM ERR1_INT_WR(ERR_INT_ALL);
10439783SAdrian.Frost@Sun.COM ERR2_INT_WR(ERR_INT_ALL);
10449783SAdrian.Frost@Sun.COM MCERR_INT_WR(ERR_INT_ALL);
10459783SAdrian.Frost@Sun.COM EMASK_INT_WR(ERR_INT_ALL);
10467532SSean.Ye@Sun.COM
10477532SSean.Ye@Sun.COM ERR0_INT_WR(nb_err0_int);
10487532SSean.Ye@Sun.COM ERR1_INT_WR(nb_err1_int);
10497532SSean.Ye@Sun.COM ERR2_INT_WR(nb_err2_int);
10507532SSean.Ye@Sun.COM MCERR_INT_WR(nb_mcerr_int);
10517532SSean.Ye@Sun.COM EMASK_INT_WR(nb_emask_int);
10527532SSean.Ye@Sun.COM }
10537532SSean.Ye@Sun.COM
10547532SSean.Ye@Sun.COM void
nb_int_mask_mc(uint32_t mc_mask_int)10557532SSean.Ye@Sun.COM nb_int_mask_mc(uint32_t mc_mask_int)
10567532SSean.Ye@Sun.COM {
10577532SSean.Ye@Sun.COM uint32_t emask_int;
10587532SSean.Ye@Sun.COM
10597532SSean.Ye@Sun.COM emask_int = MCERR_INT_RD();
10607532SSean.Ye@Sun.COM if ((emask_int & mc_mask_int) != mc_mask_int) {
10617532SSean.Ye@Sun.COM MCERR_INT_WR(emask_int|mc_mask_int);
10627532SSean.Ye@Sun.COM nb_mask_mc_set = 1;
10637532SSean.Ye@Sun.COM }
10647532SSean.Ye@Sun.COM }
10657532SSean.Ye@Sun.COM
106610049SVuong.Nguyen@Sun.COM static void
nb_fbd_init()10677532SSean.Ye@Sun.COM nb_fbd_init()
10687532SSean.Ye@Sun.COM {
10697532SSean.Ye@Sun.COM uint32_t err0_fbd;
10707532SSean.Ye@Sun.COM uint32_t err1_fbd;
10717532SSean.Ye@Sun.COM uint32_t err2_fbd;
10727532SSean.Ye@Sun.COM uint32_t mcerr_fbd;
10737532SSean.Ye@Sun.COM uint32_t emask_fbd;
10747532SSean.Ye@Sun.COM uint32_t emask_bios_fbd;
10757532SSean.Ye@Sun.COM uint32_t emask_poll_fbd;
10767532SSean.Ye@Sun.COM
10777532SSean.Ye@Sun.COM err0_fbd = ERR0_FBD_RD();
10787532SSean.Ye@Sun.COM err1_fbd = ERR1_FBD_RD();
10797532SSean.Ye@Sun.COM err2_fbd = ERR2_FBD_RD();
10807532SSean.Ye@Sun.COM mcerr_fbd = MCERR_FBD_RD();
10817532SSean.Ye@Sun.COM emask_fbd = EMASK_FBD_RD();
10827532SSean.Ye@Sun.COM
10837532SSean.Ye@Sun.COM nb_err0_fbd = err0_fbd;
10847532SSean.Ye@Sun.COM nb_err1_fbd = err1_fbd;
10857532SSean.Ye@Sun.COM nb_err2_fbd = err2_fbd;
10867532SSean.Ye@Sun.COM nb_mcerr_fbd = mcerr_fbd;
10877532SSean.Ye@Sun.COM nb_emask_fbd = emask_fbd;
10887532SSean.Ye@Sun.COM
10897532SSean.Ye@Sun.COM ERR0_FBD_WR(0xffffffff);
10907532SSean.Ye@Sun.COM ERR1_FBD_WR(0xffffffff);
10917532SSean.Ye@Sun.COM ERR2_FBD_WR(0xffffffff);
10927532SSean.Ye@Sun.COM MCERR_FBD_WR(0xffffffff);
10937532SSean.Ye@Sun.COM EMASK_FBD_WR(0xffffffff);
10947532SSean.Ye@Sun.COM
109510668SVuong.Nguyen@Sun.COM if (nb_chipset == INTEL_NB_7300) {
109610668SVuong.Nguyen@Sun.COM if (nb_mode == NB_MEMORY_MIRROR) {
109710668SVuong.Nguyen@Sun.COM /* MCH 7300 errata 34 */
109810668SVuong.Nguyen@Sun.COM emask_bios_fbd = nb7300_mask_bios_fbd & ~EMASK_FBD_M23;
109910668SVuong.Nguyen@Sun.COM emask_poll_fbd = nb7300_mask_poll_fbd;
110010668SVuong.Nguyen@Sun.COM mcerr_fbd |= EMASK_FBD_M23;
110110668SVuong.Nguyen@Sun.COM } else {
110210668SVuong.Nguyen@Sun.COM emask_bios_fbd = nb7300_mask_bios_fbd;
110310668SVuong.Nguyen@Sun.COM emask_poll_fbd = nb7300_mask_poll_fbd;
110410668SVuong.Nguyen@Sun.COM }
11057532SSean.Ye@Sun.COM } else if (nb_chipset == INTEL_NB_5400) {
11067532SSean.Ye@Sun.COM emask_bios_fbd = nb5400_mask_bios_fbd;
11077532SSean.Ye@Sun.COM emask_poll_fbd = nb5400_mask_poll_fbd;
11087532SSean.Ye@Sun.COM } else {
11097532SSean.Ye@Sun.COM emask_bios_fbd = nb5000_mask_bios_fbd;
11107532SSean.Ye@Sun.COM emask_poll_fbd = nb5000_mask_poll_fbd;
11117532SSean.Ye@Sun.COM }
11127532SSean.Ye@Sun.COM mcerr_fbd &= ~emask_bios_fbd;
11137532SSean.Ye@Sun.COM mcerr_fbd |= emask_bios_fbd & (~err0_fbd | ~err1_fbd | ~err2_fbd);
11147532SSean.Ye@Sun.COM mcerr_fbd |= emask_poll_fbd;
11157532SSean.Ye@Sun.COM err0_fbd |= emask_poll_fbd;
11167532SSean.Ye@Sun.COM err1_fbd |= emask_poll_fbd;
11177532SSean.Ye@Sun.COM err2_fbd |= emask_poll_fbd;
11187532SSean.Ye@Sun.COM
11197532SSean.Ye@Sun.COM l_mcerr_fbd = mcerr_fbd;
11207532SSean.Ye@Sun.COM ERR0_FBD_WR(err0_fbd);
11217532SSean.Ye@Sun.COM ERR1_FBD_WR(err1_fbd);
11227532SSean.Ye@Sun.COM ERR2_FBD_WR(err2_fbd);
11237532SSean.Ye@Sun.COM MCERR_FBD_WR(mcerr_fbd);
11247532SSean.Ye@Sun.COM if (nb5000_reset_emask_fbd) {
11257532SSean.Ye@Sun.COM if (nb_chipset == INTEL_NB_5400)
11267532SSean.Ye@Sun.COM EMASK_FBD_WR(nb5400_emask_fbd);
11277532SSean.Ye@Sun.COM else
11287532SSean.Ye@Sun.COM EMASK_FBD_WR(nb5000_emask_fbd);
11297532SSean.Ye@Sun.COM } else {
11307532SSean.Ye@Sun.COM EMASK_FBD_WR(nb_emask_fbd);
11317532SSean.Ye@Sun.COM }
11327532SSean.Ye@Sun.COM }
11337532SSean.Ye@Sun.COM
11347532SSean.Ye@Sun.COM void
nb_fbd_mask_mc(uint32_t mc_mask_fbd)11357532SSean.Ye@Sun.COM nb_fbd_mask_mc(uint32_t mc_mask_fbd)
11367532SSean.Ye@Sun.COM {
11377532SSean.Ye@Sun.COM uint32_t emask_fbd;
11387532SSean.Ye@Sun.COM
11397532SSean.Ye@Sun.COM emask_fbd = MCERR_FBD_RD();
11407532SSean.Ye@Sun.COM if ((emask_fbd & mc_mask_fbd) != mc_mask_fbd) {
11417532SSean.Ye@Sun.COM MCERR_FBD_WR(emask_fbd|mc_mask_fbd);
11427532SSean.Ye@Sun.COM nb_mask_mc_set = 1;
11437532SSean.Ye@Sun.COM }
11447532SSean.Ye@Sun.COM }
11457532SSean.Ye@Sun.COM
114610049SVuong.Nguyen@Sun.COM static void
nb_fbd_fini()11477532SSean.Ye@Sun.COM nb_fbd_fini()
11487532SSean.Ye@Sun.COM {
11497532SSean.Ye@Sun.COM ERR0_FBD_WR(0xffffffff);
11507532SSean.Ye@Sun.COM ERR1_FBD_WR(0xffffffff);
11517532SSean.Ye@Sun.COM ERR2_FBD_WR(0xffffffff);
11527532SSean.Ye@Sun.COM MCERR_FBD_WR(0xffffffff);
11537532SSean.Ye@Sun.COM EMASK_FBD_WR(0xffffffff);
11547532SSean.Ye@Sun.COM
11557532SSean.Ye@Sun.COM ERR0_FBD_WR(nb_err0_fbd);
11567532SSean.Ye@Sun.COM ERR1_FBD_WR(nb_err1_fbd);
11577532SSean.Ye@Sun.COM ERR2_FBD_WR(nb_err2_fbd);
11587532SSean.Ye@Sun.COM MCERR_FBD_WR(nb_mcerr_fbd);
11597532SSean.Ye@Sun.COM EMASK_FBD_WR(nb_emask_fbd);
11607532SSean.Ye@Sun.COM }
11617532SSean.Ye@Sun.COM
11627532SSean.Ye@Sun.COM static void
nb_mem_init()116310049SVuong.Nguyen@Sun.COM nb_mem_init()
116410049SVuong.Nguyen@Sun.COM {
116510049SVuong.Nguyen@Sun.COM uint32_t err0_mem;
116610049SVuong.Nguyen@Sun.COM uint32_t err1_mem;
116710049SVuong.Nguyen@Sun.COM uint32_t err2_mem;
116810049SVuong.Nguyen@Sun.COM uint32_t mcerr_mem;
116910049SVuong.Nguyen@Sun.COM uint32_t emask_mem;
117010049SVuong.Nguyen@Sun.COM uint32_t emask_poll_mem;
117110049SVuong.Nguyen@Sun.COM
117210049SVuong.Nguyen@Sun.COM err0_mem = ERR0_MEM_RD();
117310049SVuong.Nguyen@Sun.COM err1_mem = ERR1_MEM_RD();
117410049SVuong.Nguyen@Sun.COM err2_mem = ERR2_MEM_RD();
117510049SVuong.Nguyen@Sun.COM mcerr_mem = MCERR_MEM_RD();
117610049SVuong.Nguyen@Sun.COM emask_mem = EMASK_MEM_RD();
117710049SVuong.Nguyen@Sun.COM
117810049SVuong.Nguyen@Sun.COM nb_err0_mem = err0_mem;
117910049SVuong.Nguyen@Sun.COM nb_err1_mem = err1_mem;
118010049SVuong.Nguyen@Sun.COM nb_err2_mem = err2_mem;
118110049SVuong.Nguyen@Sun.COM nb_mcerr_mem = mcerr_mem;
118210049SVuong.Nguyen@Sun.COM nb_emask_mem = emask_mem;
118310049SVuong.Nguyen@Sun.COM
118410049SVuong.Nguyen@Sun.COM ERR0_MEM_WR(0xffffffff);
118510049SVuong.Nguyen@Sun.COM ERR1_MEM_WR(0xffffffff);
118610049SVuong.Nguyen@Sun.COM ERR2_MEM_WR(0xffffffff);
118710049SVuong.Nguyen@Sun.COM MCERR_MEM_WR(0xffffffff);
118810049SVuong.Nguyen@Sun.COM EMASK_MEM_WR(0xffffffff);
118910049SVuong.Nguyen@Sun.COM
119010049SVuong.Nguyen@Sun.COM emask_poll_mem = nb5100_mask_poll_mem;
119110049SVuong.Nguyen@Sun.COM mcerr_mem |= emask_poll_mem;
119210049SVuong.Nguyen@Sun.COM err0_mem |= emask_poll_mem;
119310049SVuong.Nguyen@Sun.COM err1_mem |= emask_poll_mem;
119410049SVuong.Nguyen@Sun.COM err2_mem |= emask_poll_mem;
119510049SVuong.Nguyen@Sun.COM
119610049SVuong.Nguyen@Sun.COM l_mcerr_mem = mcerr_mem;
119710049SVuong.Nguyen@Sun.COM ERR0_MEM_WR(err0_mem);
119810049SVuong.Nguyen@Sun.COM ERR1_MEM_WR(err1_mem);
119910049SVuong.Nguyen@Sun.COM ERR2_MEM_WR(err2_mem);
120010049SVuong.Nguyen@Sun.COM MCERR_MEM_WR(mcerr_mem);
120110049SVuong.Nguyen@Sun.COM if (nb5100_reset_emask_mem) {
120210049SVuong.Nguyen@Sun.COM EMASK_MEM_WR(~nb5100_mask_poll_mem);
120310049SVuong.Nguyen@Sun.COM } else {
120410049SVuong.Nguyen@Sun.COM EMASK_MEM_WR(nb_emask_mem);
120510049SVuong.Nguyen@Sun.COM }
120610049SVuong.Nguyen@Sun.COM }
120710049SVuong.Nguyen@Sun.COM
120810049SVuong.Nguyen@Sun.COM void
nb_mem_mask_mc(uint32_t mc_mask_mem)120910049SVuong.Nguyen@Sun.COM nb_mem_mask_mc(uint32_t mc_mask_mem)
121010049SVuong.Nguyen@Sun.COM {
121110049SVuong.Nguyen@Sun.COM uint32_t emask_mem;
121210049SVuong.Nguyen@Sun.COM
121310049SVuong.Nguyen@Sun.COM emask_mem = MCERR_MEM_RD();
121410049SVuong.Nguyen@Sun.COM if ((emask_mem & mc_mask_mem) != mc_mask_mem) {
121510049SVuong.Nguyen@Sun.COM MCERR_MEM_WR(emask_mem|mc_mask_mem);
121610049SVuong.Nguyen@Sun.COM nb_mask_mc_set = 1;
121710049SVuong.Nguyen@Sun.COM }
121810049SVuong.Nguyen@Sun.COM }
121910049SVuong.Nguyen@Sun.COM
122010049SVuong.Nguyen@Sun.COM static void
nb_mem_fini()122110049SVuong.Nguyen@Sun.COM nb_mem_fini()
122210049SVuong.Nguyen@Sun.COM {
122310049SVuong.Nguyen@Sun.COM ERR0_MEM_WR(0xffffffff);
122410049SVuong.Nguyen@Sun.COM ERR1_MEM_WR(0xffffffff);
122510049SVuong.Nguyen@Sun.COM ERR2_MEM_WR(0xffffffff);
122610049SVuong.Nguyen@Sun.COM MCERR_MEM_WR(0xffffffff);
122710049SVuong.Nguyen@Sun.COM EMASK_MEM_WR(0xffffffff);
122810049SVuong.Nguyen@Sun.COM
122910049SVuong.Nguyen@Sun.COM ERR0_MEM_WR(nb_err0_mem);
123010049SVuong.Nguyen@Sun.COM ERR1_MEM_WR(nb_err1_mem);
123110049SVuong.Nguyen@Sun.COM ERR2_MEM_WR(nb_err2_mem);
123210049SVuong.Nguyen@Sun.COM MCERR_MEM_WR(nb_mcerr_mem);
123310049SVuong.Nguyen@Sun.COM EMASK_MEM_WR(nb_emask_mem);
123410049SVuong.Nguyen@Sun.COM }
123510049SVuong.Nguyen@Sun.COM
123610049SVuong.Nguyen@Sun.COM static void
nb_fsb_init()12377532SSean.Ye@Sun.COM nb_fsb_init()
12387532SSean.Ye@Sun.COM {
12397532SSean.Ye@Sun.COM uint16_t err0_fsb;
12407532SSean.Ye@Sun.COM uint16_t err1_fsb;
12417532SSean.Ye@Sun.COM uint16_t err2_fsb;
12427532SSean.Ye@Sun.COM uint16_t mcerr_fsb;
12437532SSean.Ye@Sun.COM uint16_t emask_fsb;
12447532SSean.Ye@Sun.COM
12457532SSean.Ye@Sun.COM err0_fsb = ERR0_FSB_RD(0);
12467532SSean.Ye@Sun.COM err1_fsb = ERR1_FSB_RD(0);
12477532SSean.Ye@Sun.COM err2_fsb = ERR2_FSB_RD(0);
12487532SSean.Ye@Sun.COM mcerr_fsb = MCERR_FSB_RD(0);
12497532SSean.Ye@Sun.COM emask_fsb = EMASK_FSB_RD(0);
12507532SSean.Ye@Sun.COM
12517532SSean.Ye@Sun.COM ERR0_FSB_WR(0, 0xffff);
12527532SSean.Ye@Sun.COM ERR1_FSB_WR(0, 0xffff);
12537532SSean.Ye@Sun.COM ERR2_FSB_WR(0, 0xffff);
12547532SSean.Ye@Sun.COM MCERR_FSB_WR(0, 0xffff);
12557532SSean.Ye@Sun.COM EMASK_FSB_WR(0, 0xffff);
12567532SSean.Ye@Sun.COM
12577532SSean.Ye@Sun.COM ERR0_FSB_WR(1, 0xffff);
12587532SSean.Ye@Sun.COM ERR1_FSB_WR(1, 0xffff);
12597532SSean.Ye@Sun.COM ERR2_FSB_WR(1, 0xffff);
12607532SSean.Ye@Sun.COM MCERR_FSB_WR(1, 0xffff);
12617532SSean.Ye@Sun.COM EMASK_FSB_WR(1, 0xffff);
12627532SSean.Ye@Sun.COM
12637532SSean.Ye@Sun.COM nb_err0_fsb = err0_fsb;
12647532SSean.Ye@Sun.COM nb_err1_fsb = err1_fsb;
12657532SSean.Ye@Sun.COM nb_err2_fsb = err2_fsb;
12667532SSean.Ye@Sun.COM nb_mcerr_fsb = mcerr_fsb;
12677532SSean.Ye@Sun.COM nb_emask_fsb = emask_fsb;
12687532SSean.Ye@Sun.COM
12697532SSean.Ye@Sun.COM mcerr_fsb &= ~nb5000_mask_bios_fsb;
12707532SSean.Ye@Sun.COM mcerr_fsb |= nb5000_mask_bios_fsb & (~err2_fsb | ~err1_fsb | ~err0_fsb);
12717532SSean.Ye@Sun.COM mcerr_fsb |= nb5000_mask_poll_fsb;
12727532SSean.Ye@Sun.COM err0_fsb |= nb5000_mask_poll_fsb;
12737532SSean.Ye@Sun.COM err1_fsb |= nb5000_mask_poll_fsb;
12747532SSean.Ye@Sun.COM err2_fsb |= nb5000_mask_poll_fsb;
12757532SSean.Ye@Sun.COM
12767532SSean.Ye@Sun.COM l_mcerr_fsb = mcerr_fsb;
12777532SSean.Ye@Sun.COM ERR0_FSB_WR(0, err0_fsb);
12787532SSean.Ye@Sun.COM ERR1_FSB_WR(0, err1_fsb);
12797532SSean.Ye@Sun.COM ERR2_FSB_WR(0, err2_fsb);
12807532SSean.Ye@Sun.COM MCERR_FSB_WR(0, mcerr_fsb);
12817532SSean.Ye@Sun.COM if (nb5000_reset_emask_fsb) {
12827532SSean.Ye@Sun.COM EMASK_FSB_WR(0, nb5000_emask_fsb);
12837532SSean.Ye@Sun.COM } else {
12847532SSean.Ye@Sun.COM EMASK_FSB_WR(0, nb_emask_fsb);
12857532SSean.Ye@Sun.COM }
12867532SSean.Ye@Sun.COM
12877532SSean.Ye@Sun.COM ERR0_FSB_WR(1, err0_fsb);
12887532SSean.Ye@Sun.COM ERR1_FSB_WR(1, err1_fsb);
12897532SSean.Ye@Sun.COM ERR2_FSB_WR(1, err2_fsb);
12907532SSean.Ye@Sun.COM MCERR_FSB_WR(1, mcerr_fsb);
12917532SSean.Ye@Sun.COM if (nb5000_reset_emask_fsb) {
12927532SSean.Ye@Sun.COM EMASK_FSB_WR(1, nb5000_emask_fsb);
12937532SSean.Ye@Sun.COM } else {
12947532SSean.Ye@Sun.COM EMASK_FSB_WR(1, nb_emask_fsb);
12957532SSean.Ye@Sun.COM }
12967532SSean.Ye@Sun.COM
12977532SSean.Ye@Sun.COM if (nb_chipset == INTEL_NB_7300) {
12987532SSean.Ye@Sun.COM ERR0_FSB_WR(2, 0xffff);
12997532SSean.Ye@Sun.COM ERR1_FSB_WR(2, 0xffff);
13007532SSean.Ye@Sun.COM ERR2_FSB_WR(2, 0xffff);
13017532SSean.Ye@Sun.COM MCERR_FSB_WR(2, 0xffff);
13027532SSean.Ye@Sun.COM EMASK_FSB_WR(2, 0xffff);
13037532SSean.Ye@Sun.COM
13047532SSean.Ye@Sun.COM ERR0_FSB_WR(3, 0xffff);
13057532SSean.Ye@Sun.COM ERR1_FSB_WR(3, 0xffff);
13067532SSean.Ye@Sun.COM ERR2_FSB_WR(3, 0xffff);
13077532SSean.Ye@Sun.COM MCERR_FSB_WR(3, 0xffff);
13087532SSean.Ye@Sun.COM EMASK_FSB_WR(3, 0xffff);
13097532SSean.Ye@Sun.COM
13107532SSean.Ye@Sun.COM ERR0_FSB_WR(2, err0_fsb);
13117532SSean.Ye@Sun.COM ERR1_FSB_WR(2, err1_fsb);
13127532SSean.Ye@Sun.COM ERR2_FSB_WR(2, err2_fsb);
13137532SSean.Ye@Sun.COM MCERR_FSB_WR(2, mcerr_fsb);
13147532SSean.Ye@Sun.COM if (nb5000_reset_emask_fsb) {
13157532SSean.Ye@Sun.COM EMASK_FSB_WR(2, nb5000_emask_fsb);
13167532SSean.Ye@Sun.COM } else {
13177532SSean.Ye@Sun.COM EMASK_FSB_WR(2, nb_emask_fsb);
13187532SSean.Ye@Sun.COM }
13197532SSean.Ye@Sun.COM
13207532SSean.Ye@Sun.COM ERR0_FSB_WR(3, err0_fsb);
13217532SSean.Ye@Sun.COM ERR1_FSB_WR(3, err1_fsb);
13227532SSean.Ye@Sun.COM ERR2_FSB_WR(3, err2_fsb);
13237532SSean.Ye@Sun.COM MCERR_FSB_WR(3, mcerr_fsb);
13247532SSean.Ye@Sun.COM if (nb5000_reset_emask_fsb) {
13257532SSean.Ye@Sun.COM EMASK_FSB_WR(3, nb5000_emask_fsb);
13267532SSean.Ye@Sun.COM } else {
13277532SSean.Ye@Sun.COM EMASK_FSB_WR(3, nb_emask_fsb);
13287532SSean.Ye@Sun.COM }
13297532SSean.Ye@Sun.COM }
13307532SSean.Ye@Sun.COM }
13317532SSean.Ye@Sun.COM
13327532SSean.Ye@Sun.COM static void
nb_fsb_fini()13337532SSean.Ye@Sun.COM nb_fsb_fini() {
13347532SSean.Ye@Sun.COM ERR0_FSB_WR(0, 0xffff);
13357532SSean.Ye@Sun.COM ERR1_FSB_WR(0, 0xffff);
13367532SSean.Ye@Sun.COM ERR2_FSB_WR(0, 0xffff);
13377532SSean.Ye@Sun.COM MCERR_FSB_WR(0, 0xffff);
13387532SSean.Ye@Sun.COM EMASK_FSB_WR(0, 0xffff);
13397532SSean.Ye@Sun.COM
13407532SSean.Ye@Sun.COM ERR0_FSB_WR(0, nb_err0_fsb);
13417532SSean.Ye@Sun.COM ERR1_FSB_WR(0, nb_err1_fsb);
13427532SSean.Ye@Sun.COM ERR2_FSB_WR(0, nb_err2_fsb);
13437532SSean.Ye@Sun.COM MCERR_FSB_WR(0, nb_mcerr_fsb);
13447532SSean.Ye@Sun.COM EMASK_FSB_WR(0, nb_emask_fsb);
13457532SSean.Ye@Sun.COM
13467532SSean.Ye@Sun.COM ERR0_FSB_WR(1, 0xffff);
13477532SSean.Ye@Sun.COM ERR1_FSB_WR(1, 0xffff);
13487532SSean.Ye@Sun.COM ERR2_FSB_WR(1, 0xffff);
13497532SSean.Ye@Sun.COM MCERR_FSB_WR(1, 0xffff);
13507532SSean.Ye@Sun.COM EMASK_FSB_WR(1, 0xffff);
13517532SSean.Ye@Sun.COM
13527532SSean.Ye@Sun.COM ERR0_FSB_WR(1, nb_err0_fsb);
13537532SSean.Ye@Sun.COM ERR1_FSB_WR(1, nb_err1_fsb);
13547532SSean.Ye@Sun.COM ERR2_FSB_WR(1, nb_err2_fsb);
13557532SSean.Ye@Sun.COM MCERR_FSB_WR(1, nb_mcerr_fsb);
13567532SSean.Ye@Sun.COM EMASK_FSB_WR(1, nb_emask_fsb);
13577532SSean.Ye@Sun.COM
13587532SSean.Ye@Sun.COM if (nb_chipset == INTEL_NB_7300) {
13597532SSean.Ye@Sun.COM ERR0_FSB_WR(2, 0xffff);
13607532SSean.Ye@Sun.COM ERR1_FSB_WR(2, 0xffff);
13617532SSean.Ye@Sun.COM ERR2_FSB_WR(2, 0xffff);
13627532SSean.Ye@Sun.COM MCERR_FSB_WR(2, 0xffff);
13637532SSean.Ye@Sun.COM EMASK_FSB_WR(2, 0xffff);
13647532SSean.Ye@Sun.COM
13657532SSean.Ye@Sun.COM ERR0_FSB_WR(2, nb_err0_fsb);
13667532SSean.Ye@Sun.COM ERR1_FSB_WR(2, nb_err1_fsb);
13677532SSean.Ye@Sun.COM ERR2_FSB_WR(2, nb_err2_fsb);
13687532SSean.Ye@Sun.COM MCERR_FSB_WR(2, nb_mcerr_fsb);
13697532SSean.Ye@Sun.COM EMASK_FSB_WR(2, nb_emask_fsb);
13707532SSean.Ye@Sun.COM
13717532SSean.Ye@Sun.COM ERR0_FSB_WR(3, 0xffff);
13727532SSean.Ye@Sun.COM ERR1_FSB_WR(3, 0xffff);
13737532SSean.Ye@Sun.COM ERR2_FSB_WR(3, 0xffff);
13747532SSean.Ye@Sun.COM MCERR_FSB_WR(3, 0xffff);
13757532SSean.Ye@Sun.COM EMASK_FSB_WR(3, 0xffff);
13767532SSean.Ye@Sun.COM
13777532SSean.Ye@Sun.COM ERR0_FSB_WR(3, nb_err0_fsb);
13787532SSean.Ye@Sun.COM ERR1_FSB_WR(3, nb_err1_fsb);
13797532SSean.Ye@Sun.COM ERR2_FSB_WR(3, nb_err2_fsb);
13807532SSean.Ye@Sun.COM MCERR_FSB_WR(3, nb_mcerr_fsb);
13817532SSean.Ye@Sun.COM EMASK_FSB_WR(3, nb_emask_fsb);
13827532SSean.Ye@Sun.COM }
13837532SSean.Ye@Sun.COM }
13847532SSean.Ye@Sun.COM
13857532SSean.Ye@Sun.COM void
nb_fsb_mask_mc(int fsb,uint16_t mc_mask_fsb)13867532SSean.Ye@Sun.COM nb_fsb_mask_mc(int fsb, uint16_t mc_mask_fsb)
13877532SSean.Ye@Sun.COM {
13887532SSean.Ye@Sun.COM uint16_t emask_fsb;
13897532SSean.Ye@Sun.COM
13907532SSean.Ye@Sun.COM emask_fsb = MCERR_FSB_RD(fsb);
13917532SSean.Ye@Sun.COM if ((emask_fsb & mc_mask_fsb) != mc_mask_fsb) {
13927532SSean.Ye@Sun.COM MCERR_FSB_WR(fsb, emask_fsb|mc_mask_fsb|EMASK_FBD_RES);
13937532SSean.Ye@Sun.COM nb_mask_mc_set = 1;
13947532SSean.Ye@Sun.COM }
13957532SSean.Ye@Sun.COM }
13967532SSean.Ye@Sun.COM
13977532SSean.Ye@Sun.COM static void
nb_thr_init()13987532SSean.Ye@Sun.COM nb_thr_init()
13997532SSean.Ye@Sun.COM {
14007532SSean.Ye@Sun.COM uint16_t err0_thr;
14017532SSean.Ye@Sun.COM uint16_t err1_thr;
14027532SSean.Ye@Sun.COM uint16_t err2_thr;
14037532SSean.Ye@Sun.COM uint16_t mcerr_thr;
14047532SSean.Ye@Sun.COM uint16_t emask_thr;
14057532SSean.Ye@Sun.COM
14067532SSean.Ye@Sun.COM if (nb_chipset == INTEL_NB_5400) {
14077532SSean.Ye@Sun.COM err0_thr = ERR0_THR_RD(0);
14087532SSean.Ye@Sun.COM err1_thr = ERR1_THR_RD(0);
14097532SSean.Ye@Sun.COM err2_thr = ERR2_THR_RD(0);
14107532SSean.Ye@Sun.COM mcerr_thr = MCERR_THR_RD(0);
14117532SSean.Ye@Sun.COM emask_thr = EMASK_THR_RD(0);
14127532SSean.Ye@Sun.COM
14137532SSean.Ye@Sun.COM ERR0_THR_WR(0xffff);
14147532SSean.Ye@Sun.COM ERR1_THR_WR(0xffff);
14157532SSean.Ye@Sun.COM ERR2_THR_WR(0xffff);
14167532SSean.Ye@Sun.COM MCERR_THR_WR(0xffff);
14177532SSean.Ye@Sun.COM EMASK_THR_WR(0xffff);
14187532SSean.Ye@Sun.COM
14197532SSean.Ye@Sun.COM nb_err0_thr = err0_thr;
14207532SSean.Ye@Sun.COM nb_err1_thr = err1_thr;
14217532SSean.Ye@Sun.COM nb_err2_thr = err2_thr;
14227532SSean.Ye@Sun.COM nb_mcerr_thr = mcerr_thr;
14237532SSean.Ye@Sun.COM nb_emask_thr = emask_thr;
14247532SSean.Ye@Sun.COM
14257532SSean.Ye@Sun.COM mcerr_thr &= ~nb_mask_bios_thr;
14267532SSean.Ye@Sun.COM mcerr_thr |= nb_mask_bios_thr &
14277532SSean.Ye@Sun.COM (~err2_thr | ~err1_thr | ~err0_thr);
14287532SSean.Ye@Sun.COM mcerr_thr |= nb_mask_poll_thr;
14297532SSean.Ye@Sun.COM err0_thr |= nb_mask_poll_thr;
14307532SSean.Ye@Sun.COM err1_thr |= nb_mask_poll_thr;
14317532SSean.Ye@Sun.COM err2_thr |= nb_mask_poll_thr;
14327532SSean.Ye@Sun.COM
14337532SSean.Ye@Sun.COM l_mcerr_thr = mcerr_thr;
14347532SSean.Ye@Sun.COM ERR0_THR_WR(err0_thr);
14357532SSean.Ye@Sun.COM ERR1_THR_WR(err1_thr);
14367532SSean.Ye@Sun.COM ERR2_THR_WR(err2_thr);
14377532SSean.Ye@Sun.COM MCERR_THR_WR(mcerr_thr);
14387532SSean.Ye@Sun.COM EMASK_THR_WR(nb_emask_thr);
14397532SSean.Ye@Sun.COM }
14407532SSean.Ye@Sun.COM }
14417532SSean.Ye@Sun.COM
14427532SSean.Ye@Sun.COM static void
nb_thr_fini()14437532SSean.Ye@Sun.COM nb_thr_fini()
14447532SSean.Ye@Sun.COM {
14457532SSean.Ye@Sun.COM if (nb_chipset == INTEL_NB_5400) {
14467532SSean.Ye@Sun.COM ERR0_THR_WR(0xffff);
14477532SSean.Ye@Sun.COM ERR1_THR_WR(0xffff);
14487532SSean.Ye@Sun.COM ERR2_THR_WR(0xffff);
14497532SSean.Ye@Sun.COM MCERR_THR_WR(0xffff);
14507532SSean.Ye@Sun.COM EMASK_THR_WR(0xffff);
14517532SSean.Ye@Sun.COM
14527532SSean.Ye@Sun.COM ERR0_THR_WR(nb_err0_thr);
14537532SSean.Ye@Sun.COM ERR1_THR_WR(nb_err1_thr);
14547532SSean.Ye@Sun.COM ERR2_THR_WR(nb_err2_thr);
14557532SSean.Ye@Sun.COM MCERR_THR_WR(nb_mcerr_thr);
14567532SSean.Ye@Sun.COM EMASK_THR_WR(nb_emask_thr);
14577532SSean.Ye@Sun.COM }
14587532SSean.Ye@Sun.COM }
14597532SSean.Ye@Sun.COM
14607532SSean.Ye@Sun.COM void
nb_thr_mask_mc(uint16_t mc_mask_thr)14617532SSean.Ye@Sun.COM nb_thr_mask_mc(uint16_t mc_mask_thr)
14627532SSean.Ye@Sun.COM {
14637532SSean.Ye@Sun.COM uint16_t emask_thr;
14647532SSean.Ye@Sun.COM
14657532SSean.Ye@Sun.COM emask_thr = MCERR_THR_RD(0);
14667532SSean.Ye@Sun.COM if ((emask_thr & mc_mask_thr) != mc_mask_thr) {
14677532SSean.Ye@Sun.COM MCERR_THR_WR(emask_thr|mc_mask_thr);
14687532SSean.Ye@Sun.COM nb_mask_mc_set = 1;
14697532SSean.Ye@Sun.COM }
14707532SSean.Ye@Sun.COM }
14717532SSean.Ye@Sun.COM
14727532SSean.Ye@Sun.COM void
nb_mask_mc_reset()14737532SSean.Ye@Sun.COM nb_mask_mc_reset()
14747532SSean.Ye@Sun.COM {
147510049SVuong.Nguyen@Sun.COM if (nb_chipset == INTEL_NB_5100)
147610049SVuong.Nguyen@Sun.COM MCERR_MEM_WR(l_mcerr_mem);
147710049SVuong.Nguyen@Sun.COM else
147810049SVuong.Nguyen@Sun.COM MCERR_FBD_WR(l_mcerr_fbd);
14797532SSean.Ye@Sun.COM MCERR_INT_WR(l_mcerr_int);
14807532SSean.Ye@Sun.COM MCERR_FSB_WR(0, l_mcerr_fsb);
14817532SSean.Ye@Sun.COM MCERR_FSB_WR(1, l_mcerr_fsb);
14827532SSean.Ye@Sun.COM if (nb_chipset == INTEL_NB_7300) {
14837532SSean.Ye@Sun.COM MCERR_FSB_WR(2, l_mcerr_fsb);
14847532SSean.Ye@Sun.COM MCERR_FSB_WR(3, l_mcerr_fsb);
14857532SSean.Ye@Sun.COM }
14867532SSean.Ye@Sun.COM if (nb_chipset == INTEL_NB_5400) {
14877532SSean.Ye@Sun.COM MCERR_THR_WR(l_mcerr_thr);
14887532SSean.Ye@Sun.COM }
14897532SSean.Ye@Sun.COM }
14907532SSean.Ye@Sun.COM
14917532SSean.Ye@Sun.COM int
nb_dev_init()14927532SSean.Ye@Sun.COM nb_dev_init()
14937532SSean.Ye@Sun.COM {
14947532SSean.Ye@Sun.COM find_dimm_label_t *label_function_p;
14957532SSean.Ye@Sun.COM
14967532SSean.Ye@Sun.COM label_function_p = find_dimms_per_channel();
14977532SSean.Ye@Sun.COM mutex_init(&nb_mutex, NULL, MUTEX_DRIVER, NULL);
14987532SSean.Ye@Sun.COM nb_queue = errorq_create("nb_queue", nb_drain, NULL, NB_MAX_ERRORS,
14997532SSean.Ye@Sun.COM sizeof (nb_logout_t), 1, ERRORQ_VITAL);
15007532SSean.Ye@Sun.COM if (nb_queue == NULL) {
15017532SSean.Ye@Sun.COM mutex_destroy(&nb_mutex);
15027532SSean.Ye@Sun.COM return (EAGAIN);
15037532SSean.Ye@Sun.COM }
15047532SSean.Ye@Sun.COM nb_int_init();
15057532SSean.Ye@Sun.COM nb_thr_init();
15067532SSean.Ye@Sun.COM dimm_init();
15077532SSean.Ye@Sun.COM nb_dimms_init(label_function_p);
15087532SSean.Ye@Sun.COM nb_mc_init();
15097532SSean.Ye@Sun.COM nb_pex_init();
151010049SVuong.Nguyen@Sun.COM if (nb_chipset == INTEL_NB_5100)
151110049SVuong.Nguyen@Sun.COM nb_mem_init();
151210049SVuong.Nguyen@Sun.COM else
151310049SVuong.Nguyen@Sun.COM nb_fbd_init();
15147532SSean.Ye@Sun.COM nb_fsb_init();
15157532SSean.Ye@Sun.COM nb_scrubber_enable();
15167532SSean.Ye@Sun.COM return (0);
15177532SSean.Ye@Sun.COM }
15187532SSean.Ye@Sun.COM
15197532SSean.Ye@Sun.COM int
nb_init()15207532SSean.Ye@Sun.COM nb_init()
15217532SSean.Ye@Sun.COM {
15227532SSean.Ye@Sun.COM /* return ENOTSUP if there is no PCI config space support. */
15237532SSean.Ye@Sun.COM if (pci_getl_func == NULL)
15247532SSean.Ye@Sun.COM return (ENOTSUP);
15257532SSean.Ye@Sun.COM
15267532SSean.Ye@Sun.COM /* get vendor and device */
15277532SSean.Ye@Sun.COM nb_chipset = (*pci_getl_func)(0, 0, 0, PCI_CONF_VENID);
15287532SSean.Ye@Sun.COM switch (nb_chipset) {
15297532SSean.Ye@Sun.COM default:
15307532SSean.Ye@Sun.COM if (nb_5000_memory_controller == 0)
15317532SSean.Ye@Sun.COM return (ENOTSUP);
15327532SSean.Ye@Sun.COM break;
15337532SSean.Ye@Sun.COM case INTEL_NB_7300:
15347532SSean.Ye@Sun.COM case INTEL_NB_5000P:
15357532SSean.Ye@Sun.COM case INTEL_NB_5000X:
15367532SSean.Ye@Sun.COM break;
15377532SSean.Ye@Sun.COM case INTEL_NB_5000V:
15387532SSean.Ye@Sun.COM case INTEL_NB_5000Z:
15397532SSean.Ye@Sun.COM nb_number_memory_controllers = 1;
15407532SSean.Ye@Sun.COM break;
154110049SVuong.Nguyen@Sun.COM case INTEL_NB_5100:
154210049SVuong.Nguyen@Sun.COM nb_channels_per_branch = 1;
154310049SVuong.Nguyen@Sun.COM break;
15447532SSean.Ye@Sun.COM case INTEL_NB_5400:
15457532SSean.Ye@Sun.COM case INTEL_NB_5400A:
15467532SSean.Ye@Sun.COM case INTEL_NB_5400B:
15477532SSean.Ye@Sun.COM nb_chipset = INTEL_NB_5400;
15487532SSean.Ye@Sun.COM break;
15497532SSean.Ye@Sun.COM }
15507532SSean.Ye@Sun.COM return (0);
15517532SSean.Ye@Sun.COM }
15527532SSean.Ye@Sun.COM
15537532SSean.Ye@Sun.COM void
nb_dev_reinit()15547532SSean.Ye@Sun.COM nb_dev_reinit()
15557532SSean.Ye@Sun.COM {
15567532SSean.Ye@Sun.COM int i, j;
15577532SSean.Ye@Sun.COM int nchannels = nb_number_memory_controllers * 2;
15587532SSean.Ye@Sun.COM nb_dimm_t **dimmpp;
15597532SSean.Ye@Sun.COM nb_dimm_t *dimmp;
15607532SSean.Ye@Sun.COM nb_dimm_t **old_nb_dimms;
15617532SSean.Ye@Sun.COM int old_nb_dimms_per_channel;
15627532SSean.Ye@Sun.COM find_dimm_label_t *label_function_p;
15638037SAdrian.Frost@Sun.COM int dimm_slot = nb_dimm_slots;
15647532SSean.Ye@Sun.COM
15657532SSean.Ye@Sun.COM old_nb_dimms = nb_dimms;
15667532SSean.Ye@Sun.COM old_nb_dimms_per_channel = nb_dimms_per_channel;
15677532SSean.Ye@Sun.COM
15687532SSean.Ye@Sun.COM dimm_fini();
15698037SAdrian.Frost@Sun.COM nb_dimms_per_channel = 0;
15707532SSean.Ye@Sun.COM label_function_p = find_dimms_per_channel();
15717532SSean.Ye@Sun.COM dimm_init();
15727532SSean.Ye@Sun.COM nb_dimms_init(label_function_p);
15737532SSean.Ye@Sun.COM nb_mc_init();
15747532SSean.Ye@Sun.COM nb_pex_init();
15757532SSean.Ye@Sun.COM nb_int_init();
15767532SSean.Ye@Sun.COM nb_thr_init();
157710049SVuong.Nguyen@Sun.COM if (nb_chipset == INTEL_NB_5100)
157810049SVuong.Nguyen@Sun.COM nb_mem_init();
157910049SVuong.Nguyen@Sun.COM else
158010049SVuong.Nguyen@Sun.COM nb_fbd_init();
15817532SSean.Ye@Sun.COM nb_fsb_init();
15827532SSean.Ye@Sun.COM nb_scrubber_enable();
15837532SSean.Ye@Sun.COM
15847532SSean.Ye@Sun.COM dimmpp = old_nb_dimms;
15857532SSean.Ye@Sun.COM for (i = 0; i < nchannels; i++) {
15867532SSean.Ye@Sun.COM for (j = 0; j < old_nb_dimms_per_channel; j++) {
15877532SSean.Ye@Sun.COM dimmp = *dimmpp;
15887532SSean.Ye@Sun.COM if (dimmp) {
15897532SSean.Ye@Sun.COM kmem_free(dimmp, sizeof (nb_dimm_t));
15907532SSean.Ye@Sun.COM *dimmpp = NULL;
15917532SSean.Ye@Sun.COM }
1592*12726SJakub.Jermar@Sun.COM dimmpp++;
15937532SSean.Ye@Sun.COM }
15947532SSean.Ye@Sun.COM }
15958037SAdrian.Frost@Sun.COM kmem_free(old_nb_dimms, sizeof (nb_dimm_t *) * dimm_slot);
15967532SSean.Ye@Sun.COM }
15977532SSean.Ye@Sun.COM
15987532SSean.Ye@Sun.COM void
nb_dev_unload()15997532SSean.Ye@Sun.COM nb_dev_unload()
16007532SSean.Ye@Sun.COM {
16017532SSean.Ye@Sun.COM errorq_destroy(nb_queue);
16027532SSean.Ye@Sun.COM nb_queue = NULL;
16037532SSean.Ye@Sun.COM mutex_destroy(&nb_mutex);
16047532SSean.Ye@Sun.COM nb_int_fini();
16057532SSean.Ye@Sun.COM nb_thr_fini();
160610049SVuong.Nguyen@Sun.COM if (nb_chipset == INTEL_NB_5100)
160710049SVuong.Nguyen@Sun.COM nb_mem_fini();
160810049SVuong.Nguyen@Sun.COM else
160910049SVuong.Nguyen@Sun.COM nb_fbd_fini();
16107532SSean.Ye@Sun.COM nb_fsb_fini();
16117532SSean.Ye@Sun.COM nb_pex_fini();
16127532SSean.Ye@Sun.COM nb_fini();
16137532SSean.Ye@Sun.COM }
16147532SSean.Ye@Sun.COM
16157532SSean.Ye@Sun.COM void
nb_unload()16167532SSean.Ye@Sun.COM nb_unload()
16177532SSean.Ye@Sun.COM {
16187532SSean.Ye@Sun.COM }
1619