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

#include <unistd.h>
#include <linux/major.h>
#include "crash.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 },
};

extern void prhead_tq_struct();
extern addr_t print_tq_struct();

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

	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);
			}
		}
	}

	if (argcnt == optind) {
		for (i = 0; i < sizeof(tqlist)/sizeof(tqlist[0]); i++) {
			mprintf(FPTR " %s\n", tqlist[i].addr, tqlist[i].name);
			memread(tqlist[i].addr, sizeof(lh), &lh, tqlist[i].name);
			addr = (addr_t)lh.next;
			if (addr != tqlist[i].addr)
				prhead_tq_struct();
			while (addr && addr != tqlist[i].addr) {
				addr_t next = print_tq_struct(addr);
				if (addr == next)
					break;
				addr = next;
			}
			mprintf("\n");
		}
	} else {
		prhead_tq_struct();
		while (args[optind]) {
			addr = getvalue(args[optind]);
			while (addr && addr != tqlist[i].addr) {
				addr_t next = print_tq_struct(addr);
				if (addr == next)
					break;
				addr = next;
			}
			optind++;
		}
	}
	return addr;
}
