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

#include "def.h"

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

addr_t print_request_queue();
addr_t print_request();

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:        ");
	if ((addr_t)rq.queue_head.next == addr + OFFSET(struct request_queue, queue_head))
		mprintf(SPTR "  " SPTR "\n", "-", "-");
	else
		mprintf(FPTR "  " FPTR "\n",
			rq.queue_head.next, rq.queue_head.prev);

#if 0	/* -mm */
	mprintf("elevator:          " FPTR "  %s\n", rq.elevator,
		(p = getsymstr_func((addr_t)rq.elevator))? p: "");
#else
	mprintf("elevator.elevator_merge_fn:          " FPTR "  %s\n",
		rq.elevator.elevator_merge_fn,
		(p = getsymstr_func((addr_t)rq.elevator.elevator_merge_fn))? p: "");
	mprintf("elevator.elevator_merge_req_fn:      " FPTR "  %s\n",
		rq.elevator.elevator_merge_req_fn,
		(p = getsymstr_func((addr_t)rq.elevator.elevator_merge_req_fn))? p: "");
	mprintf("elevator.elevator_next_req_fn:       " FPTR "  %s\n",
		rq.elevator.elevator_next_req_fn,
		(p = getsymstr_func((addr_t)rq.elevator.elevator_next_req_fn))? p: "");
	mprintf("elevator.elevator_add_req_fn:        " FPTR "  %s\n",
		rq.elevator.elevator_add_req_fn,
		(p = getsymstr_func((addr_t)rq.elevator.elevator_add_req_fn))? p: "");
	mprintf("elevator.elevator_remove_req_fn:     " FPTR "  %s\n",
		rq.elevator.elevator_remove_req_fn,
		(p = getsymstr_func((addr_t)rq.elevator.elevator_remove_req_fn))? p: "");
	mprintf("elevator.elevator_name:              " FPTR "\n",
		rq.elevator.elevator_name);
#endif

	mprintf("request_fn:        " FPTR "  %s\n", rq.request_fn,
		(p = getsymstr_func((addr_t)rq.request_fn))? p: "");
	mprintf("back_merge_fn:     " FPTR "  %s\n", rq.back_merge_fn,
		(p = getsymstr_func((addr_t)rq.back_merge_fn))? p: "");
	mprintf("front_merge_fn:    " FPTR "  %s\n", rq.front_merge_fn,
		(p = getsymstr_func((addr_t)rq.front_merge_fn))? p: "");
	mprintf("merge_requests_fn: " FPTR "  %s\n", rq.merge_requests_fn,
		(p = getsymstr_func((addr_t)rq.merge_requests_fn))? p: "");
	mprintf("make_request_fn:   " FPTR "  %s\n", rq.make_request_fn,
		(p = getsymstr_func((addr_t)rq.make_request_fn))? p: "");
	mprintf("prep_rq_fn:        " FPTR "  %s\n", rq.prep_rq_fn,
		(p = getsymstr_func((addr_t)rq.prep_rq_fn))? p: "");
	mprintf("unplug_fn:         " FPTR "  %s\n", rq.unplug_fn,
		(p = getsymstr_func((addr_t)rq.unplug_fn))? p: "");
	mprintf("merge_bvec_fn:     " FPTR "  %s\n", rq.merge_bvec_fn,
		(p = getsymstr_func((addr_t)rq.merge_bvec_fn))? p: "");
	mprintf("queuedata:         " FPTR "\n", rq.queuedata);

	mprintf("plug_list:         ");
	if ((addr_t)rq.plug_list.next == addr + OFFSET(struct request_queue, plug_list))
		mprintf(SPTR "  " SPTR "\n", "-", "-");
	else
		mprintf(FPTR "  " FPTR "\n",
			rq.plug_list.next, rq.plug_list.prev);
	mprintf("queue_flags:       %lx\n", rq.queue_flags);
	mprintf("queue_lock:        " FPTR "  %s\n", rq.queue_lock,
		(p = getsymstr((addr_t)rq.queue_lock))? p: "");
	mprintf("nr_requests:       %lx\n", rq.nr_requests);
	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: "");
	mprintf("refcnt:            %x\n", ATOMIC_READ(rq.refcnt));

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