FreeBSD/Linux Kernel Cross Reference
sys/sqt/memory.c
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
|