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

#include "def.h"

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

extern addr_t print_page();

void
prhead_zone()
{
	mprintf(SPTR" FREEPG "SPTR" "SPTR" STARTPFN PAGES NAME\n",
		"ADDR", "PGDAT", "MEM_MAP");
}

addr_t
print_zone(addr, full)
	addr_t addr;
	int full;
{
	struct zone zone;
	char buf[64];
	int i;

	memread(addr, sizeof(zone), &zone, "zone");
	if (!full) {
		mprintf(FPTR " %6lx " FPTR " " FPTR " %8lx %5lx ",
			addr, zone.free_pages, zone.zone_pgdat,
			zone.zone_mem_map, zone.zone_start_pfn,
			zone.present_pages);
		memread((addr_t)zone.name, sizeof(buf), &buf, "name");
		mprintstr(buf, sizeof(buf));
		mprintf("\n");
		return 0;
	}

	mprintf("addr               " FPTR "\n", addr);
	if (addr == 0) {
		mprintf("\n");
		return 0;
	}

	mprintf("free_pages         %lx\n", zone.free_pages);
	mprintf("pages_min/low/high %lx/%lx/%lx\n",
		zone.pages_min, zone.pages_low, zone.pages_high);
	mprintf("refill_counter     %x\n", ATOMIC_READ(zone.refill_counter));
	mprintf("nr_active          %lx\n", zone.nr_active);
	mprintf("nr_inactive        %lx\n", zone.nr_inactive);
	mprintf("all_unreclaimable  %x\n", zone.all_unreclaimable);
	mprintf("pages_scanned      %lx\n", zone.pages_scanned);
	mprintf("FREE " SPTR " " SPTR "  " SPTR "\n", "NEXT", "PREV", "MAP");
	for (i = 0; i < MAX_ORDER; i++) {
		struct free_area *fp = &zone.free_area[i];
		mprintf("%3x  ", i);
		if ((addr_t)fp->free_list.next == addr + OFFSET(struct zone, free_area[i].free_list)) {
			mprintf(SPTR " ", "-");
		} else {
			mprintf(FPTR " ", fp->free_list.next);
		}
		if ((addr_t)fp->free_list.prev == addr + OFFSET(struct zone, free_area[i].free_list)) {
			mprintf(SPTR " ", "-");
		} else {
			mprintf(FPTR " ", fp->free_list.prev);
		}
		mprintf(" " FPTR "\n", fp->map);
	}
	mprintf("wait_table         " FPTR "\n", zone.wait_table);
	mprintf("wait_table_size    %lx  (2^%lx)\n",
		zone.wait_table_size, zone.wait_table_bits);
	mprintf("zone_pgdat         " FPTR "\n", zone.zone_pgdat);
	mprintf("zone_mem_map       " FPTR "\n", zone.zone_mem_map);
	mprintf("zone_start_pfn     %lx\n", zone.zone_start_pfn);

	mprintf("name               \"");
	memread((addr_t)zone.name, sizeof(buf), &buf, "name");
	mprintstr(buf, sizeof(buf));
	mprintf("\"\n");
	mprintf("spanned_pages      %lx\n", zone.spanned_pages);
	mprintf("present_pages      %lx\n", zone.present_pages);
	return 0;
}

addr_t
get_zone_from_pglist_data(addr, n)
	addr_t addr;
	int n;
{
	struct pglist_data pg;

	memread(addr, sizeof(pg), &pg, "pglist_data");
	if (n < LENGTHOF(pg.node_zones) && n < pg.nr_zones) {
		return addr + OFFSET(struct pglist_data, node_zones[n]);
	}
	return 0;
}

addr_t
print_pglist_data(addr)
	addr_t addr;
{
	struct pglist_data pg;
	char buf[256];
	int i, j;

	mprintf("addr               " FPTR "\n", addr);
	if (addr == 0) {
		mprintf("\n");
		return 0;
	}
	memread(addr, sizeof(pg), &pg, "pglist_data");

	mprintf("node_zones        ");
	for (i = 0; i < LENGTHOF(pg.node_zones) && i < pg.nr_zones ; i++) {
		mprintf(" " FPTR "(", addr + OFFSET(struct pglist_data, node_zones[i]));
		if (pg.node_zones[i].name) {
			memread((addr_t)pg.node_zones[i].name, sizeof(buf), &buf, "name");
			mprintstr(buf, sizeof(buf));
		}
		mprintf(")");
	}
	mprintf("\n");
	for (i = 0; i < LENGTHOF(pg.node_zonelists); i++) {
		struct zonelist *zl = &pg.node_zonelists[i];
		mprintf("%3x ", i);
		for (j = 0; j < LENGTHOF(zl->zones); j++) {
			if (zl->zones[j] == 0) {
				break;
			}
			mprintf(" " FPTR, zl->zones[j]);
		}
		mprintf("\n");
	}
	mprintf("nr_zones           %x\n", pg.nr_zones);
	mprintf("node_mem_map       " FPTR "\n", pg.node_mem_map);
	mprintf("valid_addr_bitmap  " FPTR "\n", pg.valid_addr_bitmap);
	mprintf("bdata              " FPTR "\n", pg.bdata);
	mprintf("node_start_pfn     %lx\n", pg.node_start_pfn);
	mprintf("node_present_pages %lx / %lx\n",
		pg.node_present_pages, pg.node_spanned_pages);
	mprintf("node_id            %x\n", pg.node_id);
	mprintf("pgdat_next         " FPTR "\n", pg.pgdat_next);
	return (addr_t)pg.pgdat_next;
}

void
print_zone_active_list(zaddr)
	addr_t zaddr;
{
	addr_t start, addr;

#ifdef PRINT_ZONE_NAME
	char buf[64];
	memread(zaddr + OFFSET(struct zone, name), sizeof(addr), &addr, "zone");
	memread(addr, sizeof(buf), &buf, "zone.name");
	mprintf(" --- ");
	mprintstr(buf, sizeof(buf));
	mprintf(" zone ---\n");
#endif /*PRINT_ZONE_NAME*/

	start = zaddr + OFFSET(struct zone, active_list);
	memread(start, sizeof(addr), &addr, "zone.active_list");
	while (addr && addr != start) {
		addr = print_page(addr, 1);
	}
}
