/*
 * Copyright (C) 2000-2002 ASANO Masahiro
 */

#include "def.h"

#define __KERNEL__
#include <linux/mm.h>

#include "flags_mm.h"

void
prhead_page()
{
	mprintf(SPTR" "SPTR"   INDEX CNT "SPTR"  PRIVATE FLAGS\n",
		"ADDR", "MAPPING", "PTE");
}

addr_t
print_page(addr, lru)
	addr_t addr;
	int lru;
{
	struct page pg;

	if (lru) {
		addr -= OFFSET(struct page, lru);
	}
	mprintf(FPTR " ", addr);
	memread(addr, sizeof(pg), &pg, "page");

	mprintf(FPTR " %7lx %3x", pg.mapping, pg.index, ATOMIC_READ(pg.count));
	mprintf(" " FPTR, pg.pte.direct);
	mprintf(" %8lx", pg.private);
	mprintbit(pgflags, pg.flags);
	mprintf("\n");
	if (lru) {
		return (addr_t)pg.lru.next;
	}
	return (addr_t)pg.list.next - OFFSET(struct page, list);
}

int
sizeof_page()
{
	return sizeof(struct page);
}

void
prhead_vm_area_struct()
{
	mprintf(SPTR " " SPTR " " SPTR " " SPTR "  FLAGS\n",
		"ADDR", "START", "END", "FILE");
}

addr_t
print_vm_area_struct(addr, full)
	addr_t addr;
{
	struct vm_area_struct vma;
	static const struct bitname vmflags[] = {
		{ VM_READ,	"R" },
		{ VM_WRITE,	"W" },
		{ VM_EXEC,	"X" },
		{ VM_SHARED,	"S" },

		{ VM_MAYREAD,	"mayR" },
		{ VM_MAYWRITE,	"mayW" },
		{ VM_MAYEXEC,	"mayX" },
		{ VM_MAYSHARE,	"mayS" },

		{ VM_GROWSDOWN,	"growsdown" },
		{ VM_GROWSUP,	"growsup" },
		{ VM_SHM,	"shm" },
		{ VM_DENYWRITE,	"denywrite" },

		{ VM_EXECUTABLE,"executable" },
		{ VM_LOCKED,	"locked" },
		{ VM_IO,	"io" },

		{ VM_SEQ_READ,	"seq_read" },
		{ VM_RAND_READ,	"rand_read" },

		{ VM_DONTCOPY,	"dontcopy" },
		{ VM_DONTEXPAND,"dontexpand" },
		{ VM_RESERVED,	"reserved" },
		{ VM_ACCOUNT,	"account" },

		{ 0,		NULL }
	};

	memread(addr, sizeof(vma), &vma, "vm_area_struct");

	if (!full) {
		mprintf(FPTR " " FPTR " " FPTR " " FPTR " ",
			addr, vma.vm_start, vma.vm_end, vma.vm_file);
		mprintbit(vmflags, vma.vm_flags);
		mprintf("\n");
		return (addr_t)vma.vm_next;
	}
	mprintf("addr:           " FPTR "\n", addr);

	mprintf("vm_mm:          " FPTR "\n", vma.vm_mm);
	mprintf("vm_start:       " FPTR "\n", vma.vm_start);
	mprintf("vm_end:         " FPTR "\n", vma.vm_end);
	mprintf("vm_next:        " FPTR "\n", vma.vm_next);
	mprintf("vm_flags:      ");
	mprintbit(vmflags, vma.vm_flags);
	mprintf("\n");
	mprintf("shared:         " FPTR "\n", vma.shared.next);
	mprintf("vm_ops:         " FPTR "\n", vma.vm_ops);
	mprintf("vm_pgoff:       " FPTR "\n", vma.vm_pgoff);
	mprintf("vm_file:        " FPTR "\n", vma.vm_file);
	mprintf("vm_private_data:" FPTR "\n", vma.vm_private_data);
	return (addr_t)vma.vm_next;
}

void
print_gfp(gfp)
	int gfp;
{
	static const struct bitname gfpbit[] = {
		{ __GFP_DMA,		"dma" },
		{ __GFP_HIGHMEM,	"highmem" },
		{ __GFP_WAIT,		"wait" },
		{ __GFP_HIGH,		"high" },
		{ __GFP_IO,		"io" },
		{ __GFP_HIGHIO,		"highio" },
		{ __GFP_FS,		"fs" },
		{ 0,			NULL }
	};
	const char *p = NULL;

	mprintbit(gfpbit, gfp);
	switch (gfp) {
	case GFP_NOHIGHIO:	p = "NOHIGHIO";	break;
	case GFP_NOIO:		p = "NOIO";	break;
	case GFP_NOFS:		p = "NOFS";	break;
	case GFP_ATOMIC:	p = "ATOMIC";	break;
	case GFP_USER:		p = "USER";	break;
	case GFP_HIGHUSER:	p = "HIGHUSER";	break;
#if GFP_USER != GFP_KERNEL
	case GFP_KERNEL:	p = "KERNEL";	break;
#endif
#if GFP_USER != GFP_NFS && GFP_KERNEL != GFP_NFS
	case GFP_NFS:		p = "NFS";	break;
#endif
#if GFP_USER != GFP_KSWAPD && GFP_KERNEL != GFP_KSWAPD && GFP_NFS != GFP_KSWAPD
	case GFP_KSWAPD:	p = "KSWAPD";	break;
#endif
	case GFP_DMA:		p = "DMA";	break;
	}
	if (p) {
		mprintf("  (GFP_%s)\n", p);
	} else {
		mprintf("\n");
	}
}
