/*
 * Copyright (C) 2000-2003 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();

PRIVATE addr_t gendisk();
const commandtable_t command_gendisk =
	{"gendisk", gendisk, "[-f] address", "print gendisk table"};
extern addr_t print_gendisk();

addr_t all_bdevs_addr;
extern int offset_block_device_bd_list;

PRIVATE addr_t
block_device()
{
	int c;
	int eflag = 0;
	addr_t addr = 0;
	struct list_head all_bdevs;

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

	GETADDR(all_bdevs);

	if (argcnt == optind) {
		prhead_block_device();
		memread(all_bdevs_addr, sizeof(all_bdevs), &all_bdevs, "all_bdevs");
		addr = (addr_t)all_bdevs.next;
		while (addr && addr != all_bdevs_addr) {
			addr = print_block_device(addr - offset_block_device_bd_list, eflag);
		}
	} else {
		prhead_block_device();
		while (args[optind]) {
			addr = print_block_device(getvalue(args[optind]), 1);
			optind++;
		}
	}
	return addr;
}

PRIVATE addr_t
gendisk()
{
	int c;
	addr_t addr = 0;
	int full = 0;

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

	if (argcnt == optind) {
		THROW(usage);
	} else {
		while (args[optind]) {
			addr = print_gendisk(getvalue(args[optind]), full);
			optind++;
		}
	}
	return addr;
}
