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

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

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

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

extern addr_t print_block_device();
extern void prhead_block_device();

addr_t bdev_hashtable_addr;

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

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

	GETADDR(bdev_hashtable);

	if (argcnt == optind) {
		prhead_block_device();
		memread(bdev_hashtable_addr, sizeof(bdev_hashtable), bdev_hashtable, "bdev_hashtable");
		for (i = 0; i < HASH_SIZE; i++) {
			addr = (addr_t)bdev_hashtable[i].next;
			while (addr && !(addr >= bdev_hashtable_addr && addr < bdev_hashtable_addr + sizeof(bdev_hashtable))) {
				addr = print_block_device(addr, eflag);
			}
		}
	} else {
		prhead_block_device();
		while (args[optind]) {
			addr = print_block_device(getaddr(args[optind]), 1);
			optind++;
		}
	}
	return addr;
}
