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

#include <sys/stat.h>
#include <unistd.h>
#include "crash.h"

/* BEGIN fs/char_dev.c */
#define HASH_BITS	6
#define HASH_SIZE	(1UL << HASH_BITS)
#define HASH_MASK	(HASH_SIZE-1)
/* END fs/char_dev.c */

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

extern addr_t print_char_device();
extern void prhead_char_device();

addr_t cdev_hashtable_addr;

PRIVATE addr_t
char_device()
{
	int i, c;
	int eflag = 0;
	addr_t addr = 0;
	struct list_head cdev_hashtable[HASH_SIZE];

	while ((c = getopt(argcnt, args, "e")) != EOF) {
		switch (c) {
		case 'e':
			eflag = 1;
			break;
		default:
			THROW(usage);
		}
	}

	GETADDR(cdev_hashtable);

	if (argcnt == optind) {
		prhead_char_device();
		memread(cdev_hashtable_addr, sizeof(cdev_hashtable), cdev_hashtable, "cdev_hashtable");
		for (i = 0; i < HASH_SIZE; i++) {
			addr = (addr_t)cdev_hashtable[i].next;
			while (addr && !(addr >= cdev_hashtable_addr && addr < cdev_hashtable_addr + sizeof(cdev_hashtable))) {
				addr = print_char_device(addr, eflag);
			}
		}
	} else {
		prhead_char_device();
		while (args[optind]) {
			addr = print_char_device(getvalue(args[optind]), 1);
			optind++;
		}
	}
	return addr;
}
