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

#include "def.h"

#define __KERNEL__
#include <linux/blkdev.h>
#include "printdev.h"

addr_t print_blk_dev_struct();
addr_t print_request_queue();
addr_t print_request();

void
prhead_blk_dev_struct()
{
	mprintf(SPTR " DEV " SPTR " " SPTR "\n", "ADDR", "QUEUE", "DATA");
}

addr_t
print_blk_dev_struct(addr, n, full)
	addr_t addr;
	int n;
	int full;
{
	struct blk_dev_struct bd;

	if (n >= 0) {
		addr += sizeof(bd) * n;
	}
	memread(addr, sizeof(bd), &bd, "blk_dev_struct");
	if (bd.queue == NULL && bd.data == NULL) {
		int i;
		char *p;
		for (i = 0, p = (char *)&bd; i < sizeof(&bd) && *p == 0; i++, p++)
			;
		if (i == sizeof(&bd))
			return -1;
	}

	mprintf(FPTR " ", addr);
	if (n >= 0) {
		mprintf("%3d ", n);
	} else {
		mprintf("  - ");
	}
	mprintf(FPTR " " FPTR "\n", bd.queue, bd.data);
	if (full) {
		print_request_queue(addr, 1);
	}
	return 0;
}

addr_t
print_request_queue(addr, full)
	addr_t addr;
	int full;
{
	struct request_queue rq;
	const char *p;
	addr_t req;

	memread(addr, sizeof(rq), &rq, "request_queue");

	mprintf("queue_head:        " FPTR "  " FPTR "\n",
		rq.queue_head.next, rq.queue_head.prev);

	mprintf("elevator.elevator_merge_fn:          " FPTR "  %s\n",
		rq.elevator.elevator_merge_fn,
		(p = getsymstr((addr_t)rq.elevator.elevator_merge_fn))? p: "");
	mprintf("elevator.elevator_merge_cleanup_fn:  " FPTR "  %s\n",
		rq.elevator.elevator_merge_cleanup_fn,
		(p = getsymstr((addr_t)rq.elevator.elevator_merge_cleanup_fn))? p: "");
	mprintf("elevator.elevator_merge_req_fn:      " FPTR "  %s\n",
		rq.elevator.elevator_merge_req_fn,
		(p = getsymstr((addr_t)rq.elevator.elevator_merge_req_fn))? p: "");
	mprintf("request_fn:        " FPTR "  %s\n", rq.request_fn,
		(p = getsymstr((addr_t)rq.request_fn))? p: "");
	mprintf("back_merge_fn:     " FPTR "  %s\n", rq.back_merge_fn,
		(p = getsymstr((addr_t)rq.back_merge_fn))? p: "");
	mprintf("front_merge_fn:    " FPTR "  %s\n", rq.front_merge_fn,
		(p = getsymstr((addr_t)rq.front_merge_fn))? p: "");
	mprintf("merge_requests_fn: " FPTR "  %s\n", rq.merge_requests_fn,
		(p = getsymstr((addr_t)rq.merge_requests_fn))? p: "");
	mprintf("make_request_fn:   " FPTR "  %s\n", rq.make_request_fn,
		(p = getsymstr((addr_t)rq.make_request_fn))? p: "");
	mprintf("prep_rq_fn:        " FPTR "  %s\n", rq.prep_rq_fn,
		(p = getsymstr((addr_t)rq.prep_rq_fn))? p: "");
	mprintf("unplug_fn:         " FPTR "  %s\n", rq.unplug_fn,
		(p = getsymstr((addr_t)rq.unplug_fn))? p: "");
	mprintf("queuedata:         " FPTR "\n", rq.queuedata);

	mprintf("plug_list:         " FPTR "  " FPTR "\n",
					rq.plug_list.next,
					rq.plug_list.prev);
	mprintf("queue_lock:        " FPTR "  %s\n", rq.queue_lock,
		(p = getsymstr((addr_t)rq.queue_lock))? p: "");
	mprintf("max_sectors:       %x\n", rq.max_sectors);
	mprintf("queue_tags:        " FPTR "  %s\n", rq.queue_tags,
		(p = getsymstr((addr_t)rq.queue_tags))? p: "");

	if (full) {
		req = (addr_t) rq.queue_head.next;
		while (req && req != (addr_t) &((struct request_queue *)addr)->queue_head) {
			req = print_request(addr);
		}
	}

	return 0;
}

addr_t
print_request(addr)
	addr_t addr;
{
	struct request req;

	memread(addr, sizeof(req), &req, "request");
	mprintf(FPTR " ", addr);
	print_kdev_t(req.rq_dev);
	mprintf(" %02x %8lx %5lx " FPTR " " FPTR " " FPTR "\n", req.cmd[0], req.sector, req.nr_sectors, req.buffer, req.bio, req.q);

	return (addr_t) req.queuelist.next;
}
