The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/sqt/memory.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1991 Carnegie Mellon University
    4  * Copyright (c) 1991 Sequent Computer Systems
    5  * All Rights Reserved.
    6  * 
    7  * Permission to use, copy, modify and distribute this software and its
    8  * documentation is hereby granted, provided that both the copyright
    9  * notice and this permission notice appear in all copies of the
   10  * software, derivative works or modified versions, and any portions
   11  * thereof, and that both notices appear in supporting documentation.
   12  * 
   13  * CARNEGIE MELLON AND SEQUENT COMPUTER SYSTEMS ALLOW FREE USE OF
   14  * THIS SOFTWARE IN ITS "AS IS" CONDITION.  CARNEGIE MELLON AND
   15  * SEQUENT COMPUTER SYSTEMS DISCLAIM ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  * 
   18  * Carnegie Mellon requests users of this software to return to
   19  * 
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  * 
   25  * any improvements or extensions that they make and grant Carnegie Mellon 
   26  * the rights to redistribute these changes.
   27  */
   28 
   29 /*
   30  * HISTORY
   31  * $Log:        memory.c,v $
   32  * Revision 2.4  93/03/11  14:05:34  danner
   33  *      u_long -> u_int
   34  *      [93/03/09            danner]
   35  * 
   36  * Revision 2.3  91/07/31  18:02:26  dbg
   37  *      Changed copyright.
   38  *      [91/07/31            dbg]
   39  * 
   40  * Revision 2.2  91/05/08  12:57:34  dbg
   41  *      Adapted for pure Mach kernel.
   42  *      [91/04/26  14:54:06  dbg]
   43  * 
   44  */
   45 
   46 #ifndef lint
   47 static  char    rcsid[] = "$Header: memory.c,v 2.4 93/03/11 14:05:34 danner Exp $";
   48 #endif
   49 
   50 /*
   51  * memory.c
   52  *      Architecture dependent memory handling routines to deal with
   53  *      configration, initialization, and error polling.
   54  *
   55  * Balance/Symmetry version.
   56  */
   57 
   58 /*
   59  * Revision 1.3  89/08/16  15:23:09  kak
   60  * bool_t -> boolean_t
   61  * 
   62  * Revision 1.2  89/07/20  18:05:27  kak
   63  * moved balance includes
   64  * 
   65  * Revision 1.1  89/07/05  13:15:37  kak
   66  * Initial revision
   67  * 
   68  * Revision 2.14  88/04/27  15:21:44  dmo
   69  * added splhi()/splx() calls around wrslave() in fgs_mem_init().
   70  * ./
   71  * 
   72  * Revision 2.13  87/11/24  16:33:16  phil
   73  * Fix bug in constant for edc MEM_EDC_HI_SE error reporting.
   74  * 
   75  */
   76 
   77 #include <mach/boolean.h>
   78 #include <mach/vm_param.h>
   79 
   80 #include <sqt/vm_defs.h>
   81 #include <sqt/cfg.h>
   82 #include <sqt/bdp.h>
   83 #include <sqt/slicreg.h>
   84 #include <sqt/SGSmem.h>
   85 #include <sqt/intctl.h>
   86 
   87 vm_offset_t     topmem;                         /* top of memory */
   88 vm_size_t       totalmem;                       /* total memory (topmem-holes)*/
   89 
   90 extern  int     memintvl;                       /* polling interval in Hz */
   91 
   92 /*
   93  * Define structure to represent the different types of memory boards.
   94  */
   95 
   96 struct  memory  {
   97         u_char  m_type;                 /* board type */
   98         int     (*m_init)();            /* procedure to init m_type boards */
   99         int     (*m_poll)();            /* procedure to poll m_type boards */
  100 };
  101 
  102 int     fgs_mem_init(), fgs_mem_poll();
  103 int     sgs_mem_init(), sgs_mem_poll();
  104 
  105 static  struct  memory  memory_boards[] = {
  106         { SLB_MEMBOARD, fgs_mem_init, fgs_mem_poll },
  107         { SLB_SGSMEMBOARD,sgs_mem_init, sgs_mem_poll },
  108         { 0 }
  109 };
  110 
  111 /*
  112  * MC_MMAP is true iff bit-map for memory click 'i' is on.
  113  * See cfg.h for definitions.
  114  */
  115 
  116 #define MC_MMAP(i)      ((PHYSTOKV(va_CD_LOC->c_mmap, unsigned long *)) \
  117                                 [(i)/MC_BPI] & (1 << ((i)%MC_BPI)))
  118 
  119 /*
  120  * conf_mem()
  121  *      Configure memory.
  122  *
  123  * Figure top of memory.  Allow holes; meminit() handles this.
  124  */
  125 
  126 conf_mem()
  127 {
  128         register struct ctlr_toc *toc;
  129         register struct ctlr_desc *cd;
  130         register struct memory *mem;
  131         register int    i;
  132         int     bad_mem = 0;
  133         extern  int     resphysmem;
  134 
  135         /*
  136          * Print about deconfigured/failed boards.  These are not in
  137          * the bit-map (power-up arranges this).
  138          */
  139 
  140         for (mem = memory_boards; mem->m_type != 0; mem++) {
  141                 toc = PHYSTOKV(&va_CD_LOC->c_toc[mem->m_type],
  142                                 struct ctlr_toc *);
  143                 cd = PHYSTOKV(&va_CD_LOC->c_ctlrs[toc->ct_start],
  144                                 struct ctlr_desc *);
  145                 for (i = 0; i < toc->ct_count; i++, cd++) {
  146                         if (cd->cd_diag_flag & (CFG_FAIL|CFG_DECONF)) {
  147                                 if (++bad_mem == 1)
  148                                         printf("Not using memory boards: slic");
  149                                 printf(" %d", cd->cd_slic);
  150                         }
  151                 }
  152         }
  153         if (bad_mem)
  154                 printf(".\n");
  155 
  156         /*
  157          * Determine top of physical memory, including holes.
  158          */
  159 
  160         topmem = (vm_offset_t) (va_CD_LOC->c_maxmem);
  161         totalmem = va_CD_LOC->c_memsize * 1024;
  162 
  163 #ifdef  MAX_PROC_ADDR_MEM
  164         /*
  165          * Limit topmem to what processors can address in main-memory.
  166          * Relevant for 032 and K20 processors.
  167          */
  168         if (topmem >= (vm_offset_t)MAX_PROC_ADDR_MEM) {
  169                 printf("Non-addressable memory [0x%x,0x%x] unused.\n",
  170                                 MAX_PROC_ADDR_MEM, topmem);
  171                 topmem = (vm_offset_t)MAX_PROC_ADDR_MEM;
  172         }
  173 #endif  MAX_PROC_ADDR_MEM
  174 
  175         /*
  176          * If desired, reserve top of physical memory for special things.
  177          * Basic sanity: insure at least 2Meg of usable system memory.
  178          * This allows resphysmem to consume the highest non-hole, leaving
  179          * topmem just after a hole.  meminit() handles this.
  180          */
  181 
  182         if (resphysmem) {
  183             register vm_offset_t i;
  184 
  185             i = topmem - resphysmem;
  186             while (i < topmem) {
  187                 if (MC_MMAP(i/MC_CLICK) == 0) {
  188                     printf("Reserved memory has a hole; no reserved memory allocated.\n");
  189                     resphysmem = 0;
  190                     break;
  191                 }
  192                 i += MC_CLICK;
  193             }
  194             if (topmem - resphysmem < 2*1024*1024) {
  195                 printf("Not enough memory to reserve 0x%x bytes.\n",
  196                                                         resphysmem);
  197                 resphysmem = 0;
  198             }
  199             if (resphysmem) {
  200                 topmem -= resphysmem;
  201                 totalmem -= resphysmem;
  202                 printf("Physical memory [0x%x,0x%x) reserved for custom use.\n",
  203                                         topmem, topmem+resphysmem);
  204             }
  205         }
  206 }
  207 
  208 /*
  209  * page_exists()
  210  *      Return true iff HW page "pg" exists in physical memory.
  211  */
  212 
  213 page_exists(pg)
  214         register int pg;
  215 {
  216         pg /= i386_btop(MC_CLICK);
  217         return((pg >= va_CD_LOC->c_mmap_size) ? 0 : MC_MMAP(pg));
  218 }
  219 
  220 /*
  221  * memenable()
  222  *      Enable memory controller correctable and uncorrectable
  223  *      error reporting.
  224  *
  225  * The ecc correctable errors are polled for at memintvl seconds
  226  * (usually 10 minutes).  Thus we report at most once per memintvl.
  227  */
  228 
  229 memenable()
  230 {
  231         register struct ctlr_toc *toc;
  232         register struct ctlr_desc *cd;
  233         register struct memory *mem;
  234         register int i;
  235 
  236         /*
  237          * Initialize all instances of all kinds of memory boards.
  238          */
  239 
  240         for (mem = memory_boards; mem->m_type != 0; mem++) {
  241                 toc = PHYSTOKV(&va_CD_LOC->c_toc[mem->m_type],
  242                                 struct ctlr_toc *);
  243                 cd = PHYSTOKV(&va_CD_LOC->c_ctlrs[toc->ct_start],
  244                                 struct ctlr_desc *);
  245                 for (i = 0; i < toc->ct_count; i++, cd++) {
  246                         if ((cd->cd_diag_flag & (CFG_FAIL|CFG_DECONF)) == 0)
  247                                 (*mem->m_init)(cd);
  248                 }
  249         }
  250 }
  251 
  252 /*
  253  * memlog()
  254  *      Log memory errors.
  255  *
  256  * This routine checks for memory errors.  It is called when ecc uncorrectable
  257  * errors are detected AND when polling for ecc correctable memory errors.
  258  * Its functions is to log and clear, if possible, existing errors.
  259  */
  260 
  261 memlog()
  262 {
  263         register struct ctlr_toc *toc;
  264         register struct ctlr_desc *cd;
  265         register struct memory *mem;
  266         register int i;
  267 
  268         /*
  269          * Poll all instances of all kinds of memory boards for errors.
  270          */
  271 
  272         for (mem = memory_boards; mem->m_type != 0; mem++) {
  273                 toc = PHYSTOKV(&va_CD_LOC->c_toc[mem->m_type],
  274                                 struct ctlr_toc *);
  275                 cd = PHYSTOKV(&va_CD_LOC->c_ctlrs[toc->ct_start],
  276                                 struct ctlr_desc *);
  277                 for (i = 0; i < toc->ct_count; i++, cd++) {
  278                         if ((cd->cd_diag_flag & (CFG_FAIL|CFG_DECONF)) == 0)
  279                                 (*mem->m_poll)(cd);
  280                 }
  281         }
  282 }
  283 
  284 /*
  285  * memerr()
  286  *      Memerr is the timeout routine which polls for ecc corrected memory
  287  *      errors.
  288  */
  289 
  290 memerr()
  291 {
  292         memlog();
  293         timeout(memerr, (caddr_t)0, memintvl);
  294 }
  295 
  296 /*
  297  * fgs_mem_init()
  298  *      Arrange error handling for a given FGS memory board.
  299  */
  300 
  301 fgs_mem_init(cd)
  302         register struct ctlr_desc *cd;
  303 {
  304         spl_t s_spl;
  305         /*
  306          * Enable Ecc correctable and uncorrectable error logging and
  307          * uncorrectable error reporting.
  308          */
  309         s_spl = splhi();
  310         wrslave(cd->cd_slic, SL_M_ECC, SLB_EN_UCE_LOG|SLB_REP_UCE|SLB_EN_CE_LOG);
  311         splx(s_spl);
  312 }
  313 
  314 /*
  315  * fgs_mem_poll()
  316  *      Poll a given FGS memory board for errors.
  317  *
  318  * Log and clear, if possible existing errors.
  319  */
  320 
  321 fgs_mem_poll(cd)
  322         register struct ctlr_desc *cd;
  323 {
  324         u_char  eccreg;
  325         u_char  ilv;
  326         u_char  val;
  327         u_char  slbsize;
  328         u_char  syndrome;
  329         u_char  row;
  330         int     addr;
  331         spl_t   s_ipl;
  332 
  333         /*
  334          * Read memory board ECC register.
  335          */
  336 
  337         s_ipl = splhi();
  338         eccreg = rdslave(cd->cd_slic, SL_M_ECC);
  339         splx(s_ipl);
  340 
  341         /*
  342          * If no errors, return.  Else print about it and get more data.
  343          */
  344 
  345         if ((eccreg & (SLB_UCE|SLB_UCE_OV|SLB_CE|SLB_CE_OV)) == 0)
  346                 return;
  347 
  348         printf("%s %d: ECC %scorrectable error: Slic id = %d, Error Reg = 0x%x,\n",
  349                         cd->cd_name, cd->cd_i,
  350                         (eccreg & (SLB_UCE|SLB_UCE_OV)) ? "Un" : "",
  351                         cd->cd_slic, eccreg);
  352 
  353         /*
  354          * Get the base address of the board.
  355          */
  356 
  357         s_ipl = splhi();
  358         ilv = rdslave(cd->cd_slic, SL_M_ENABLES);
  359         val = rdslave(cd->cd_slic, SL_M_ADDR);
  360         slbsize = rdslave(cd->cd_slic, SL_M_BSIZE);
  361         splx(s_ipl);
  362 
  363         /*
  364          * Determine interleaving.
  365          */
  366 
  367         if ((ilv & SLB_INTLV) && (val&1))
  368                 val &= ~1;
  369 
  370         /*
  371          * Base address.
  372          */
  373 
  374         if (slbsize & SLB_LTYPE)
  375                 addr = val << 19;       /* 64K chips */
  376         else
  377                 addr = ((val & 0xE0) << 19) | ((val & 0x07) << 21);
  378 
  379         if ((eccreg & (SLB_UCE|SLB_CE)) == 0) {
  380                 /*
  381                  * Clear the error and report.
  382                  */
  383                 s_ipl = splhi();
  384                 wrslave(cd->cd_slic, SL_M_ECC, eccreg);
  385                 splx(s_ipl);
  386                 printf("%s %d: Base Address = 0x%x, Operation = ?, Syndrome = ?\n",
  387                                 cd->cd_name, cd->cd_i, addr);
  388                 return;
  389         }
  390 
  391         /*
  392          * Read the ECC error address and determine the row.
  393          */
  394 
  395         s_ipl = splhi();
  396         addr &= 0xff000000;     /* mask out lower 24 bits */
  397         val = rdslave(cd->cd_slic, SL_M_EADD_H);
  398         addr += val << 16;
  399         val = rdslave(cd->cd_slic, SL_M_EADD_M);
  400         addr += val << 8;
  401         val = rdslave(cd->cd_slic, SL_M_EADD_L);
  402         addr += val & ~SLB_ROW;
  403         row = val & SLB_ROW;
  404 
  405         /*
  406          * Get operation code and syndrome.
  407          */
  408 
  409         val = rdslave(cd->cd_slic, SL_M_ES);
  410         syndrome = rdslave(cd->cd_slic, SL_M_SYNDR);
  411 
  412         /*
  413          * Clear the error and report.
  414          */
  415 
  416         wrslave(cd->cd_slic, SL_M_ECC, eccreg);
  417         splx(s_ipl);
  418         printf("%s %d: Address = 0x%x (%s Board), Operation = 0x%x, Syndrome = 0x%x\n",
  419                 cd->cd_name, cd->cd_i,
  420                 addr, (row == SLB_CNTRL) ? "Controller" : "Expansion",
  421                 val, syndrome);
  422 }
  423 
  424 /*
  425  * sgs_mem_init()
  426  *      Arrange error handling for a given SGS memory board.
  427  *
  428  * Power-up firmware leaves the board enabled and in "if loggable" mode;
  429  * ie, scrubbing is done if it can log an error it finds.  This is
  430  * how Dynix wants to run the memory board, so nothing to do.
  431  */
  432 
  433 sgs_mem_init(cd)
  434         register struct ctlr_desc *cd;
  435 {
  436 #ifdef  lint
  437         cd->cd_slic = 0;
  438 #endif  lint
  439 }
  440 
  441 /*
  442  * sgs_mem_poll()
  443  *      Poll a given SGS memory board for errors.
  444  *
  445  * Read the EDC Error Register and see if there are any errors.
  446  * Single bit errors can be located to address and bit; double bit
  447  * errors can only be isolated to the address.
  448  *
  449  * Much of this code is cloned from /ccs/sced.fw/v.next/work/src/fw/mon/mem2.c
  450  * (SCED FW power-up memory test).
  451  *
  452  * Smarter polling/recording/etc should be done (later) that might
  453  * (eg) turn off scrubbing for boards with a bad bank (don't want to
  454  * get reports all the time for known bad bits), or be more intelligent
  455  * about how often and how to report.
  456  */
  457 
  458 /*
  459  * sgs_mem_decode[]
  460  *      Table indexed by syndrome value for single-bit error, returns
  461  *      which bit is in error.
  462  *
  463  * The value is described below:
  464  *
  465  *      0 - 31 indicates the failing data bit position. 0 is the lsb and
  466  *             31 is the msb.
  467  *
  468  *      32- 38 indicates a check bit failure.  32 indicates checkbit cx
  469  *                                             33 indicates checkbit c0
  470  *                                             34 indicates checkbit c1
  471  *                                             35 indicates checkbit c2
  472  *                                             36 indicates checkbit c4
  473  *                                             37 indicates checkbit c8
  474  *                                             38 indicates checkbit c16
  475  */
  476 
  477 #define EDCCX   32                      /* checkbit cx  is a 1-bit error */
  478 #define EDCC0   (EDCCX+1)               /* checkbit c0  is a 1-bit error */
  479 #define EDCC1   (EDCCX+2)               /* checkbit c1  is a 1-bit error */
  480 #define EDCC2   (EDCCX+3)               /* checkbit c2  is a 1-bit error */
  481 #define EDCC4   (EDCCX+4)               /* checkbit c4  is a 1-bit error */
  482 #define EDCC8   (EDCCX+5)               /* checkbit c8  is a 1-bit error */
  483 #define EDCC16  (EDCCX+6)               /* checkbit c16 is a 1-bit error */
  484 #define EDCTWO  (EDCC16+1)              /* 2-bit error */
  485 #define EDCMLT  (EDCTWO+1)              /* 3 or more bits in error */
  486 #define EDCOK   (-1)                    /* no error */
  487 
  488 static  u_char  sgs_mem_decode[] = {
  489         EDCOK,  EDCCX,  EDCC0,  EDCTWO, EDCC1,  EDCTWO, EDCTWO, EDCMLT,
  490         EDCC2,  EDCTWO, EDCTWO, 17,     EDCTWO, EDCMLT, 16,     EDCTWO,
  491         EDCC4,  EDCTWO, EDCTWO, 18,     EDCTWO, 19,     20,     EDCTWO,
  492         EDCTWO, 21,     22,     EDCTWO, 23,     EDCTWO, EDCTWO, EDCMLT,
  493         EDCC8,  EDCTWO, EDCTWO, 8,      EDCTWO, 9,      10,     EDCTWO,
  494         EDCTWO, 11,     12,     EDCTWO, 13,     EDCTWO, EDCTWO, EDCMLT,
  495         EDCTWO, 14,     EDCMLT, EDCTWO, 15,     EDCTWO, EDCTWO, EDCMLT,
  496         EDCMLT, EDCTWO, EDCTWO, EDCMLT, EDCTWO, EDCMLT, EDCMLT, EDCTWO,
  497         EDCC16, EDCTWO, EDCTWO, EDCMLT, EDCTWO, EDCMLT, EDCMLT, EDCTWO,
  498         EDCTWO, EDCMLT, 1,      EDCTWO, EDCMLT, EDCTWO, EDCTWO, 0,
  499         EDCTWO, EDCMLT, 2,      EDCTWO, 3,      EDCTWO, EDCTWO, 4,
  500         5,      EDCTWO, EDCTWO, 6,      EDCTWO, 7,      EDCMLT, EDCTWO,
  501         EDCTWO, EDCMLT, 24,     EDCTWO, 25,     EDCTWO, EDCTWO, 26,
  502         27,     EDCTWO, EDCTWO, 28,     EDCTWO, 29,     EDCMLT, EDCTWO,
  503         30,     EDCTWO, EDCTWO, EDCMLT, EDCTWO, 31,     EDCMLT, EDCTWO,
  504         EDCTWO, EDCMLT, EDCMLT, EDCTWO, EDCMLT, EDCTWO, EDCTWO, EDCMLT
  505 };
  506 
  507 vm_offset_t     sgs_mem_err_addr();     /* forward */
  508 int             sgs_mem_bank_decode();  /* forward */
  509 
  510 sgs_mem_poll(cd)
  511         register struct ctlr_desc *cd;
  512 {
  513         register u_int  addr;
  514         u_int   bank;
  515         u_char  edc;
  516         int     errbit;
  517         spl_t   s;
  518         boolean_t       normal_cycle;
  519         boolean_t       xover_cycle;
  520         u_char  synd_lo;
  521         u_char  synd_hi;
  522         static  char    Local[] = "local (refresh/scrub)";
  523         static  char    Normal[] = "normal bus";
  524         static  char    XMessage[] = "Low EDC status reflects cross over status\n";
  525         static  char    Edc[] =
  526                 "%s %d: %s %s error, %s cycle.\nbank=%d addr=0x%x error status=0x%x synd=0x%x\n";
  527         static  char    Interpret_Edc[] =
  528                 "%s %d: single bit error on %s bit %d\n";
  529         static  char    Hard[] = "Non-correctable";
  530         static  char    Soft[] = "Correctable";
  531         static  char    Hiovfl[] = "HIGH overflow bit set, multiple errors have occured.\n";
  532         static  char    LOovfl[] = "LOW overflow bit set, multiple errors have occured.\n";
  533 
  534         /*
  535          * Read EDC Error Register.  If zero, no errors.
  536          */
  537 
  538         s = splhi();
  539 
  540         edc = rdslave(cd->cd_slic, MEM_EDC) & MEM_EDC_MASK;
  541 
  542         /*
  543          * If any errors, read the syndrome registers
  544          */
  545 
  546         if (edc) {
  547                 synd_lo = rdslave(cd->cd_slic, MEM_SYND_LO) & MEM_SYND_MASK;
  548                 synd_hi = rdslave(cd->cd_slic, MEM_SYND_HI) & MEM_SYND_MASK;
  549         }
  550 
  551         /*
  552          * Check low part of EDC error register, then high part.
  553          */
  554 
  555         if (edc & MEM_EDC_LO_MASK) {                    /* low edc */
  556                 addr = sgs_mem_err_addr(cd->cd_slic, MEM_BDP_LO);
  557                 bank = sgs_mem_bank_decode(cd, addr);
  558                 normal_cycle = synd_lo & MEM_NORMCY;
  559                 xover_cycle = synd_hi & MEM_XOVER;
  560                 printf(Edc, cd->cd_name, cd->cd_i,
  561                         (edc & MEM_EDC_LO_ME) ? Hard : Soft,
  562                         "EDC LO", normal_cycle ? Normal : Local,
  563                         bank, addr, edc, synd_lo);
  564                 if (xover_cycle)
  565                         printf(XMessage);
  566                 /*
  567                  * Report failing bit if single-bit error and not a
  568                  * multi-bit error.
  569                  */
  570                 if ((edc & MEM_EDC_LO_SE) && !(edc & MEM_EDC_LO_ME)) {
  571                         errbit = sgs_mem_decode[synd_lo & MEM_SYND_BITS];
  572                         printf(Interpret_Edc, cd->cd_name, cd->cd_i,
  573                                 (errbit <= 31) ? "data" : "check",
  574                                 (errbit <= 31) ? errbit : errbit - 32);
  575                 }
  576                 if (edc & MEM_EDC_LO_OV)
  577                         printf(LOovfl);
  578         }
  579 
  580         if (edc & MEM_EDC_HI_MASK) {                    /* high edc */
  581                 /*
  582                  * Note: address stored only in the low BDP.
  583                  */
  584                 addr = sgs_mem_err_addr(cd->cd_slic, MEM_BDP_LO);
  585                 bank = sgs_mem_bank_decode(cd, addr);
  586                 xover_cycle =  synd_hi & MEM_XOVER;
  587                 normal_cycle = synd_lo & MEM_NORMCY;
  588                 printf(Edc, cd->cd_name, cd->cd_i,
  589                         (edc & MEM_EDC_HI_ME) ? Hard : Soft,
  590                         "EDC HI", normal_cycle ? Normal : Local,
  591                         bank, addr, edc, synd_hi);
  592                 if (xover_cycle)
  593                         printf(XMessage);
  594                 /*
  595                  * Report failing bit if single-bit error and not a
  596                  * multi-bit error.
  597                  */
  598                 if ((edc & MEM_EDC_HI_SE) && !(edc & MEM_EDC_HI_ME)) {
  599                         errbit = sgs_mem_decode[synd_hi & MEM_SYND_BITS];
  600                         printf(Interpret_Edc, cd->cd_name, cd->cd_i,
  601                                 (errbit <= 31) ? "data" : "check",
  602                                 (errbit <= 31) ? errbit : errbit - 32);
  603                 }
  604                 if (edc & MEM_EDC_HI_OV)
  605                         printf(Hiovfl);
  606         }
  607 
  608         /*
  609          * If there was an error, clear it.
  610          * Writing anything to Clear EDC Error Information register
  611          * clears all error bits.
  612          */
  613 
  614         if (edc)
  615                 wrslave(cd->cd_slic, MEM_CLR_EDC, 0xbb);
  616 
  617         splx(s);
  618 }
  619 
  620 vm_offset_t
  621 sgs_mem_err_addr(slic, bdp)
  622         u_char  slic;
  623         u_char  bdp;
  624 {
  625         register vm_offset_t    temp;
  626         register vm_offset_t    result;
  627         register int            i;
  628 
  629         for (result = i = 0; i < 4; i++) {
  630                 temp = rdSubslave(slic, bdp,
  631                                    (u_char)(BDP_WAR|(BDP_BYTE0 - i))) & 0xff;
  632                 result |= temp << (i*8);
  633         }
  634         return (result);
  635 }
  636 
  637 /*
  638  * sgs_mem_bank_decode()
  639  *      Return indication of which bank the error was in.
  640  *
  641  * A painful decode of cases.
  642  */
  643 
  644 int
  645 sgs_mem_bank_decode(cd, err_addr)
  646         register struct ctlr_desc *cd;
  647         register u_int err_addr;
  648 {
  649         u_int   bank_select;
  650         boolean_t       normal_cycle = (rdslave(cd->cd_slic, MEM_SYND_LO) & MEM_NORMCY);
  651         boolean_t       four_banks = (rdslave(cd->cd_slic, MEM_CFG) & MEM_CFG_4_BANKS);
  652         boolean_t       half_banks = ((cd->cd_m_type&SL_M2_RAM_POP) == SL_M2_RAM_HALF);
  653         boolean_t       four_meg_rams = ((cd->cd_m_type&SL_M2_RAM_DENS) == SL_M2_RAM_4MB
  654                                         || (cd->cd_m_expid & MEM_EXP_4MB));
  655         boolean_t       interleaved = cd->cd_m_ileave;
  656 
  657 #define BIT(i)  ((err_addr) & (1 << (i)))
  658 
  659         if (half_banks) {
  660                 if (!normal_cycle) {
  661                                 bank_select = (BIT(24)|BIT(25)|BIT(26)) >> 24;
  662                 } else if (four_meg_rams) {
  663                         if (interleaved)
  664                                 bank_select = (BIT(24) >> 24)
  665                                             | ((BIT(26)|BIT(27)) >> 25);
  666                         else
  667                                 bank_select = (BIT(24)|BIT(25)|BIT(26)) >> 24;
  668                 } else if (interleaved) {
  669                         if (four_banks)
  670                                 bank_select = (BIT(22) >> 22) | (BIT(24) >> 23);
  671                         else
  672                                 bank_select = (BIT(22) >> 22)
  673                                             | ((BIT(24)|BIT(25)) >> 23);
  674                 } else if (four_banks)
  675                         bank_select = (BIT(22)|BIT(23)) >> 22;
  676                 else
  677                         bank_select = (BIT(22)|BIT(23)|BIT(24)) >> 22;
  678         } else {
  679                 if (!normal_cycle) {
  680                                 bank_select = (BIT(25)|BIT(26)|BIT(27)) >> 25;
  681                 } else if (four_meg_rams) {
  682                         if (interleaved)
  683                                 bank_select = (BIT(26)|BIT(27)|BIT(28)) >> 26;
  684                         else
  685                                 bank_select = (BIT(25)|BIT(26)|BIT(27)) >> 25;
  686                 } else if (interleaved) {
  687                         if (four_banks)
  688                                 bank_select = (BIT(24)|BIT(25)) >> 24;
  689                         else
  690                                 bank_select = (BIT(24)|BIT(25)|BIT(26)) >> 24;
  691                 } else if (four_banks)
  692                         bank_select = (BIT(23)|BIT(24)) >> 23;
  693                 else
  694                         bank_select = (BIT(23)|BIT(24)|BIT(25)) >> 23;
  695         } 
  696 
  697         return(bank_select);
  698 
  699 #undef  BIT
  700 }

Cache object: 330c2f9bf71a6fc9f091c9e20a752f62


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.