#include <ppc/mappings.h>
#include <ppc/pmap.h>
#include <ppc/mem.h>
-#include <ppc/pmap_internals.h>
#include <ppc/savearea.h>
#include <ppc/vmachmon.h>
-void db_dumpphys(struct phys_entry *pp); /* Dump from physent */
-void db_dumppca(struct mapping *mp); /* PCA */
+void db_dumppca(unsigned int ptegindex);
void db_dumpmapping(struct mapping *mp); /* Dump out a mapping */
-void db_dumppmap(pmap_t pmap); /* Dump out a pmap */
extern kmod_info_t *kmod; /* Find the kmods */
db_addr_t db_low_trace_prev = 0;
int c, i;
unsigned int tempx, cnt;
- unsigned int xbuf[8];
- unsigned int xTraceCurr, xTraceStart, xTraceEnd, cxltr, xxltr;
+ unsigned int xTraceCurr, xTraceStart, xTraceEnd, cxltr;
db_addr_t next_addr;
LowTraceRecord xltr;
unsigned char cmark;
+ addr64_t xxltr;
cnt = 16; /* Default to 16 entries */
return; /* Leave... */
}
- if((unsigned int)addr&0x0000003F) { /* Proper alignment? */
- db_printf("address not aligned on trace entry boundary (0x40)\n"); /* Tell 'em */
+ if((unsigned int)addr&0x0000007F) { /* Proper alignment? */
+ db_printf("address not aligned on trace entry boundary (0x80)\n"); /* Tell 'em */
return; /* Leave... */
}
- xxltr=(unsigned int)addr; /* Set the start */
- cxltr=((xTraceCurr==xTraceStart ? xTraceEnd : xTraceCurr)-sizeof(LowTraceRecord)); /* Get address of newest entry */
+ xxltr = addr; /* Set the start */
+ cxltr = ((xTraceCurr == xTraceStart ? xTraceEnd : xTraceCurr) - sizeof(LowTraceRecord)); /* Get address of newest entry */
db_low_trace_prev = addr; /* Starting point */
for(i=0; i < cnt; i++) { /* Dump the 16 (or all) entries */
- ReadReal(xxltr, (unsigned int *)&xltr); /* Get the first half */
- ReadReal(xxltr+32, &(((unsigned int *)&xltr)[8])); /* Get the second half */
+ ReadReal((addr64_t)xxltr, (unsigned int *)&xltr); /* Get the first half */
+ ReadReal((addr64_t)xxltr + 32, &(((unsigned int *)&xltr)[8])); /* Get the second half */
+ ReadReal((addr64_t)xxltr + 64, &(((unsigned int *)&xltr)[16])); /* Get the second half */
+ ReadReal((addr64_t)xxltr + 96, &(((unsigned int *)&xltr)[24])); /* Get the second half */
- db_printf("\n%s%08X %1X %08X %08X - %04X\n", (xxltr!=cxltr ? " " : "*"),
+ db_printf("\n%s%08llX %1X %08X %08X - %04X\n", (xxltr != cxltr ? " " : "*"),
xxltr,
xltr.LTR_cpu, xltr.LTR_timeHi, xltr.LTR_timeLo,
- (xltr.LTR_excpt&0x8000 ? 0xFFFF : xltr.LTR_excpt*64)); /* Print the first line */
- db_printf(" %08X %08X %08X %08X %08X %08X %08X\n",
- xltr.LTR_cr, xltr.LTR_srr0, xltr.LTR_srr1, xltr.LTR_dar, xltr.LTR_save, xltr.LTR_lr, xltr.LTR_ctr);
- db_printf(" %08X %08X %08X %08X %08X %08X\n",
- xltr.LTR_r0, xltr.LTR_r1, xltr.LTR_r2, xltr.LTR_r3, xltr.LTR_r4, xltr.LTR_r5);
+ (xltr.LTR_excpt & 0x8000 ? 0xFFFF : xltr.LTR_excpt * 64)); /* Print the first line */
+
+ db_printf(" DAR/DSR/CR: %016llX %08X %08X\n", xltr.LTR_dar, xltr.LTR_dsisr, xltr.LTR_cr);
+
+ db_printf(" SRR0/SRR1 %016llX %016llX\n", xltr.LTR_srr0, xltr.LTR_srr1);
+ db_printf(" LR/CTR %016llX %016llX\n", xltr.LTR_lr, xltr.LTR_ctr);
+
+ db_printf(" R0/R1/R2 %016llX %016llX %016llX\n", xltr.LTR_r0, xltr.LTR_r1, xltr.LTR_r2);
+ db_printf(" R3/R4/R5 %016llX %016llX %016llX\n", xltr.LTR_r3, xltr.LTR_r4, xltr.LTR_r5);
+ db_printf(" R6/sv/rsv %016llX %016llX %08X\n", xltr.LTR_r6, xltr.LTR_save, xltr.LTR_rsvd0);
if((cnt != 16) && (xxltr == xTraceCurr)) break; /* If whole table dump, exit when we hit start again... */
int i;
for(i=0; i<8; i++) { /* Print 256 bytes */
- db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */
+ db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */
((unsigned long *)addr)[0], ((unsigned long *)addr)[1], ((unsigned long *)addr)[2], ((unsigned long *)addr)[3],
((unsigned long *)addr)[4], ((unsigned long *)addr)[5], ((unsigned long *)addr)[6], ((unsigned long *)addr)[7]);
- addr=(db_expr_t)((unsigned int)addr+0x00000020); /* Point to next address */
+ addr=(db_expr_t)(addr+0x00000020); /* Point to next address */
}
db_next = addr;
+}
+
+unsigned char xtran[256] = {
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* 0x */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* 1x */
+ ' ', '!', '"', '#', '$', '%', '&',0x27, '(', ')', '*', '+', ',', '-', '.', '/', /* 2x */
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', /* 3x */
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 4x */
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',0x5C, ']', '^', '_', /* 5x */
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 6x */
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '.', /* 7x */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* 8x */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* 9x */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Ax */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Bx */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Cx */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Dx */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Ex */
+ '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', /* Fx */
+};
+
+/*
+ * Print out 256 bytes in characters
+ *
+ *
+ * dc [entaddr]
+ */
+void db_display_char(db_expr_t addr, int have_addr, db_expr_t count, char * modif) {
+
+ int i, j, k;
+ unsigned char xlt[256], *xaddr;
+
+ xaddr = (unsigned char *)addr;
+
+
+ for(i = 0; i < 8; i++) { /* Print 256 bytes */
+ j = 0;
+ for(k = 0; k < 32; k++) {
+ xlt[j] = xtran[*xaddr];
+ xaddr++;
+ j++;
+ if((k & 3) == 3) {
+ xlt[j] = ' ';
+ j++;
+ }
+ }
+ xlt[j] = 0;
+
+ db_printf("%016llX %s\n", (addr64_t)(xaddr - 32), xlt); /* Print a line */
+ }
+
+ db_next = (db_expr_t)xaddr;
+
+
}
/*
unsigned int xbuf[8];
for(i=0; i<8; i++) { /* Print 256 bytes */
- ReadReal((unsigned int)addr, &xbuf[0]); /* Get the real storage data */
- db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */
+ ReadReal(addr, &xbuf[0]); /* Get the real storage data */
+ db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */
xbuf[0], xbuf[1], xbuf[2], xbuf[3],
xbuf[4], xbuf[5], xbuf[6], xbuf[7]);
- addr=(db_expr_t)((unsigned int)addr+0x00000020); /* Point to next address */
+ addr = addr + 0x00000020; /* Point to next address */
}
db_next = addr;
-
-
}
unsigned int dvspace = 0;
*/
void db_display_mappings(db_expr_t addr, int have_addr, db_expr_t count, char * modif) {
- int i;
- unsigned int xspace;
+ db_expr_t xspace;
+ pmap_t pmap;
+ addr64_t lnextva;
- mapping *mp, *mpv;
- vm_offset_t pa;
+ mapping *mp;
+
+ if (db_expression(&xspace)) { /* Get the address space requested */
+ if(xspace >= maxAdrSp) {
+ db_printf("requested address space (%llX) larger than max (%X)\n", xspace, maxAdrSp - 1);
+ return;
+ }
+ dvspace = xspace; /* Get the space or set default */
+ }
- if (db_expression(&xspace)) dvspace = xspace; /* Get the space or set default */
+ db_printf("mapping information for %016llX in space %8X:\n", addr, dvspace);
+
+ pmap = pmapTrans[dvspace].pmapVAddr; /* Find the pmap address */
+ if(!pmap) { /* The pmap is not in use */
+ db_printf("The space %X is not assigned to a pmap\n", dvspace); /* Say we are wrong */
+ return;
+ }
+
+ mp = hw_find_map(pmap, (addr64_t)addr, &lnextva); /* Try to find the mapping for this address */
+ if((unsigned int)mp == mapRtBadLk) { /* Did we lock up ok? */
+ db_printf("Timeout locking physical entry for virtual address %016ll8X\n", addr);
+ return;
+ }
- db_printf("mapping information for %08X in space %08X:\n", addr, dvspace);
- mp = hw_lock_phys_vir(dvspace, addr); /* Lock the physical entry for this mapping */
if(!mp) { /* Did we find one? */
db_printf("Not mapped\n");
return; /* Didn't find any, return FALSE... */
}
- if((unsigned int)mp&1) { /* Did we timeout? */
- db_printf("Timeout locking physical entry for virtual address (%08X)\n", addr); /* Yeah, scream about it! */
- return; /* Bad hair day, return FALSE... */
+
+ mapping_drop_busy(mp); /* The mapping shouldn't be changing */
+
+ db_dumpmapping(mp); /* Dump it all out */
+
+ return; /* Tell them we did it */
+
+
+}
+
+/*
+ * Print out hash table data
+ *
+ *
+ * dh vaddr [space] (defaults to last entered)
+ */
+void db_display_hash(db_expr_t addr, int have_addr, db_expr_t count, char * modif) {
+
+ db_expr_t xspace;
+ unsigned int seg, vsid, ptegindex, htsize;
+ pmap_t pmap;
+ addr64_t lnextva, llva, vpn, esid;
+ uint64_t hash;
+ int s4bit;
+
+ llva = (addr64_t)((unsigned int)addr); /* Make sure we are 64-bit now */
+
+ s4bit = !((per_proc_info[0].pf.Available & pf64Bit) == 0); /* Are we a big guy? */
+ if (db_expression(&xspace)) { /* Get the address space requested */
+ if(xspace >= maxAdrSp) {
+ db_printf("requested address space (%llX) larger than max (%X)\n", xspace, maxAdrSp - 1);
+ return;
+ }
+ dvspace = xspace; /* Get the space or set default */
}
- printf("dumpaddr: space=%08X; vaddr=%08X\n", dvspace, addr); /* Say what address were dumping */
- mpv = hw_cpv(mp); /* Get virtual address of mapping */
- dumpmapping(mpv);
- if(mpv->physent) {
- hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Unlock physical entry associated with mapping */
+
+ pmap = pmapTrans[dvspace].pmapVAddr; /* Find the pmap address */
+ if(!pmap) { /* The pmap is not in use */
+ db_printf("The space %X is not assigned to a pmap\n", dvspace); /* Say we are wrong */
+ return;
}
+
+ hash = (uint64_t)pmap->space | ((uint64_t)pmap->space << maxAdrSpb) | ((uint64_t)pmap->space << (2 * maxAdrSpb)); /* Get hash value */
+ hash = hash & 0x0000001FFFFFFFFF; /* Make sure we stay within supported ranges */
+
+ esid = ((llva >> 14) & -maxAdrSp) ^ hash; /* Get ESID */
+ llva = ((llva >> 12) & 0xFFFF) ^ esid; /* Get index into hash table */
+
+ if(s4bit) htsize = hash_table_size >> 7; /* Get number of entries in hash table for 64-bit */
+ else htsize = hash_table_size >> 6; /* get number of entries in hash table for 32-bit */
+
+ ptegindex = llva & (htsize - 1); /* Get the index to the pteg and pca */
+ db_dumppca(ptegindex); /* dump the info */
+
return; /* Tell them we did it */
void db_display_pmap(db_expr_t addr, int have_addr, db_expr_t count, char * modif) {
pmap_t pmap;
+ int i;
+ unsigned int v0, v1, st0, st1;
- pmap = kernel_pmap; /* Start at the beginning */
+ pmap = (pmap_t)addr;
+ if(!have_addr) pmap = kernel_pmap; /* Start at the beginning */
- db_printf("PMAP (real) Next Prev VRMask Space Bmaps Flags Ref spaceNum Resident Wired\n");
-// xxxxxxxx rrrrrrrr xxxxxxxx pppppppp vvvvvvvv ssssssss bbbbbbbb cccccccc vvvvvvvv nnnnnnnn rrrrrrrr wwwwwwwww
+ db_printf("PMAP (real) Next Prev Space Flags Ref spaceNum Resident Wired\n");
+// xxxxxxxx rrrrrrrrrrrrrrrr xxxxxxxx pppppppp ssssssss cccccccc vvvvvvvv nnnnnnnn rrrrrrrr wwwwwwwww
while(1) { /* Do them all */
- db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X %08X %08X %08X\n",
- pmap, (unsigned int)pmap ^ pmap->pmapvr,
- pmap->pmap_link.next, pmap->pmap_link.prev, pmap->pmapvr,
- pmap->space, pmap->bmaps, pmap->vflags, pmap->ref_count, pmap->spaceNum,
+ db_printf("%08X %016llX %08X %08X %08X %08X %08X %08X %08X %08X\n",
+ pmap, (addr64_t)pmap ^ pmap->pmapvr,
+ pmap->pmap_link.next, pmap->pmap_link.prev,
+ pmap->space, pmap->pmapFlags, pmap->ref_count, pmap->spaceNum,
pmap->stats.resident_count,
pmap->stats.wired_count);
+ db_printf("lists = %d, rand = %08X, visits = %016llX, searches = %08X\n",
+ pmap->pmapCurLists, pmap->pmapRandNum,
+ pmap->pmapSearchVisits, pmap->pmapSearchCnt);
-// xxxxxxxx rrrrrrrr xxxxxxxx pppppppp vvvvvvvv ssssssss bbbbbbbb cccccccc vvvvvvvv nnnnnnnn rrrrrrrr wwwwwwwww
- db_printf(" SRs: %08X %08X %08X %08X %08X %08X %08X %08X\n", pmap->pmapSegs[0], pmap->pmapSegs[1], pmap->pmapSegs[2], pmap->pmapSegs[3],
- pmap->pmapSegs[4], pmap->pmapSegs[5], pmap->pmapSegs[6], pmap->pmapSegs[7]);
- db_printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", pmap->pmapSegs[8], pmap->pmapSegs[9], pmap->pmapSegs[10], pmap->pmapSegs[11],
- pmap->pmapSegs[12], pmap->pmapSegs[13], pmap->pmapSegs[14], pmap->pmapSegs[15]);
-
- db_printf(" spmaps: %08X %08X %08X %08X %08X %08X %08X %08X\n", pmap->pmapPmaps[0], pmap->pmapPmaps[1], pmap->pmapPmaps[2], pmap->pmapPmaps[3],
- pmap->pmapPmaps[4], pmap->pmapPmaps[5], pmap->pmapPmaps[6], pmap->pmapPmaps[7]);
- db_printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", pmap->pmapPmaps[8], pmap->pmapPmaps[9], pmap->pmapPmaps[10], pmap->pmapPmaps[11],
- pmap->pmapPmaps[12], pmap->pmapPmaps[13], pmap->pmapPmaps[14], pmap->pmapPmaps[15]);
+ db_printf("cctl = %08X, SCSubTag = %016llX\n",
+ pmap->pmapCCtl, pmap->pmapSCSubTag);
+
+ for(i = 0; i < 16; i +=2) {
+ v0 = (pmap->pmapCCtl >> (31 - i) & 1); /* Get high order bit */
+ v1 = (pmap->pmapCCtl >> (30 - i) & 1); /* Get high order bit */
+ st0 = (pmap->pmapSCSubTag >> (60 - (4 * i))) & 0xF; /* Get the sub-tag */
+ st1 = (pmap->pmapSCSubTag >> (56 - (4 * i))) & 0xF; /* Get the sub-tag */
+
+ db_printf(" %01X %01X %016llX/%016llX %01X %01X %016llX/%016llX\n",
+ v0, st0, pmap->pmapSegCache[i].sgcESID, pmap->pmapSegCache[i].sgcVSID,
+ v1, st1, pmap->pmapSegCache[i+1].sgcESID, pmap->pmapSegCache[i+1].sgcVSID);
+ }
- pmap = (pmap_t)pmap->pmap_link.next; /* Skip to the next */
db_printf("\n");
+ if(have_addr) break; /* Do only one if address supplied */
+ pmap = (pmap_t)pmap->pmap_link.next; /* Skip to the next */
if(pmap == kernel_pmap) break; /* We've wrapped, we're done */
}
return;
}
-/*
- * print information about the passed in pmap block
- */
-void db_dumppmap(pmap_t pmap) {
-
- db_printf("Dump of pmap block: %08X\n", pmap);
- db_printf(" pmap_link: %08X %08X\n", pmap->pmap_link.next, pmap->pmap_link.prev);
- db_printf(" pmapvr: %08X\n", pmap->pmapvr);
- db_printf(" space: %08X\n", pmap->space);
- db_printf(" bmaps: %08X\n", pmap->bmaps);
- db_printf(" ref_count: %08X\n", pmap->ref_count);
- db_printf(" spaceNum: %08X\n", pmap->spaceNum);
- db_printf(" resident_count: %08X\n", pmap->stats.resident_count);
- db_printf(" wired_count: %08X\n", pmap->stats.wired_count);
- db_printf("\n");
+/*
+ * Checks the pmap skip lists
+ *
+ *
+ * cp pmap
+ */
+void db_check_pmaps(db_expr_t addr, int have_addr, db_expr_t count, char * modif) {
+ int i;
+ unsigned int ret;
+ uint64_t dumpa[32];
+ pmap_t pmap;
+
+ pmap = (pmap_t)addr;
+ if(!have_addr) pmap = kernel_pmap; /* If no map supplied, start with kernel */
+
+ while(1) { /* Do them all */
+ ret = mapSkipListVerifyC(pmap, &dumpa); /* Check out the map */
+ if(!ret) db_printf("Skiplists verified ok, pmap = %08X\n", pmap);
+ else {
+ db_printf("Verification failure at %08X, pmap = %08X\n", ret, pmap);
+ for(i = 0; i < 32; i += 4) {
+ db_printf("R%02d %016llX %016llX %016llX %016llX\n", i,
+ dumpa[i], dumpa[i + 1], dumpa[i + 2], dumpa[i + 3]);
+ }
+ }
+ if(have_addr) break; /* Do only one if address supplied */
+ pmap = (pmap_t)pmap->pmap_link.next; /* Skip to the next */
+ if(pmap == kernel_pmap) break; /* We've wrapped, we're done */
+ }
+
return;
}
+
/*
- * Prints out a mapping control block
+ * Displays iokit junk
*
+ * dp
*/
-
-void db_dumpmapping(struct mapping *mp) { /* Dump out a mapping */
- db_printf("Dump of mapping block: %08X\n", mp); /* Header */
- db_printf(" next: %08X\n", mp->next);
- db_printf(" hashnext: %08X\n", mp->hashnext);
- db_printf(" PTEhash: %08X\n", mp->PTEhash);
- db_printf(" PTEent: %08X\n", mp->PTEent);
- db_printf(" physent: %08X\n", mp->physent);
- db_printf(" PTEv: %08X\n", mp->PTEv);
- db_printf(" PTEr: %08X\n", mp->PTEr);
- db_printf(" pmap: %08X\n", mp->pmap);
-
- if(mp->physent) { /* Print physent if it exists */
- db_printf("Associated physical entry: %08X %08X\n", mp->physent->phys_link, mp->physent->pte1);
- }
- else {
- db_printf("Associated physical entry: none\n");
- }
-
- db_dumppca(mp); /* Dump out the PCA information */
-
+void db_piokjunk(void);
+
+void db_display_iokit(db_expr_t addr, int have_addr, db_expr_t count, char * modif) {
+
+ db_piokjunk();
+
return;
}
/*
- * Prints out a PTEG control area
+ * Prints out a mapping control block
*
*/
-void db_dumppca(struct mapping *mp) { /* PCA */
-
- PCA *pca;
- unsigned int *pteg, sdr;
-
- pca = (PCA *)((unsigned int)mp->PTEhash&-64); /* Back up to the start of the PCA */
- __asm__ volatile("mfsdr1 %0" : "=r" (sdr));
- db_printf(" SDR1: %08X\n", sdr);
- pteg=(unsigned int *)((unsigned int)pca-(((sdr&0x0000FFFF)+1)<<16));
- db_printf(" Dump of PCA: %08X\n", pca); /* Header */
- db_printf(" PCAlock: %08X\n", pca->PCAlock);
- db_printf(" PCAallo: %08X\n", pca->flgs.PCAallo);
- db_printf(" PCAhash: %08X %08X %08X %08X\n", pca->PCAhash[0], pca->PCAhash[1], pca->PCAhash[2], pca->PCAhash[3]);
- db_printf(" %08X %08X %08X %08X\n", pca->PCAhash[4], pca->PCAhash[5], pca->PCAhash[6], pca->PCAhash[7]);
- db_printf("Dump of PTEG: %08X\n", pteg); /* Header */
- db_printf(" %08X %08X %08X %08X\n", pteg[0], pteg[1], pteg[2], pteg[3]);
- db_printf(" %08X %08X %08X %08X\n", pteg[4], pteg[5], pteg[6], pteg[7]);
- db_printf(" %08X %08X %08X %08X\n", pteg[8], pteg[9], pteg[10], pteg[11]);
- db_printf(" %08X %08X %08X %08X\n", pteg[12], pteg[13], pteg[14], pteg[15]);
+void db_dumpmapping(struct mapping *mp) { /* Dump out a mapping */
+
+ pmap_t pmap;
+ int i;
+
+ db_printf("Dump of mapping block: %08X, pmap: %08X (%016llX)\n", mp, pmapTrans[mp->mpSpace].pmapVAddr,
+ pmapTrans[mp->mpSpace].pmapPAddr); /* Header */
+ db_printf(" mpFlags: %08X\n", mp->mpFlags);
+ db_printf(" mpSpace: %04X\n", mp->mpSpace);
+ db_printf(" mpBSize: %04X\n", mp->mpBSize);
+ db_printf(" mpPte: %08X\n", mp->mpPte);
+ db_printf(" mpPAddr: %08X\n", mp->mpPAddr);
+ db_printf(" mpVAddr: %016llX\n", mp->mpVAddr);
+ db_printf(" mpAlias: %016llX\n", mp->mpAlias);
+ db_printf(" mpList00: %016llX\n", mp->mpList0);
+
+ for(i = 1; i < (mp->mpFlags & mpLists); i++) { /* Dump out secondary physical skip lists */
+ db_printf(" mpList%02d: %016llX\n", i, mp->mpList[i - 1]);
+ }
+
return;
}
/*
- * Dumps starting with a physical entry
+ * Prints out a PTEG and PCA
+ *
*/
-void db_dumpphys(struct phys_entry *pp) { /* Dump from physent */
+void db_dumppca(unsigned int ptegindex) {
- mapping *mp;
- PCA *pca;
- unsigned int *pteg;
+ addr64_t pteg, pca, llva;
+ unsigned int xpteg[32], xpca[8], space, hash, pva, seg, api, va;
+ int i, s4bit;
+ unsigned long long llslot, llseg, llhash;
- db_printf("Dump from physical entry %08X: %08X %08X\n", pp, pp->phys_link, pp->pte1);
- mp = hw_cpv(pp->phys_link);
- while(mp) {
- db_dumpmapping(mp);
- db_dumppca(mp);
- mp = hw_cpv(mp->next);
- }
+ s4bit = !((per_proc_info[0].pf.Available & pf64Bit) == 0); /* Are we a big guy? */
+
+ pteg = hash_table_base + (ptegindex << 6); /* Point to the PTEG */
+ if(s4bit) pteg = hash_table_base + (ptegindex << 7); /* Point to the PTEG */
+ pca = hash_table_base - ((ptegindex + 1) * 4); /* Point to the PCA */
+ db_printf("PTEG = %016llX, PCA = %016llX (index = %08X)\n", pteg, pca, ptegindex);
+ ReadReal(pteg, &xpteg[0]); /* Get first half of the pteg */
+ ReadReal(pteg + 0x20, &xpteg[8]); /* Get second half of the pteg */
+ ReadReal(pca, &xpca[0]); /* Get pca */
+
+ db_printf("PCA: free = %02X, steal = %02X, auto = %02X, misc = %02X\n",
+ ((xpca[0] >> 24) & 255), ((xpca[0] >> 16) & 255), ((xpca[0] >> 8) & 255), xpca[0] & 255);
+
+ if(!s4bit) { /* Little guy? */
+
+ for(i = 0; i < 16; i += 2) { /* Step through pteg */
+ db_printf("%08X %08X - ", xpteg[i], xpteg[i + 1]); /* Dump the pteg slot */
+
+ if(xpteg[i] & 0x80000000) db_printf(" valid - "); /* Is it valid? */
+ else db_printf("invalid - "); /* Nope, invalid */
+
+ space = (xpteg[i] >> 7) & (maxAdrSp - 1); /* Extract the space */
+ hash = space | (space << maxAdrSpb) | (space << (2 * maxAdrSpb)); /* Get the hash */
+ pva = ptegindex ^ hash; /* Get part of the vaddr */
+ seg = (xpteg[i] >> 7) ^ hash; /* Get the segment number */
+ api = (xpteg[i] & 0x3F); /* Get the API */
+ va = ((seg << (28 - maxAdrSpb)) & 0xF0000000) | (api << 22) | ((pva << 12) & 0x003FF000); /* Get the vaddr */
+ db_printf("va = %08X\n", va);
+ }
+ }
+ else {
+ ReadReal(pteg + 0x40, &xpteg[16]); /* Get third half of the pteg */
+ ReadReal(pteg + 0x60, &xpteg[24]); /* Get fourth half of the pteg */
+
+ for(i = 0; i < 32; i += 4) { /* Step through pteg */
+ db_printf("%08X%08X %08X%08X - ", xpteg[i], xpteg[i + 1], xpteg[i + 2], xpteg[i + 3]); /* Dump the pteg slot */
+
+ if(xpteg[i + 1] & 1) db_printf(" valid - "); /* Is it valid? */
+ else db_printf("invalid - "); /* Nope, invalid */
+
+ llslot = ((long long)xpteg[i] << 32) | (long long)xpteg[i + 1]; /* Make a long long version of this */
+ space = (llslot >> 12) & (maxAdrSp - 1); /* Extract the space */
+ llhash = (unsigned long long)space | ((unsigned long long)space << maxAdrSpb) | ((unsigned long long)space << (2 * maxAdrSpb)); /* Get the hash */
+ llhash = llhash & 0x0000001FFFFFFFFF; /* Make sure we stay within supported ranges */
+ pva = (unsigned long long)ptegindex ^ llhash; /* Get part of the vaddr */
+ llseg = (llslot >> 12) ^ llhash; /* Get the segment number */
+ api = (llslot >> 7) & 0x1F; /* Get the API */
+ llva = ((llseg << (28 - maxAdrSpb)) & 0xFFFFFFFFF0000000ULL) | (api << 23) | ((pva << 12) & 0x007FF000); /* Get the vaddr */
+ db_printf("va = %016llX\n", llva);
+ }
+ }
+
return;
}
*/
void db_display_virtual(db_expr_t addr, int have_addr, db_expr_t count, char * modif) {
- int i, size, lines, rlines;
+ int i, size, lines, rlines;
unsigned int xbuf[8];
- unsigned int xspace;
+ db_expr_t xspace;
+ pmap_t pmap;
mapping *mp, *mpv;
- vm_offset_t pa;
+ addr64_t pa;
+ ppnum_t pnum;
+
+ if (db_expression(&xspace)) { /* Parse the space ID */
+ if(xspace >= (1 << maxAdrSpb)) { /* Check if they gave us a sane space number */
+ db_printf("Invalid space ID: %llX - max is %X\n", xspace, (1 << maxAdrSpb) - 1);
+ return;
+ }
+ dvspace = xspace; /* Get the space or set default */
+ }
- if (db_expression(&xspace)) dvspace = xspace; /* Get the space or set default */
+ pmap = (pmap_t)pmapTrans[dvspace].pmapVAddr; /* Find the pmap address */
+ if((unsigned int)pmap == 0) { /* Is there actually a pmap here? */
+ db_printf("Address space not found: %X\n", dvspace); /* Complain */
+ return;
+ }
- addr&=-32;
+ addr &= -32;
size = 4096 - (addr & 0x00000FFF); /* Bytes left on page */
lines = size / 32; /* Number of lines in first or only part */
rlines = 8 - lines;
if(rlines < 0) lines = 0;
- db_printf("Dumping %08X (space=%08X); ", addr, dvspace);
- mp = hw_lock_phys_vir(dvspace, addr); /* Lock the physical entry for this mapping */
- if(!mp) { /* Did we find one? */
+ db_printf("Dumping %016llX (pmap = %08X, space = %X); ", addr, pmap, dvspace);
+
+ pnum = pmap_find_phys(pmap, (addr64_t)addr); /* Phynd the Physical */
+ if(!pnum) { /* Did we find one? */
db_printf("Not mapped\n");
return; /* Didn't find any, return FALSE... */
}
- if((unsigned int)mp&1) { /* Did we timeout? */
- db_printf("Timeout locking physical entry for virtual address (%08X)\n", addr); /* Yeah, scream about it! */
- return; /* Bad hair day, return FALSE... */
- }
- mpv = hw_cpv(mp); /* Get virtual address of mapping */
- if(!mpv->physent) { /* Was there a physical entry? */
- pa = (vm_offset_t)((mpv->PTEr & -PAGE_SIZE) | ((unsigned int)addr & (PAGE_SIZE-1))); /* Get physical address from physent */
- }
- else {
- pa = (vm_offset_t)((mpv->physent->pte1 & -PAGE_SIZE) | ((unsigned int)addr & (PAGE_SIZE-1))); /* Get physical address from physent */
- hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Unlock the physical entry */
- }
- db_printf("phys=%08X\n", pa);
+
+ pa = (addr64_t)(pnum << 12) | (addr64_t)(addr & 0xFFF); /* Get the physical address */
+ db_printf("phys = %016llX\n", pa);
+
for(i=0; i<lines; i++) { /* Print n bytes */
- ReadReal((unsigned int)pa, &xbuf[0]); /* Get the real storage data */
- db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */
+ ReadReal(pa, &xbuf[0]); /* Get the real storage data */
+ db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */
xbuf[0], xbuf[1], xbuf[2], xbuf[3],
xbuf[4], xbuf[5], xbuf[6], xbuf[7]);
- addr=(db_expr_t)((unsigned int)addr+0x00000020); /* Point to next address */
- pa=(unsigned int)pa+0x00000020; /* Point to next address */
+ addr = (db_expr_t)((unsigned int)addr + 0x00000020); /* Point to next address */
+ pa = pa + 0x00000020; /* Point to next address */
}
db_next = addr;
if(!rlines) return;
- db_printf("Dumping %08X (space=%08X); ", addr, dvspace);
- mp = hw_lock_phys_vir(dvspace, addr); /* Lock the physical entry for this mapping */
- if(!mp) { /* Did we find one? */
+ db_printf("Dumping %016llX (pmap = %08X, space = %X); ", addr, pmap, dvspace);
+
+ pnum = pmap_find_phys(pmap, (addr64_t)((unsigned int)addr)); /* Phynd the Physical */
+ if(!pnum) { /* Did we find one? */
db_printf("Not mapped\n");
return; /* Didn't find any, return FALSE... */
}
- if((unsigned int)mp&1) { /* Did we timeout? */
- db_printf("Timeout locking physical entry for virtual address (%08X)\n", addr); /* Yeah, scream about it! */
- return; /* Bad hair day, return FALSE... */
- }
- mpv = hw_cpv(mp); /* Get virtual address of mapping */
- if(!mpv->physent) { /* Was there a physical entry? */
- pa = (vm_offset_t)((mpv->PTEr & -PAGE_SIZE) | ((unsigned int)addr & (PAGE_SIZE-1))); /* Get physical address from physent */
- }
- else {
- pa = (vm_offset_t)((mpv->physent->pte1 & -PAGE_SIZE) | ((unsigned int)addr & (PAGE_SIZE-1))); /* Get physical address from physent */
- hw_unlock_bit((unsigned int *)&mp->physent->phys_link, PHYS_LOCK); /* Unlock the physical entry */
- }
- db_printf("phys=%08X\n", pa);
+
+ pa = (addr64_t)(pnum << 12) | (addr64_t)((unsigned int)addr & 0xFFF); /* Get the physical address */
+ db_printf("phys = %016llX\n", pa);
+
for(i=0; i<rlines; i++) { /* Print n bytes */
- ReadReal((unsigned int)pa, &xbuf[0]); /* Get the real storage data */
- db_printf("%08X %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */
+ ReadReal(pa, &xbuf[0]); /* Get the real storage data */
+ db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr, /* Print a line */
xbuf[0], xbuf[1], xbuf[2], xbuf[3],
xbuf[4], xbuf[5], xbuf[6], xbuf[7]);
- addr=(db_expr_t)((unsigned int)addr+0x00000020); /* Point to next address */
- pa=(unsigned int)pa+0x00000020; /* Point to next address */
+ addr = (db_expr_t)(addr + 0x00000020); /* Point to next address */
+ pa = pa + 0x00000020; /* Point to next address */
}
db_next = addr;
for(task = (task_t)pset->tasks.next; task != (task_t)&pset->tasks.next; task = (task_t)task->pset_tasks.next) { /* Go through the tasks */
taskact = 0; /* Reset activation count */
db_printf("\nTask %4d @%08X:\n", tottasks, task); /* Show where we're at */
- for(act = (thread_act_t)task->thr_acts.next; act != (thread_act_t)&task->thr_acts; act = (thread_act_t)act->thr_acts.next) { /* Go through activations */
+ for(act = (thread_act_t)task->threads.next; act != (thread_act_t)&task->threads; act = (thread_act_t)act->task_threads.next) { /* Go through activations */
db_printf(" Act %4d @%08X - p: %08X current context: %08X\n",
taskact, act, act->mact.pcb, act->mact.curctx);
while(save) { /* Do them all */
totsaves++; /* Count savearea */
- db_printf(" Norm %08X: %08X %08X - tot = %d\n", save, save->save_srr0, save->save_srr1, totsaves);
- save = save->save_hdr.save_prev; /* Next one */
+ db_printf(" Norm %08X: %016llX %016llX - tot = %d\n", save, save->save_srr0, save->save_srr1, totsaves);
+ save = (savearea *)save->save_hdr.save_prev; /* Next one */
if(chainsize++ > chainmax) { /* See if we might be in a loop */
db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save);
break;
while(save) { /* Do them all */
totsaves++; /* Count savearea */
db_printf(" FPU %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves);
- save = save->save_hdr.save_prev; /* Next one */
+ save = (savearea *)save->save_hdr.save_prev; /* Next one */
if(chainsize++ > chainmax) { /* See if we might be in a loop */
db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save);
break;
while(save) { /* Do them all */
totsaves++; /* Count savearea */
db_printf(" Vec %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves);
- save = save->save_hdr.save_prev; /* Next one */
+ save = (savearea *)save->save_hdr.save_prev; /* Next one */
if(chainsize++ > chainmax) { /* See if we might be in a loop */
db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save);
break;
if(CTable = act->mact.vmmControl) { /* Are there virtual machines? */
- for(vmid = 0; vmid < kVmmMaxContextsPerThread; vmid++) {
+ for(vmid = 0; vmid < kVmmMaxContexts; vmid++) {
if(!(CTable->vmmc[vmid].vmmFlags & vmmInUse)) continue; /* Skip if vm is not in use */
while(save) { /* Do them all */
totsaves++; /* Count savearea */
db_printf(" FPU %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves);
- save = save->save_hdr.save_prev; /* Next one */
+ save = (savearea *)save->save_hdr.save_prev; /* Next one */
if(chainsize++ > chainmax) { /* See if we might be in a loop */
db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save);
break;
while(save) { /* Do them all */
totsaves++; /* Count savearea */
db_printf(" Vec %08X: %08X - tot = %d\n", save, save->save_hdr.save_level, totsaves);
- save = save->save_hdr.save_prev; /* Next one */
+ save = (savearea *)save->save_hdr.save_prev; /* Next one */
if(chainsize++ > chainmax) { /* See if we might be in a loop */
db_printf(" Chain terminated by count (%d) before %08X\n", chainmax, save);
break;
db_printf("THRM2: %08X\n", dbspecrs[45]);
db_printf("THRM3: %08X\n", dbspecrs[46]);
db_printf("ICTC: %08X\n", dbspecrs[47]);
+ db_printf("L2CR2: %08X\n", dbspecrs[48]);
+ db_printf("DABR: %08X\n", dbspecrs[49]);
db_printf("\n");
db_printf("DBAT: %08X %08X %08X %08X\n", dbspecrs[2], dbspecrs[3], dbspecrs[4], dbspecrs[5]);
}
+/*
+ * Check check mappings and hash table for consistency
+ *
+ * cm
+ */
+void db_check_mappings(db_expr_t addr, int have_addr, db_expr_t count, char * modif) {
+
+ addr64_t pteg, pca, llva, lnextva;
+ unsigned int xpteg[32], xpca[8], space, hash, pva, seg, api, va, free, free2, xauto, PTEGcnt, wimgkk, wimgxx, slotoff;
+ int i, j, fnderr, slot, slot2, k, s4bit;
+ pmap_t pmap;
+ mapping *mp;
+ ppnum_t ppn, pa, aoff;
+ unsigned long long llslot, llseg, llhash;
+
+ s4bit = 0; /* Assume dinky? */
+ if(per_proc_info[0].pf.Available & pf64Bit) s4bit = 1; /* Are we a big guy? */
+
+ PTEGcnt = hash_table_size / 64; /* Get the number of PTEGS */
+ if(s4bit) PTEGcnt = PTEGcnt / 2; /* PTEGs are twice as big */
+
+ pteg = hash_table_base; /* Start of hash table */
+ pca = hash_table_base - 4; /* Start of PCA */
+
+ for(i = 0; i < PTEGcnt; i++) { /* Step through them all */
+
+ fnderr = 0;
+
+ ReadReal(pteg, &xpteg[0]); /* Get first half of the pteg */
+ ReadReal(pteg + 0x20, &xpteg[8]); /* Get second half of the pteg */
+ if(s4bit) { /* See if we need the other half */
+ ReadReal(pteg + 0x40, &xpteg[16]); /* Get third half of the pteg */
+ ReadReal(pteg + 0x60, &xpteg[24]); /* Get fourth half of the pteg */
+ }
+ ReadReal(pca, &xpca[0]); /* Get pca */
+
+ if(xpca[0] & 0x00000001) { /* Is PCA locked? */
+ db_printf("Unexpected locked PCA\n"); /* Yeah, this may be bad */
+ fnderr = 1; /* Remember to print the pca/pteg pair later */
+ }
+
+ free = 0x80000000;
+
+ for(j = 0; j < 7; j++) { /* Search for duplicates */
+ slot = j * 2; /* Point to the slot */
+ if(s4bit) slot = slot * 2; /* Adjust for bigger slots */
+ if(!(xpca[0] & free)) { /* Check more if slot is allocated */
+ for(k = j + 1; k < 8; k++) { /* Search remaining slots */
+ slot2 = k * 2; /* Point to the slot */
+ if(s4bit) slot2 = slot2 * 2; /* Adjust for bigger slots */
+ if((xpteg[slot] == xpteg[slot2])
+ && (!s4bit || (xpteg[slot + 1] == xpteg[slot2 + 1]))) { /* Do we have duplicates? */
+ db_printf("Duplicate tags in pteg, slot %d and slot %d\n", j, k);
+ fnderr = 1;
+ }
+ }
+ }
+ free = free >> 1; /* Move slot over */
+ }
+
+ free = 0x80000000;
+ xauto = 0x00008000;
+
+ for(j = 0; j < 8; j++) { /* Step through the slots */
+
+ slot = j * 2; /* Point to the slot */
+ if(s4bit) slot = slot * 2; /* Hagfish? */
+ if(xpca[0] & free) { /* Check if marked free */
+ if((!s4bit && (xpteg[slot] & 0x80000000)) /* Is a supposedly free slot valid? */
+ || (s4bit && (xpteg[slot + 1] & 1))) {
+ db_printf("Free slot still valid - %d\n", j);
+ fnderr = 1;
+ }
+ }
+ else { /* We have an in use slot here */
+
+ if(!(!s4bit && (xpteg[slot] & 0x80000000)) /* Is a supposedly in use slot valid? */
+ && !(s4bit && (xpteg[slot + 1] & 1))) {
+ db_printf("Inuse slot not valid - %d\n", j);
+ fnderr = 1;
+ }
+ else { /* Slot is valid, check mapping */
+ if(!s4bit) { /* Not Hagfish? */
+ space = (xpteg[slot] >> 7) & (maxAdrSp - 1); /* Extract the space */
+ hash = space | (space << maxAdrSpb) | (space << (2 * maxAdrSpb)); /* Get the hash */
+ pva = i ^ hash; /* Get part of the vaddr */
+ seg = (xpteg[slot] >> 7) ^ hash; /* Get the segment number */
+ api = (xpteg[slot] & 0x3F); /* Get the API */
+ va = ((seg << (28 - maxAdrSpb)) & 0xF0000000) | (api << 22) | ((pva << 12) & 0x003FF000); /* Get the vaddr */
+ llva = (addr64_t)va; /* Make this a long long */
+ wimgxx = xpteg[slot + 1] & 0x7F; /* Get the wimg and pp */
+ ppn = xpteg[slot + 1] >> 12; /* Get physical page number */
+ slotoff = (i * 64) + (j * 8) | 1; /* Get offset to slot and valid bit */
+ }
+ else { /* Yes, Hagfish */
+ llslot = ((long long)xpteg[slot] << 32) | (long long)xpteg[slot + 1]; /* Make a long long version of this */
+ space = (llslot >> 12) & (maxAdrSp - 1); /* Extract the space */
+ llhash = (unsigned long long)space | ((unsigned long long)space << maxAdrSpb) | ((unsigned long long)space << (2 * maxAdrSpb)); /* Get the hash */
+ llhash = llhash & 0x0000001FFFFFFFFF; /* Make sure we stay within supported ranges */
+ pva = i ^ llhash; /* Get part of the vaddr */
+ llseg = ((llslot >> 12) ^ llhash); /* Get the segment number */
+ api = (llslot >> 7) & 0x1F; /* Get the API */
+ llva = ((llseg << (28 - maxAdrSpb)) & 0xFFFFFFFFF0000000ULL) | (api << 23) | ((pva << 12) & 0x007FF000); /* Get the vaddr */
+ wimgxx = xpteg[slot + 3] & 0x7F; /* Get the wimg and pp */
+ ppn = (xpteg[slot + 2] << 20) | (xpteg[slot + 3] >> 12); /* Get physical page number */
+ slotoff = (i * 128) + (j * 16) | 1; /* Get offset to slot and valid bit */
+ }
+
+ pmap = pmapTrans[space].pmapVAddr; /* Find the pmap address */
+ if(!pmap) { /* The pmap is not in use */
+ db_printf("The space %08X is not assigned to a pmap, slot = %d\n", space, slot); /* Say we are wrong */
+ fnderr = 1;
+ goto dcmout;
+ }
+
+ mp = hw_find_map(pmap, llva, &lnextva); /* Try to find the mapping for this address */
+// db_printf("%08X - %017llX\n", mp, llva);
+ if((unsigned int)mp == mapRtBadLk) { /* Did we lock up ok? */
+ db_printf("Timeout locking mapping for for virtual address %016ll8X, slot = %d\n", llva, j);
+ return;
+ }
+
+ if(!mp) { /* Did we find one? */
+ db_printf("Not mapped, slot = %d, va = %08X\n", j, (unsigned int)llva);
+ fnderr = 1;
+ goto dcmout;
+ }
+
+ if((mp->mpFlags & 0xFF000000) > 0x01000000) { /* Is busy count too high? */
+ db_printf("Busy count too high, slot = %d\n", j);
+ fnderr = 1;
+ }
+
+ if(mp->mpFlags & mpBlock) { /* Is this a block map? */
+ if(!(xpca[0] & xauto)) { /* Is it marked as such? */
+ db_printf("mapping marked as block, PCA is not, slot = %d\n", j);
+ fnderr = 1;
+ }
+ }
+ else { /* Is a block */
+ if(xpca[0] & xauto) { /* Is it marked as such? */
+ db_printf("mapping not marked as block, PCA is, slot = %d\n", j);
+ fnderr = 1;
+ }
+ if(mp->mpPte != slotoff) { /* See if mapping PTEG offset is us */
+ db_printf("mapping does not point to PTE, slot = %d\n", j);
+ fnderr = 1;
+ }
+ }
+
+ wimgkk = (unsigned int)mp->mpVAddr; /* Get last half of vaddr where keys, etc are */
+ wimgkk = (wimgkk ^ wimgxx) & 0x7F; /* XOR to find differences from PTE */
+ if(wimgkk) { /* See if key in PTE is what we want */
+ db_printf("key or WIMG does not match, slot = %d\n", j);
+ fnderr = 1;
+ }
+
+ aoff = (ppnum_t)((llva >> 12) - (mp->mpVAddr >> 12)); /* Get the offset from vaddr */
+ pa = aoff + mp->mpPAddr; /* Get the physical page number we expect */
+ if(pa != ppn) { /* Is physical address expected? */
+ db_printf("Physical address does not match, slot = %d\n", j);
+ fnderr = 1;
+ }
+
+ mapping_drop_busy(mp); /* We're done with the mapping */
+ }
+
+ }
+dcmout:
+ free = free >> 1;
+ xauto = xauto >> 1;
+ }
+
+
+ if(fnderr)db_dumppca(i); /* Print if error */
+
+ pteg = pteg + 64; /* Go to the next one */
+ if(s4bit) pteg = pteg + 64; /* Hagfish? */
+ pca = pca - 4; /* Go to the next one */
+
+
+ }
+
+ return;
+}
+
/*
* Displays all of the kmods in the system.
*