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

#include <unistd.h>
#include <linux/major.h>
#include "crash.h"

#include <linux/tqueue.h>

PRIVATE addr_t tq_struct();
const commandtable_t command_tq_struct =
	{"tq_struct", tq_struct, "[address]", "print tq_struct table"};

struct tqlist {
	char *name;
	addr_t addr;
};
PRIVATE struct tqlist tqlist[] = {
	{"tq_immediate", 0 },
	{"tq_timer", 0 },
	{"tq_disk", 0 },
	{"tq_scheduler", 0 },
};

addr_t
print_tq_struct(addr)
	addr_t addr;
{
	struct tq_struct tq;

	memread(addr, sizeof(tq), &tq, "tq_struct");
	mprintf(FPTR "  ", addr);
	mprintf("%8lx  %8lx  %8lx\n", tq.sync, tq.routine, tq.data);
	return (addr_t) tq.next;
}

PRIVATE addr_t
tq_struct()
{
	int c, i;
	addr_t addr = 0;

	while ((c = getopt(argcnt, args, "")) != EOF) {
		THROW(usage);
	}

	for (i = 0; i < sizeof(tqlist)/sizeof(tqlist[0]); i++) {
		if (tqlist[i].addr == 0) {
			tqlist[i].addr = searchaddr_bysym(tqlist[i].name);
			if (tqlist[i].addr == 0) {
				THROWF("%s not found", tqlist[i].name);
			}
		}
	}

	/* mprintf(head_blk_dev_struct); */
	if (argcnt == optind) {
		for (i = 0; i < sizeof(tqlist)/sizeof(tqlist[0]); i++) {
			mprintf("%8lx  %s\n", tqlist[i].addr, tqlist[i].name);
			memread(tqlist[i].addr, sizeof(addr), &addr, tqlist[i].name);

			while (addr) {
				addr = print_tq_struct(addr);
			}
			mprintf("\n");
		}
	} else {
		while (args[optind]) {
			addr = getvalue(args[optind]);
			while (addr) {
				addr = print_tq_struct(addr);
			}
			optind++;
		}
	}
	return addr;
}
