mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
bitkeeper revision 1.22.2.22 (3e4cda4a2-HBaZScWA7Qk6FzzCDhWQ)
Merge boulderdash.cl.cam.ac.uk:/usr/groups/xeno/BK/xeno into boulderdash.cl.cam.ac.uk:/local/scratch/smh22/xeno.bk
This commit is contained in:
commit
0ac7f11e5b
18 files changed
+1002
-1602
No files matched your search
@@ -42,6 +42,7 @@
|
||||
3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen-2.4.16/common/domain_page.c
|
||||
3ddb79bdeyutmaXEfpQvvxj7eQ0fCw xen-2.4.16/common/event.c
|
||||
3ddb79bd9drcFPVxd4w2GPOIjLlXpA xen-2.4.16/common/kernel.c
|
||||
3e4cd9d8LAAghUY0hNIK72uc2ch_Nw xen-2.4.16/common/keyhandler.c
|
||||
3ddb79bduhSEZI8xa7IbGQCpap5y2A xen-2.4.16/common/lib.c
|
||||
3ddb79bdS39UXxUtZnaScie83-7VTQ xen-2.4.16/common/memory.c
|
||||
3ddb79bdN51qpRC-6bOH-v5hl_AK6A xen-2.4.16/common/network.c
|
||||
@@ -231,6 +232,7 @@
|
||||
3ddb79c2b3qe-6Ann09FqZBF4IrJaQ xen-2.4.16/include/xeno/irq_cpustat.h
|
||||
3ddb79c11w_O7z7YZJnzuDSxaK5LlA xen-2.4.16/include/xeno/kdev_t.h
|
||||
3e4540ccPHqIIv2pvnQ1gV8LUnoHIg xen-2.4.16/include/xeno/kernel.h
|
||||
3e4cd9d8elj_7EgAs9Of56RQ2Yq_4g xen-2.4.16/include/xeno/keyhandler.h
|
||||
3ddb79c1NfYlOrWNqgZkj9EwtFfJow xen-2.4.16/include/xeno/lib.h
|
||||
3ddb79c18Ajy7micDGQQfJ0zWgEHtA xen-2.4.16/include/xeno/list.h
|
||||
3ddb79c0_s2_wgV0cA6tztEaeyy1NA xen-2.4.16/include/xeno/major.h
|
||||
@@ -273,7 +275,6 @@
|
||||
3ddb79b8L4xnwrcvWk6nAbgKVbNkSA xenolinux-2.4.16-sparse/arch/xeno/config.in
|
||||
3ddb79b7v_Be34as7_mlzFlw65hOjQ xenolinux-2.4.16-sparse/arch/xeno/defconfig
|
||||
3ddb79b7KUvtx0knQJoRaBDZQeNidg xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile
|
||||
3ddb79b6Rc0uAOGFthIFxq1KGWZ_Iw xenolinux-2.4.16-sparse/arch/xeno/drivers/block/block.c
|
||||
3e4a8cb7JECr--r1ipnrkd7NKdbUqQ xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block.c
|
||||
3e4a8cb7SLWsLTXQjv7ng6-3hL4pCA xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block_test.c
|
||||
3ddb79b7LLVJBGynxHSOh9A9l97sug xenolinux-2.4.16-sparse/arch/xeno/drivers/console/Makefile
|
||||
|
||||
@@ -19,3 +19,4 @@ xen-2.4.16/include/xeno/sched.h.orig
|
||||
xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile.orig
|
||||
xenolinux-2.4.16-sparse/arch/xeno/drivers/block/block.c.orig
|
||||
xenolinux-2.4.16-sparse/scripts/kconfig.tk
|
||||
xen-2.4.16/foo
|
||||
@@ -283,6 +283,7 @@ void __init start_of_day(void)
|
||||
extern int setup_network_devices(void);
|
||||
extern void net_init(void);
|
||||
extern void initialize_block_io(void);
|
||||
extern void initialize_keytable();
|
||||
extern void initialize_serial(void);
|
||||
extern void initialize_keyboard(void);
|
||||
|
||||
@@ -337,8 +338,9 @@ void __init start_of_day(void)
|
||||
#endif
|
||||
do_initcalls();
|
||||
|
||||
initialize_keytable(); /* call back handling for key codes */
|
||||
initialize_serial(); /* setup serial 'driver' (for debugging) */
|
||||
initialize_keyboard(); /* setup keyboard (also for debugging) */
|
||||
initialize_keyboard(); /* setup keyboard (also for debugging) */
|
||||
|
||||
if ( !setup_network_devices() )
|
||||
panic("Must have a network device!\n");
|
||||
|
||||
@@ -762,7 +762,11 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params)
|
||||
unsigned char nfsroot[70];
|
||||
snprintf(nfsroot, 70, opt_nfsroot, dom);
|
||||
snprintf(boot, 200,
|
||||
#if 1
|
||||
" root=/dev/nfs ip=%s:%s:%s:%s::eth0:off nfsroot=%s",
|
||||
#else
|
||||
" ro root=/dev/xhda7 ip=%s:%s:%s:%s::eth0:off arfle=%s",
|
||||
#endif
|
||||
quad_to_str(opt_ipbase + dom, ipbase),
|
||||
quad_to_str(opt_nfsserv, nfsserv),
|
||||
quad_to_str(opt_gateway, gateway),
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
#include <xeno/keyhandler.h>
|
||||
#include <xeno/reboot.h>
|
||||
|
||||
#define KEY_MAX 256
|
||||
#define STR_MAX 64
|
||||
|
||||
typedef struct _key_te {
|
||||
key_handler *handler;
|
||||
char desc[STR_MAX];
|
||||
} key_te_t;
|
||||
|
||||
static key_te_t key_table[KEY_MAX];
|
||||
|
||||
void add_key_handler(u_char key, key_handler *handler, char *desc)
|
||||
{
|
||||
int i;
|
||||
char *str;
|
||||
|
||||
if(key_table[key].handler != NULL)
|
||||
printk("Warning: overwriting handler for key 0x%x\n", key);
|
||||
|
||||
key_table[key].handler = handler;
|
||||
|
||||
str = key_table[key].desc;
|
||||
for(i = 0; i < STR_MAX; i++) {
|
||||
if(*desc)
|
||||
*str++ = *desc++;
|
||||
else break;
|
||||
}
|
||||
if (i == STR_MAX)
|
||||
key_table[key].desc[STR_MAX-1] = '\0';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
key_handler *get_key_handler(u_char key)
|
||||
{
|
||||
return key_table[key].handler;
|
||||
}
|
||||
|
||||
|
||||
void show_handlers(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk("'%c' pressed -> showing installed handlers\n", key);
|
||||
for(i=0; i < KEY_MAX; i++)
|
||||
if(key_table[i].handler)
|
||||
printk("ASCII '%02x' => %s\n", i, key_table[i].desc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void dump_registers(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
extern void show_registers(struct pt_regs *regs);
|
||||
|
||||
printk("'%c' pressed -> dumping registers\n", key);
|
||||
show_registers(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
void halt_machine(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
printk("'%c' pressed -> rebooting machine\n", key);
|
||||
machine_restart(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* XXX SMH: this is keir's fault */
|
||||
static char *task_states[] =
|
||||
{
|
||||
"Running",
|
||||
"Interruptible Sleep",
|
||||
"Uninterruptible Sleep",
|
||||
NULL, "Stopped",
|
||||
NULL, NULL, NULL, "Dying",
|
||||
};
|
||||
|
||||
void do_task_queues(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
u_long flags;
|
||||
struct task_struct *p;
|
||||
shared_info_t *s;
|
||||
|
||||
printk("'%c' pressed -> dumping task queues\n", key);
|
||||
read_lock_irqsave(&tasklist_lock, flags);
|
||||
p = &idle0_task;
|
||||
do {
|
||||
printk("Xen: DOM %d, CPU %d [has=%c], state = %s, "
|
||||
"hyp_events = %08x\n",
|
||||
p->domain, p->processor, p->has_cpu ? 'T':'F',
|
||||
task_states[p->state], p->hyp_events);
|
||||
s = p->shared_info;
|
||||
if(!is_idle_task(p)) {
|
||||
printk("Guest: events = %08lx, event_enable = %08lx\n",
|
||||
s->events, s->events_enable);
|
||||
printk("Notifying guest...\n");
|
||||
set_bit(_EVENT_DEBUG, &s->events);
|
||||
}
|
||||
}
|
||||
|
||||
while ( (p = p->next_task) != &idle0_task );
|
||||
read_unlock_irqrestore(&tasklist_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
void initialize_keytable()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* first initialize key handler table */
|
||||
for(i = 0; i < KEY_MAX; i++)
|
||||
key_table[i].handler = (key_handler *)NULL;
|
||||
|
||||
/* setup own handlers */
|
||||
add_key_handler('d', dump_registers, "dump registers");
|
||||
add_key_handler('h', show_handlers, "show this message");
|
||||
add_key_handler('q', do_task_queues, "dump task queues + guest state");
|
||||
add_key_handler('r', halt_machine, "reboot machine ungracefully");
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -31,6 +31,9 @@
|
||||
#include <xeno/slab.h>
|
||||
#include <xeno/module.h>
|
||||
|
||||
/* XXX SMH: temporarily we just dive at xen_block completion handler */
|
||||
extern void end_block_io_op(struct buffer_head *bh);
|
||||
|
||||
static void end_buffer_dummy(struct buffer_head *bh, int uptodate)
|
||||
{
|
||||
/* do nothing */
|
||||
@@ -1030,6 +1033,8 @@ out:
|
||||
return 0;
|
||||
end_io:
|
||||
bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
|
||||
/* XXX SMH: do we need this every time? */
|
||||
end_block_io_op(bh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1101,6 +1106,8 @@ void generic_make_request (int rw, struct buffer_head * bh)
|
||||
|
||||
/* Yecch again */
|
||||
bh->b_end_io(bh, 0);
|
||||
/* XXX SMH */
|
||||
end_block_io_op(bh);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1142,10 +1149,6 @@ void generic_make_request (int rw, struct buffer_head * bh)
|
||||
*/
|
||||
void submit_bh(int rw, struct buffer_head * bh)
|
||||
{
|
||||
int count = bh->b_size >> 9;
|
||||
|
||||
/* printk(KERN_ALERT "submit_bh\n"); */
|
||||
|
||||
if (!test_bit(BH_Lock, &bh->b_state))
|
||||
BUG();
|
||||
|
||||
@@ -1160,17 +1163,6 @@ void submit_bh(int rw, struct buffer_head * bh)
|
||||
/* bh->b_rsector = bh->b_blocknr * count; */
|
||||
|
||||
generic_make_request(rw, bh);
|
||||
|
||||
#if 0
|
||||
switch (rw) {
|
||||
case WRITE:
|
||||
kstat.pgpgout += count;
|
||||
break;
|
||||
default:
|
||||
kstat.pgpgin += count;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1267,6 +1259,8 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
|
||||
BUG();
|
||||
end_io:
|
||||
bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
|
||||
/* XXX SMH */
|
||||
end_block_io_op(bh);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1275,6 +1269,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
|
||||
return;
|
||||
|
||||
sorry:
|
||||
printk("~~~");
|
||||
/* Make sure we don't get infinite dirty retries.. */
|
||||
for (i = 0; i < nr; i++)
|
||||
mark_buffer_clean(bhs[i]);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <asm-i386/io.h>
|
||||
#include <asm/spinlock.h>
|
||||
|
||||
#include <xeno/keyhandler.h>
|
||||
|
||||
#define XEN_BLK_DEBUG 0
|
||||
#define XEN_BLK_DEBUG_LEVEL KERN_ALERT
|
||||
|
||||
@@ -28,10 +30,12 @@ typedef struct blk_request
|
||||
struct task_struct *domain; /* requesting domain */
|
||||
} blk_request_t;
|
||||
|
||||
static int pending_work; /* which domains have work for us? */
|
||||
static int pending_work; /* which domains have work for us? */
|
||||
|
||||
blk_request_t blk_request_list[XEN_BLK_REQUEST_LIST_SIZE];
|
||||
struct list_head free_queue; /* unused requests */
|
||||
struct list_head pending_queue; /* waiting for hardware */
|
||||
|
||||
struct list_head free_queue; /* unused requests */
|
||||
struct list_head pending_queue; /* waiting for hardware */
|
||||
struct list_head io_done_queue; /* request completed. send to guest os */
|
||||
spinlock_t free_queue_lock;
|
||||
spinlock_t pending_queue_lock;
|
||||
@@ -49,61 +53,46 @@ int dispatch_debug_block_io (int index);
|
||||
* end_block_io_op
|
||||
*
|
||||
* IO has completed. Need to notify the guest operating system.
|
||||
* Called from hardware interrupt.
|
||||
* Called from ll_rw_block -- currently /DIRECTLY/ -- XXX FIXME
|
||||
* (e.g. hook into proper end processing of ll_rw)
|
||||
*/
|
||||
|
||||
void end_block_io_op(struct buffer_head * bh)
|
||||
{
|
||||
unsigned long cpu_mask;
|
||||
/* struct list_head *list;*/
|
||||
blk_request_t *blk_request = NULL;
|
||||
unsigned long flags; /* irq save */
|
||||
|
||||
#if 0
|
||||
printk("{E}");
|
||||
#endif
|
||||
if (XEN_BLK_DEBUG) printk(XEN_BLK_DEBUG_LEVEL
|
||||
"XEN end_block_io_op, bh: %lx\n",
|
||||
(unsigned long)bh);
|
||||
|
||||
{
|
||||
char temp[100];
|
||||
sprintf(temp, "endio bh: 0x%p, blkno: 0x%lx",
|
||||
bh, bh->b_blocknr);
|
||||
printx(temp);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&pending_queue_lock, flags);
|
||||
/*
|
||||
list_for_each (list, &pending_queue)
|
||||
{
|
||||
blk_request = list_entry(list, blk_request_t, queue);
|
||||
if (blk_request->bh == bh)
|
||||
{
|
||||
break;
|
||||
unsigned long cpu_mask;
|
||||
/* struct list_head *list;*/
|
||||
blk_request_t *blk_request = NULL;
|
||||
unsigned long flags; /* irq save */
|
||||
|
||||
if (XEN_BLK_DEBUG)
|
||||
printk(XEN_BLK_DEBUG_LEVEL "XEN end_block_io_op, bh: %lx\n",
|
||||
(unsigned long)bh);
|
||||
|
||||
spin_lock_irqsave(&pending_queue_lock, flags);
|
||||
blk_request = (blk_request_t *)bh->b_xen_request;
|
||||
|
||||
if (blk_request == NULL) {
|
||||
printk (KERN_ALERT
|
||||
" block io interrupt received for unknown buffer [0x%lx]\n",
|
||||
(unsigned long) bh);
|
||||
spin_unlock_irqrestore(&pending_queue_lock, flags);
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
}
|
||||
*/
|
||||
blk_request = (blk_request_t *)bh->b_xen_request;
|
||||
if (blk_request == NULL)
|
||||
{
|
||||
printk (KERN_ALERT
|
||||
" block io interrupt received for unknown buffer [0x%lx]\n",
|
||||
(unsigned long) bh);
|
||||
|
||||
list_del(&blk_request->queue);
|
||||
spin_unlock_irqrestore(&pending_queue_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&io_done_queue_lock, flags);
|
||||
list_add_tail(&blk_request->queue, &io_done_queue);
|
||||
|
||||
/* enqueue work for 'flush_blk_queue' handler */
|
||||
cpu_mask = mark_hyp_event(blk_request->domain, _HYP_EVENT_BLK_RX);
|
||||
spin_unlock_irqrestore(&io_done_queue_lock, flags);
|
||||
|
||||
/* now kick the hypervisor */
|
||||
hyp_event_notify(cpu_mask);
|
||||
return;
|
||||
}
|
||||
list_del(&blk_request->queue);
|
||||
spin_unlock_irqrestore(&pending_queue_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&io_done_queue_lock, flags);
|
||||
list_add_tail(&blk_request->queue, &io_done_queue);
|
||||
spin_unlock_irqrestore(&io_done_queue_lock, flags);
|
||||
|
||||
/* enqueue work */
|
||||
cpu_mask = mark_hyp_event(blk_request->domain, _HYP_EVENT_BLK_RX);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -115,126 +104,82 @@ void end_block_io_op(struct buffer_head * bh)
|
||||
|
||||
void flush_blk_queue(void)
|
||||
{
|
||||
blk_request_t *blk_request;
|
||||
int position = 0;
|
||||
blk_ring_t *blk_ring;
|
||||
unsigned long flags;
|
||||
int loop;
|
||||
blk_request_t *blk_request;
|
||||
int position = 0;
|
||||
blk_ring_t *blk_ring;
|
||||
unsigned long flags;
|
||||
int loop;
|
||||
|
||||
spin_lock_irqsave(&io_done_queue_lock, flags);
|
||||
clear_bit(_HYP_EVENT_BLK_RX, ¤t->hyp_events);
|
||||
|
||||
while (!list_empty(&io_done_queue)) {
|
||||
|
||||
#if 0
|
||||
printk("{F}");
|
||||
#endif
|
||||
/*
|
||||
if (XEN_BLK_DEBUG) printk(XEN_BLK_DEBUG_LEVEL
|
||||
"XEN flush_blk_queue\n");
|
||||
*/
|
||||
blk_request = list_entry(io_done_queue.next, blk_request_t, queue);
|
||||
list_del (&blk_request->queue);
|
||||
spin_unlock_irqrestore(&io_done_queue_lock, flags);
|
||||
|
||||
/* place on ring for guest os */
|
||||
blk_ring = blk_request->domain->blk_ring_base;
|
||||
position = blk_ring->brx_prod;
|
||||
|
||||
clear_bit(_HYP_EVENT_BLK_RX, ¤t->hyp_events);
|
||||
if (XEN_BLK_DEBUG)
|
||||
printk(XEN_BLK_DEBUG_LEVEL "XEN flush_blk_queue [%d]\n", position);
|
||||
|
||||
/* NEED LOCK? */
|
||||
spin_lock_irqsave(&io_done_queue_lock, flags);
|
||||
while (!list_empty(&io_done_queue))
|
||||
{
|
||||
blk_request = list_entry(io_done_queue.next, blk_request_t, queue);
|
||||
list_del (&blk_request->queue);
|
||||
memcpy(&blk_ring->brx_ring[position], &blk_request->request,
|
||||
sizeof(blk_ring_entry_t));
|
||||
blk_ring->brx_prod = BLK_RX_RING_INC(blk_ring->brx_prod);
|
||||
|
||||
/* notify appropriate guest os */
|
||||
set_bit(_EVENT_BLK_RX, &blk_request->domain->shared_info->events);
|
||||
|
||||
/* free the buffer header allocated in do_block_io_op */
|
||||
if (blk_request->bh)
|
||||
kfree(blk_request->bh);
|
||||
|
||||
spin_lock_irqsave(&free_queue_lock, flags);
|
||||
list_add_tail(&blk_request->queue, &free_queue);
|
||||
spin_unlock_irqrestore(&free_queue_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&io_done_queue_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&io_done_queue_lock, flags);
|
||||
|
||||
/* place on ring for guest os */
|
||||
blk_ring = blk_request->domain->blk_ring_base;
|
||||
position = blk_ring->rx_prod;
|
||||
|
||||
if (XEN_BLK_DEBUG) printk(XEN_BLK_DEBUG_LEVEL
|
||||
"XEN flush_blk_queue [%d]\n", position);
|
||||
/* XXX SMH: below is ugly and dangerous -- fix */
|
||||
/*
|
||||
* now check if there is any pending work from any domain
|
||||
* that we were previously unable to process.
|
||||
*
|
||||
* NOTE: the current algorithm will check _every_ domain
|
||||
* and wake up _every_ domain that has pending work.
|
||||
* In the future, we should stop waking up domains once
|
||||
* there isn't any space for their requests any more
|
||||
* ALSO, we need to maintain a counter of the last domain
|
||||
* that we woke up for fairness... we shouldn't restart
|
||||
* at domain 0 every time (although we might want to special
|
||||
* case domain 0);
|
||||
*/
|
||||
for (loop = 0; loop < XEN_BLOCK_MAX_DOMAINS; loop++) {
|
||||
|
||||
memcpy(&blk_ring->rx_ring[position], &blk_request->request,
|
||||
sizeof(blk_ring_entry_t));
|
||||
blk_ring->rx_prod = BLK_RX_RING_INC(blk_ring->rx_prod);
|
||||
int domain = pending_work & (1 << loop);
|
||||
|
||||
/* notify appropriate guest os */
|
||||
set_bit(_EVENT_BLK_RX,
|
||||
&blk_request->domain->shared_info->events);
|
||||
if (domain) {
|
||||
|
||||
if (0)
|
||||
{
|
||||
int temp;
|
||||
struct buffer_head *bh = blk_request->bh;
|
||||
char * vbuffer = bh->b_data;
|
||||
struct task_struct *mytask = current;
|
||||
|
||||
printk (KERN_ALERT "XEN return block 0x%lx\n", bh->b_blocknr);
|
||||
while (mytask->domain != loop)
|
||||
mytask = mytask->next_task;
|
||||
|
||||
for (temp = 0; temp < bh->b_size; temp++)
|
||||
{
|
||||
if (temp % 16 == 0) printk ("[%04x] ", temp);
|
||||
else if (temp % 4 == 0) printk (" ");
|
||||
printk ("%02x",
|
||||
vbuffer[temp] & 255);
|
||||
if ((temp + 1) % 16 == 0) printk ("\n");
|
||||
}
|
||||
printk ("\n\n");
|
||||
pending_work = pending_work & !(1 << loop);
|
||||
do_block_io_op_domain(mytask);
|
||||
}
|
||||
}
|
||||
|
||||
/* free the buffer header allocated in do_block_io_op */
|
||||
if (blk_request->bh)
|
||||
{
|
||||
kfree(blk_request->bh); /* alloc in do_block_io_op */
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&free_queue_lock, flags);
|
||||
list_add_tail(&blk_request->queue, &free_queue);
|
||||
spin_unlock_irqrestore(&free_queue_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&io_done_queue_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&io_done_queue_lock, flags);
|
||||
|
||||
/*
|
||||
* now check if there is any pending work from any domain
|
||||
* that we were previously unable to process.
|
||||
*
|
||||
* NOTE: the current algorithm will check _every_ domain
|
||||
* and wake up _every_ domain that has pending work.
|
||||
* In the future, we should stop waking up domains once
|
||||
* there isn't any space for their requests any more
|
||||
* ALSO, we need to maintain a counter of the last domain
|
||||
* that we woke up for fairness... we shouldn't restart
|
||||
* at domain 0 every time (although we might want to special
|
||||
* case domain 0);
|
||||
*/
|
||||
for (loop = 0; loop < XEN_BLOCK_MAX_DOMAINS; loop++)
|
||||
{
|
||||
int domain = pending_work & (1 << loop);
|
||||
|
||||
if (domain)
|
||||
{
|
||||
struct task_struct *mytask = current;
|
||||
|
||||
/*
|
||||
printk (KERN_ALERT
|
||||
"flush_blk_queue pending_work: %x domain: %d loop: %d\n",
|
||||
pending_work, domain, loop);
|
||||
*/
|
||||
/* IS THERE A BETTER WAY OF FINDING THE TASK STRUCT FOR A
|
||||
* PARTICULAR DOMAIN?
|
||||
*
|
||||
* WHAT IF THE TASK GOES AWAY BEFORE WE HAVE A CHANCE TO
|
||||
* FINISH PROCESSING ALL OF ITS REQUESTS?
|
||||
*/
|
||||
while (mytask->domain != loop)
|
||||
{
|
||||
mytask = mytask->next_task;
|
||||
}
|
||||
do_block_io_op_domain(mytask);
|
||||
|
||||
pending_work = pending_work & !(1 << loop);
|
||||
/*
|
||||
printk (KERN_ALERT
|
||||
" pending_work: %x domain: %d loop: %d\n",
|
||||
pending_work, domain, loop);
|
||||
*/
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* do_block_io_op
|
||||
*
|
||||
@@ -244,186 +189,132 @@ void flush_blk_queue(void)
|
||||
|
||||
long do_block_io_op (void)
|
||||
{
|
||||
return do_block_io_op_domain(current);
|
||||
return do_block_io_op_domain(current);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* do_block_io_op
|
||||
*
|
||||
* handle the requests for a particular domain
|
||||
*/
|
||||
|
||||
long do_block_io_op_domain (struct task_struct* task)
|
||||
{
|
||||
blk_ring_t *blk_ring = task->blk_ring_base;
|
||||
int loop;
|
||||
blk_ring_t *blk_ring = task->blk_ring_base;
|
||||
int loop, status;
|
||||
|
||||
#if 0
|
||||
printk("{%d}", current->domain);
|
||||
#endif
|
||||
if (XEN_BLK_DEBUG) printk(XEN_BLK_DEBUG_LEVEL
|
||||
"XEN do_block_io_op %d %d\n",
|
||||
blk_ring->tx_cons, blk_ring->tx_prod);
|
||||
if (XEN_BLK_DEBUG)
|
||||
printk(XEN_BLK_DEBUG_LEVEL "XEN do_block_io_op %d %d\n",
|
||||
blk_ring->btx_cons, blk_ring->btx_prod);
|
||||
|
||||
for (loop = blk_ring->tx_cons;
|
||||
loop != blk_ring->tx_prod;
|
||||
loop = BLK_TX_RING_INC(loop))
|
||||
{
|
||||
int status = 1;
|
||||
for (loop = blk_ring->btx_cons;
|
||||
loop != blk_ring->btx_prod;
|
||||
loop = BLK_TX_RING_INC(loop)) {
|
||||
|
||||
switch (blk_ring->tx_ring[loop].operation)
|
||||
{
|
||||
case XEN_BLOCK_READ :
|
||||
case XEN_BLOCK_WRITE :
|
||||
{
|
||||
status = dispatch_rw_block_io(loop);
|
||||
break;
|
||||
}
|
||||
case XEN_BLOCK_PROBE :
|
||||
{
|
||||
status = dispatch_probe_block_io(loop);
|
||||
break;
|
||||
}
|
||||
case XEN_BLOCK_DEBUG :
|
||||
{
|
||||
status = dispatch_debug_block_io(loop);
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
printk (KERN_ALERT "error: unknown block io operation [%d]\n",
|
||||
blk_ring->tx_ring[loop].operation);
|
||||
BUG();
|
||||
}
|
||||
status = 1;
|
||||
|
||||
switch (blk_ring->btx_ring[loop].operation) {
|
||||
|
||||
case XEN_BLOCK_READ:
|
||||
case XEN_BLOCK_WRITE:
|
||||
status = dispatch_rw_block_io(loop);
|
||||
break;
|
||||
|
||||
case XEN_BLOCK_PROBE:
|
||||
status = dispatch_probe_block_io(loop);
|
||||
break;
|
||||
|
||||
case XEN_BLOCK_DEBUG:
|
||||
status = dispatch_debug_block_io(loop);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk (KERN_ALERT "error: unknown block io operation [%d]\n",
|
||||
blk_ring->btx_ring[loop].operation);
|
||||
BUG();
|
||||
}
|
||||
|
||||
|
||||
if (status) {
|
||||
/*
|
||||
** Unable to successfully issue / complete command, maybe because
|
||||
** another resource (e.g. disk request buffers) is unavailable.
|
||||
** stop removing items from the communications ring and try later
|
||||
*/
|
||||
pending_work = pending_work | (1 << task->domain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (status)
|
||||
{
|
||||
/* unable to successfully issue / complete command, maybe because
|
||||
* another resource (e.g. disk request buffers) is unavailable.
|
||||
* stop removing items from the communications ring and try
|
||||
* again later
|
||||
*/
|
||||
|
||||
/*
|
||||
printk ("do_block_io_op_domain domain:%d, pending_work: %x\n",
|
||||
task->domain, pending_work);
|
||||
*/
|
||||
pending_work = pending_work | (1 << task->domain);
|
||||
/*
|
||||
printk ("do_block_io_op_domain domain:%d, pending_work: %x\n",
|
||||
task->domain, pending_work);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
blk_ring->tx_cons = loop;
|
||||
|
||||
return 0L;
|
||||
blk_ring->btx_cons = loop;
|
||||
return 0L;
|
||||
}
|
||||
|
||||
|
||||
int dispatch_debug_block_io (int index)
|
||||
{
|
||||
struct task_struct *task;
|
||||
blk_ring_t *blk_ring = current->blk_ring_base;
|
||||
char * buffer;
|
||||
char output[1000];
|
||||
|
||||
int foobar = (unsigned long)blk_ring->tx_ring[index].block_number;
|
||||
|
||||
printk (KERN_ALERT "dispatch_debug_block_io %d\n", foobar);
|
||||
|
||||
buffer = phys_to_virt(blk_ring->tx_ring[index].buffer);
|
||||
strcpy (buffer, "DEBUG\n");
|
||||
|
||||
task = current;
|
||||
sprintf (buffer, "current %d\n", current->domain);
|
||||
sprintf (buffer, "%s tx: prod: %d, cons: %d, size: %d\n", buffer,
|
||||
blk_ring->tx_prod, blk_ring->tx_cons, blk_ring->tx_ring_size);
|
||||
sprintf (buffer, "%s rx: prod: %d, cons: %d, size: %d\n", buffer,
|
||||
blk_ring->rx_prod, blk_ring->rx_cons, blk_ring->rx_ring_size);
|
||||
|
||||
task = task->next_task;
|
||||
while (task != current)
|
||||
{
|
||||
blk_ring = task->blk_ring_base;
|
||||
sprintf (buffer, "%stask %d\n", buffer, task->domain);
|
||||
if (blk_ring != NULL)
|
||||
{
|
||||
sprintf (buffer, "%s tx: prod: %d, cons: %d, size: %d\n",
|
||||
buffer, blk_ring->tx_prod, blk_ring->tx_cons,
|
||||
blk_ring->tx_ring_size);
|
||||
sprintf (buffer, "%s rx: prod: %d, cons: %d, size: %d\n",
|
||||
buffer, blk_ring->rx_prod, blk_ring->rx_cons,
|
||||
blk_ring->rx_ring_size);
|
||||
}
|
||||
task = task->next_task;
|
||||
}
|
||||
dumpx(output, foobar);
|
||||
sprintf (buffer, "%s%s\n", buffer, output);
|
||||
|
||||
return 0;
|
||||
printk (KERN_ALERT "dispatch_debug_block_io: UNIMPL\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern void ide_probe_devices(xen_disk_info_t *xdi);
|
||||
|
||||
int dispatch_probe_block_io (int index)
|
||||
{
|
||||
blk_ring_t *blk_ring = current->blk_ring_base;
|
||||
xen_disk_info_t *xdi;
|
||||
|
||||
xdi = phys_to_virt(blk_ring->tx_ring[index].buffer);
|
||||
|
||||
ide_probe_devices(xdi);
|
||||
|
||||
return 0;
|
||||
blk_ring_t *blk_ring = current->blk_ring_base;
|
||||
xen_disk_info_t *xdi;
|
||||
|
||||
xdi = phys_to_virt((unsigned long)blk_ring->btx_ring[index].buffer);
|
||||
|
||||
ide_probe_devices(xdi);
|
||||
|
||||
memcpy(&blk_ring->brx_ring[blk_ring->brx_prod],
|
||||
&blk_ring->btx_ring[index],
|
||||
sizeof(blk_ring_entry_t));
|
||||
blk_ring->brx_prod = BLK_RX_RING_INC(blk_ring->brx_prod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
|
||||
|
||||
int dispatch_rw_block_io (int index)
|
||||
{
|
||||
blk_ring_t *blk_ring = current->blk_ring_base;
|
||||
struct buffer_head *bh;
|
||||
struct request_queue *rq;
|
||||
int operation;
|
||||
blk_request_t *blk_request;
|
||||
unsigned long flags;
|
||||
|
||||
blk_ring_t *blk_ring = current->blk_ring_base;
|
||||
struct buffer_head *bh;
|
||||
struct request_queue *rq;
|
||||
int operation;
|
||||
blk_request_t *blk_request;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* check to make sure that the block request seems at least
|
||||
* a bit legitimate
|
||||
*/
|
||||
if ((blk_ring->tx_ring[index].block_size & (0x200 - 1)) != 0)
|
||||
{
|
||||
printk(KERN_ALERT
|
||||
" error: dodgy block size: %d\n",
|
||||
blk_ring->tx_ring[index].block_size);
|
||||
BUG();
|
||||
if ((blk_ring->btx_ring[index].block_size & (0x200 - 1)) != 0) {
|
||||
printk(KERN_ALERT " error: dodgy block size: %d\n",
|
||||
blk_ring->btx_ring[index].block_size);
|
||||
BUG();
|
||||
}
|
||||
|
||||
|
||||
if (XEN_BLK_DEBUG)
|
||||
{
|
||||
printk(XEN_BLK_DEBUG_LEVEL
|
||||
" tx_cons: %d tx_prod %d index: %d op: %s, pri: %s\n",
|
||||
blk_ring->tx_cons, blk_ring->tx_prod, index,
|
||||
(blk_ring->tx_ring[index].operation == XEN_BLOCK_READ ? "read" : "write"),
|
||||
(blk_ring->tx_ring[index].priority == XEN_BLOCK_SYNC ? "sync" : "async"));
|
||||
}
|
||||
|
||||
{
|
||||
char temp[100];
|
||||
sprintf(temp, "issue buf: 0x%p, bh: 0x%p, blkno: 0x%lx",
|
||||
blk_ring->tx_ring[index].buffer, bh,
|
||||
(unsigned long)blk_ring->tx_ring[index].block_number);
|
||||
printx(temp);
|
||||
if (XEN_BLK_DEBUG) {
|
||||
printk(XEN_BLK_DEBUG_LEVEL " btx_cons: %d btx_prod %d index: %d "
|
||||
"op: %s, pri: %s\n", blk_ring->btx_cons, blk_ring->btx_prod,
|
||||
index,
|
||||
(blk_ring->btx_ring[index].operation == XEN_BLOCK_READ ?
|
||||
"read" : "write"),
|
||||
(blk_ring->btx_ring[index].priority == XEN_BLOCK_SYNC ?
|
||||
"sync" : "async"));
|
||||
}
|
||||
|
||||
/* find an empty request slot */
|
||||
spin_lock_irqsave(&free_queue_lock, flags);
|
||||
if (list_empty(&free_queue))
|
||||
{
|
||||
/* printk (KERN_ALERT "dispatch_rw_block_io EMPTY FREE LIST!! %d\n", index); */
|
||||
spin_unlock_irqrestore(&free_queue_lock, flags);
|
||||
return 1;
|
||||
if (list_empty(&free_queue)) {
|
||||
spin_unlock_irqrestore(&free_queue_lock, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
blk_request = list_entry(free_queue.next, blk_request_t, queue);
|
||||
list_del(&blk_request->queue);
|
||||
spin_unlock_irqrestore(&free_queue_lock, flags);
|
||||
@@ -432,60 +323,109 @@ int dispatch_rw_block_io (int index)
|
||||
spin_lock_irqsave(&pending_queue_lock, flags);
|
||||
list_add_tail(&blk_request->queue, &pending_queue);
|
||||
spin_unlock_irqrestore(&pending_queue_lock, flags);
|
||||
|
||||
|
||||
/* we'll be doing this frequently, would a cache be appropriate? */
|
||||
/* free in flush_blk_queue */
|
||||
bh = (struct buffer_head *) kmalloc(sizeof(struct buffer_head),
|
||||
GFP_KERNEL);
|
||||
if (!bh)
|
||||
{
|
||||
printk(KERN_ALERT "ERROR: bh is null\n");
|
||||
BUG();
|
||||
if (!bh) {
|
||||
printk(KERN_ALERT "ERROR: bh is null\n");
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* set just the important bits of the buffer header */
|
||||
memset (bh, 0, sizeof (struct buffer_head));
|
||||
|
||||
bh->b_blocknr = blk_ring->tx_ring[index].block_number; /* block number */
|
||||
bh->b_size = blk_ring->tx_ring[index].block_size; /* block size */
|
||||
bh->b_dev = blk_ring->tx_ring[index].device; /* device (B_FREE = free) */
|
||||
bh->b_rsector = blk_ring->tx_ring[index].sector_number; /* sector number */
|
||||
|
||||
bh->b_data = phys_to_virt(blk_ring->tx_ring[index].buffer);
|
||||
/* ptr to data blk */
|
||||
bh->b_count.counter = 1; /* users using this block */
|
||||
bh->b_xen_request = (void *)blk_request; /* save block request */
|
||||
|
||||
|
||||
if (blk_ring->tx_ring[index].operation == XEN_BLOCK_WRITE)
|
||||
{
|
||||
bh->b_state = ((1 << BH_JBD) | /* buffer state bitmap */
|
||||
(1 << BH_Mapped) |
|
||||
(1 << BH_Req) |
|
||||
(1 << BH_Dirty) |
|
||||
(1 << BH_Uptodate));
|
||||
operation = WRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
bh->b_state = (1 << BH_Mapped); /* buffer state bitmap */
|
||||
operation = READ;
|
||||
bh->b_blocknr = blk_ring->btx_ring[index].block_number;
|
||||
bh->b_size = blk_ring->btx_ring[index].block_size;
|
||||
bh->b_dev = blk_ring->btx_ring[index].device;
|
||||
bh->b_rsector = blk_ring->btx_ring[index].sector_number;
|
||||
bh->b_data = phys_to_virt((unsigned long)
|
||||
blk_ring->btx_ring[index].buffer);
|
||||
bh->b_count.counter = 1;
|
||||
bh->b_xen_request = (void *)blk_request;
|
||||
|
||||
if (blk_ring->btx_ring[index].operation == XEN_BLOCK_WRITE) {
|
||||
bh->b_state = ((1 << BH_JBD) | (1 << BH_Mapped) | (1 << BH_Req) |
|
||||
(1 << BH_Dirty) | (1 << BH_Uptodate));
|
||||
operation = WRITE;
|
||||
} else {
|
||||
bh->b_state = (1 << BH_Mapped);
|
||||
operation = READ;
|
||||
}
|
||||
|
||||
/* save meta data about request */
|
||||
memcpy(&blk_request->request, /* NEED COPY_FROM_USER? */
|
||||
&blk_ring->tx_ring[index], sizeof(blk_ring_entry_t));
|
||||
blk_request->bh = bh;
|
||||
blk_request->domain = current; /* save current domain */
|
||||
|
||||
/* save meta data about request XXX SMH: should copy_from_user() */
|
||||
memcpy(&blk_request->request,
|
||||
&blk_ring->btx_ring[index], sizeof(blk_ring_entry_t));
|
||||
blk_request->bh = bh;
|
||||
blk_request->domain = current;
|
||||
|
||||
/* dispatch single block request */
|
||||
ll_rw_block(operation, 1, &bh); /* linux top half */
|
||||
ll_rw_block(operation, 1, &bh); /* linux top half */
|
||||
rq = blk_get_queue(bh->b_rdev);
|
||||
generic_unplug_device(rq); /* linux bottom half */
|
||||
generic_unplug_device(rq); /* linux bottom half */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* debug dump_queue
|
||||
* arguments: queue head, name of queue
|
||||
*/
|
||||
void dump_queue(struct list_head *queue, char *name)
|
||||
{
|
||||
struct list_head *list;
|
||||
int loop = 0;
|
||||
|
||||
printk ("QUEUE %s %lx n: %lx, p: %lx\n", name, (unsigned long)queue,
|
||||
(unsigned long) queue->next, (unsigned long) queue->prev);
|
||||
list_for_each (list, queue) {
|
||||
printk (" %s %d : %lx n: %lx, p: %lx\n", name, loop++,
|
||||
(unsigned long)list,
|
||||
(unsigned long)list->next, (unsigned long)list->prev);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void dump_queue_head(struct list_head *queue, char *name)
|
||||
{
|
||||
struct list_head *list;
|
||||
int loop = 0;
|
||||
|
||||
printk ("QUEUE %s %lx n: %lx, p: %lx\n", name, (unsigned long)queue,
|
||||
(unsigned long) queue->next, (unsigned long) queue->prev);
|
||||
list_for_each (list, queue) {
|
||||
printk (" %d : %lx n: %lx, p: %lx\n", loop++,
|
||||
(unsigned long)list,
|
||||
(unsigned long)list->next, (unsigned long)list->prev);
|
||||
if (loop >= 5) return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
u_long flags;
|
||||
|
||||
printk("Dumping block queues:\n");
|
||||
|
||||
spin_lock_irqsave(&free_queue_lock, flags);
|
||||
dump_queue(&free_queue, "FREE QUEUE");
|
||||
spin_unlock_irqrestore(&free_queue_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&pending_queue_lock, flags);
|
||||
dump_queue(&pending_queue, "PENDING QUEUE");
|
||||
spin_unlock_irqrestore(&pending_queue_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&io_done_queue_lock, flags);
|
||||
dump_queue(&io_done_queue, "IO DONE QUEUE");
|
||||
spin_unlock_irqrestore(&io_done_queue_lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* initialize_block_io
|
||||
*
|
||||
@@ -493,128 +433,33 @@ int dispatch_rw_block_io (int index)
|
||||
* called from arch/i386/setup.c::start_of_day
|
||||
*/
|
||||
|
||||
void initialize_block_io ()
|
||||
{
|
||||
int loop;
|
||||
void initialize_block_io (){
|
||||
|
||||
INIT_LIST_HEAD(&free_queue);
|
||||
INIT_LIST_HEAD(&pending_queue);
|
||||
INIT_LIST_HEAD(&io_done_queue);
|
||||
|
||||
spin_lock_init(&free_queue_lock);
|
||||
spin_lock_init(&pending_queue_lock);
|
||||
spin_lock_init(&io_done_queue_lock);
|
||||
|
||||
for (loop = 0; loop < XEN_BLK_REQUEST_LIST_SIZE; loop++)
|
||||
{
|
||||
list_add_tail(&blk_request_list[loop].queue, &free_queue);
|
||||
}
|
||||
|
||||
/*
|
||||
* if bit i is true then domain i has work for us to do.
|
||||
*/
|
||||
pending_work = 0;
|
||||
|
||||
return;
|
||||
int loop;
|
||||
|
||||
INIT_LIST_HEAD(&free_queue);
|
||||
INIT_LIST_HEAD(&pending_queue);
|
||||
INIT_LIST_HEAD(&io_done_queue);
|
||||
|
||||
spin_lock_init(&free_queue_lock);
|
||||
spin_lock_init(&pending_queue_lock);
|
||||
spin_lock_init(&io_done_queue_lock);
|
||||
|
||||
for (loop = 0; loop < XEN_BLK_REQUEST_LIST_SIZE; loop++)
|
||||
{
|
||||
list_add_tail(&blk_request_list[loop].queue, &free_queue);
|
||||
}
|
||||
|
||||
|
||||
add_key_handler('b', dump_blockq, "dump xen ide block queues");
|
||||
|
||||
/*
|
||||
* if bit i is true then domain i has work for us to do.
|
||||
*/
|
||||
pending_work = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/*
|
||||
* debug dump_queue
|
||||
* arguments: queue head, name of queue
|
||||
*/
|
||||
void dump_queue(struct list_head *queue, char *name)
|
||||
{
|
||||
struct list_head *list;
|
||||
int loop = 0;
|
||||
|
||||
printk ("QUEUE %s %lx n: %lx, p: %lx\n", name, (unsigned long)queue,
|
||||
(unsigned long) queue->next, (unsigned long) queue->prev);
|
||||
list_for_each (list, queue)
|
||||
{
|
||||
printk (" %s %d : %lx n: %lx, p: %lx\n", name, loop++,
|
||||
(unsigned long)list,
|
||||
(unsigned long)list->next, (unsigned long)list->prev);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_queue_head(struct list_head *queue, char *name)
|
||||
{
|
||||
struct list_head *list;
|
||||
int loop = 0;
|
||||
|
||||
printk ("QUEUE %s %lx n: %lx, p: %lx\n", name, (unsigned long)queue,
|
||||
(unsigned long) queue->next, (unsigned long) queue->prev);
|
||||
list_for_each (list, queue)
|
||||
{
|
||||
printk (" %d : %lx n: %lx, p: %lx\n", loop++,
|
||||
(unsigned long)list,
|
||||
(unsigned long)list->next, (unsigned long)list->prev);
|
||||
if (loop >= 5) return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
|
||||
#define debug_block_size 200000
|
||||
#define debug_output_size 10
|
||||
|
||||
static int countx = 0;
|
||||
static char * arrayx[debug_block_size];
|
||||
static int outputx = 0;
|
||||
|
||||
void
|
||||
printx (char * string)
|
||||
{
|
||||
char * s;
|
||||
|
||||
s = (char *) kmalloc(strlen(string), GFP_KERNEL);
|
||||
strcpy (s, string);
|
||||
arrayx[countx++] = s;
|
||||
|
||||
if (countx >= debug_block_size)
|
||||
{
|
||||
countx = 0;
|
||||
printk (KERN_ALERT "printx wrap\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
dumpx (char *buffer, int count)
|
||||
{
|
||||
int loop;
|
||||
int start;
|
||||
|
||||
sprintf (buffer, "debug dump\n");
|
||||
|
||||
/*
|
||||
for (loop = outputx;
|
||||
loop < outputx + debug_output_size && loop < countx;
|
||||
loop ++)
|
||||
{
|
||||
sprintf (buffer, "%s%02d:%s\n", buffer, loop, arrayx[loop]);
|
||||
}
|
||||
outputx = loop;
|
||||
*/
|
||||
|
||||
if (count == 0 || count > countx)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = countx - count;
|
||||
}
|
||||
|
||||
printk (KERN_ALERT "DUMPX BUFFER\n");
|
||||
for (loop = start; loop < countx; loop++)
|
||||
{
|
||||
printk (KERN_ALERT "%4d %s\n", loop, arrayx[loop]);
|
||||
}
|
||||
printk (KERN_ALERT "DUMPX bye bye\n");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <asm-i386/io.h>
|
||||
#include <xeno/sched.h> /* this has request_irq() proto for some reason */
|
||||
#include <xeno/keyhandler.h>
|
||||
|
||||
#define KEYBOARD_IRQ 1
|
||||
|
||||
@@ -22,74 +23,148 @@
|
||||
#define kbd_read_status() inb(KBD_STATUS_REG)
|
||||
|
||||
|
||||
static int keyboard_shift = 0;
|
||||
static int keyboard_control = 0;
|
||||
|
||||
static void
|
||||
dispatch_scancode (unsigned char scancode)
|
||||
/* the following is pretty gross...
|
||||
* stop reading if you don't want to throw up!
|
||||
*/
|
||||
|
||||
static unsigned char keymap_normal[] =
|
||||
{
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
/*
|
||||
* we could be a bit more clever here, but why?
|
||||
* just add a jump to your debug routine for the appropriate character.
|
||||
*/
|
||||
switch (scancode)
|
||||
{
|
||||
case 0x01 : /* esc */
|
||||
printk ("<esc>");
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
0 , 0 ,'1','2', '3','4','5','6', '7','8','9','0', '-','=','\b','\t',
|
||||
'q','w','e','r', 't','y','u','i', 'o','p','[',']','\r', 0 ,'a','s',
|
||||
'd','f','g','h', 'j','k','l',';', '\'','`', 0 ,'#', 'z','x','c','v',
|
||||
'b','n','m',',', '.','/', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 ,'\\', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
|
||||
};
|
||||
|
||||
static unsigned char keymap_shift[] =
|
||||
{
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
0 , 0 ,'!','"', '#','$','%','^', '&','*','(',')', '_','+','\b','\t',
|
||||
'Q','W','E','R', 'T','Y','U','I', 'O','P','{','}','\r', 0 ,'A','S',
|
||||
'D','F','G','H', 'J','K','L',':', '@', 0 , 0 ,'~', 'Z','X','C','V',
|
||||
'B','N','M','<', '>','?', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 ,'|', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
|
||||
};
|
||||
|
||||
|
||||
static unsigned char keymap_control[] =
|
||||
{ /* same as normal, except for a-z -> 1 to 26 */
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
0 , 0 ,'1','2', '3','4','5','6', '7','8','9','0', '-','=','\b','\t',
|
||||
17, 23, 5 , 18, 20, 25, 21, 9 , 15, 16,'[',']','\r', 0 , 1 , 19,
|
||||
4 , 6 , 7 , 8 , 10, 11, 12,';', '\'','`', 0 ,'#', 26, 24, 3 , 22,
|
||||
2 , 14, 13,',', '.','/', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 ,'\\', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
|
||||
};
|
||||
|
||||
|
||||
static unsigned char convert_scancode (unsigned char scancode)
|
||||
{
|
||||
unsigned char value = 0;
|
||||
|
||||
switch (scancode) {
|
||||
|
||||
case 0xba: /* caps lock UP */
|
||||
case 0x9d: /* ctrl (left) UP */
|
||||
keyboard_control = 0;
|
||||
break;
|
||||
case 0x9e : /* a */
|
||||
printk ("a");
|
||||
|
||||
case 0x3a: /* caps lock DOWN */
|
||||
case 0x1d: /* ctrl (left) DOWN */
|
||||
keyboard_control = 1;
|
||||
break;
|
||||
case 0x9f : /* s */
|
||||
printk ("s");
|
||||
|
||||
case 0xaa: /* shift (left) UP */
|
||||
case 0xb6: /* shift (right) UP */
|
||||
keyboard_shift = 0;
|
||||
break;
|
||||
case 0xae : /* c */
|
||||
printk ("c");
|
||||
|
||||
case 0x2a: /* shift (left) DOWN */
|
||||
case 0x36: /* shift (right) DOWN */
|
||||
keyboard_shift = 1;
|
||||
break;
|
||||
case 0xb0 : /* b */
|
||||
printk ("b");
|
||||
break;
|
||||
case 0xbb : /* f1 */
|
||||
printk ("<f1>");
|
||||
break;
|
||||
case 0xbc : /* f2 */
|
||||
printk ("<f2>");
|
||||
break;
|
||||
case 0xbd : /* f3 */
|
||||
printk ("<f3>");
|
||||
break;
|
||||
case 0xbe : /* f4 */
|
||||
printk ("<f4>");
|
||||
break;
|
||||
case 0xbf : /* f5 */
|
||||
/* xen_block_dump_state(); */
|
||||
break;
|
||||
default :
|
||||
/* printk ("%x ", scancode); */
|
||||
|
||||
default: /* normal keys */
|
||||
if (keyboard_control)
|
||||
value = keymap_control[scancode];
|
||||
else if (keyboard_shift)
|
||||
value = keymap_shift[scancode];
|
||||
else
|
||||
value = keymap_normal[scancode];
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
if (value) printk ("%c", value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* regs should be struct pt_regs */
|
||||
|
||||
static void keyboard_interrupt(int irq, void *dev_id, void *regs)
|
||||
static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned char status = kbd_read_status();
|
||||
unsigned int work = 10000;
|
||||
|
||||
|
||||
while ((--work > 0) && (status & KBD_STAT_OBF))
|
||||
{
|
||||
unsigned char scancode;
|
||||
|
||||
scancode = kbd_read_input();
|
||||
|
||||
if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))
|
||||
{
|
||||
if (status & KBD_STAT_MOUSE_OBF)
|
||||
/* mouse event, ignore */;
|
||||
else
|
||||
dispatch_scancode (scancode);
|
||||
else {
|
||||
unsigned char key;
|
||||
key_handler *handler;
|
||||
|
||||
if((key = convert_scancode (scancode)) &&
|
||||
(handler = get_key_handler(key)))
|
||||
(*handler)(key, dev_id, regs);
|
||||
|
||||
}
|
||||
}
|
||||
status = kbd_read_status();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <asm-i386/io.h>
|
||||
#include <xeno/sched.h> /* this has request_irq() proto for some reason */
|
||||
|
||||
#include <xeno/keyhandler.h>
|
||||
#include <xeno/reboot.h>
|
||||
|
||||
/* Register offsets */
|
||||
#define NS16550_RBR 0x00 /* receive buffer */
|
||||
@@ -43,51 +44,20 @@
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** We keep an array of 'handlers' for each key code between 0 and 255;
|
||||
** this is intended to allow very simple debugging routines (toggle
|
||||
** debug flag, dump registers, reboot, etc) to be hooked in in a slightly
|
||||
** nicer fashion than just editing this file :-)
|
||||
*/
|
||||
|
||||
#define KEY_MAX 256
|
||||
typedef void key_handler(u_char key);
|
||||
|
||||
static key_handler *key_table[KEY_MAX];
|
||||
|
||||
void add_key_handler(u_char key, key_handler *handler)
|
||||
{
|
||||
if(key_table[key] != NULL)
|
||||
printk("Warning: overwriting handler for key 0x%x\n", key);
|
||||
|
||||
key_table[key] = handler;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int serial_echo = 0; /* default is not to echo; change with 'e' */
|
||||
|
||||
void toggle_echo(u_char key)
|
||||
void toggle_echo(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
serial_echo = !serial_echo;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void halt_machine(u_char key)
|
||||
{
|
||||
/* This is 'debug me please' => just dump info and halt machine */
|
||||
printk("serial_rx_int: got EOT => halting machine.\n");
|
||||
printk("<not actually halting for now>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
u_char c;
|
||||
key_handler *handler;
|
||||
|
||||
/* XXX SMH: should probably check this is an RX interrupt :-) */
|
||||
|
||||
@@ -95,8 +65,8 @@ static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
c = inb(SERIAL_BASE + NS16550_RBR );
|
||||
|
||||
/* if there's a handler, call it: we trust it won't screw us too badly */
|
||||
if(key_table[c])
|
||||
(*key_table[c])(c);
|
||||
if((handler = get_key_handler(c)) != NULL)
|
||||
(*handler)(c, dev_id, regs);
|
||||
|
||||
if(serial_echo)
|
||||
printk("%c", c);
|
||||
@@ -104,19 +74,12 @@ static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void initialize_serial()
|
||||
{
|
||||
int i, fifo, rc;
|
||||
|
||||
/* first initialize key handler table */
|
||||
for(i = 0; i < KEY_MAX; i++)
|
||||
key_table[i] = (key_handler *)NULL;
|
||||
|
||||
/* setup own handlers */
|
||||
add_key_handler(0x01, toggle_echo); /* <esc> to toggle echo */
|
||||
add_key_handler(0x04, halt_machine); /* CTRL-D to 'halt' */
|
||||
|
||||
int fifo, rc;
|
||||
|
||||
/* setup key handler */
|
||||
add_key_handler('~', toggle_echo, "toggle serial echo");
|
||||
|
||||
/* Should detect this, but must be a ns16550a at least, surely? */
|
||||
fifo = 1;
|
||||
|
||||
@@ -5,42 +5,37 @@
|
||||
#include <hypervisor-ifs/block.h>
|
||||
|
||||
|
||||
void
|
||||
ide_probe_devices (xen_disk_info_t* xdi)
|
||||
void ide_probe_devices (xen_disk_info_t* xdi)
|
||||
{
|
||||
int loop;
|
||||
int loop;
|
||||
|
||||
for (loop = 0; loop < MAX_HWIFS; ++loop) {
|
||||
|
||||
for (loop = 0; loop < MAX_HWIFS; ++loop)
|
||||
{
|
||||
ide_hwif_t *hwif = &ide_hwifs[loop];
|
||||
if (hwif->present)
|
||||
{
|
||||
struct gendisk *gd = hwif->gd;
|
||||
unsigned int unit;
|
||||
ide_hwif_t *hwif = &ide_hwifs[loop];
|
||||
if (hwif->present) {
|
||||
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit)
|
||||
{
|
||||
unsigned long capacity;
|
||||
struct gendisk *gd = hwif->gd;
|
||||
unsigned int unit;
|
||||
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit) {
|
||||
unsigned long capacity;
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
|
||||
if (drive->present)
|
||||
{
|
||||
capacity = current_capacity (drive);
|
||||
if (drive->present) {
|
||||
capacity = current_capacity (drive);
|
||||
xdi->disks[xdi->count].type = XEN_DISK_IDE;
|
||||
xdi->disks[xdi->count].capacity = capacity;
|
||||
xdi->count++;
|
||||
|
||||
xdi->disks[xdi->count].type = XEN_DISK_IDE;
|
||||
xdi->disks[xdi->count].capacity = capacity;
|
||||
xdi->count++;
|
||||
|
||||
printk (KERN_ALERT "IDE-XENO %d\n", xdi->count);
|
||||
printk (KERN_ALERT " capacity 0x%x\n", capacity);
|
||||
printk (KERN_ALERT " head 0x%x\n", drive->bios_head);
|
||||
printk (KERN_ALERT " sector 0x%x\n", drive->bios_sect);
|
||||
printk (KERN_ALERT " cylinder 0x%x\n", drive->bios_cyl);
|
||||
printk (KERN_ALERT "IDE-XENO %d\n", xdi->count);
|
||||
printk (KERN_ALERT " capacity 0x%x\n", capacity);
|
||||
printk (KERN_ALERT " head 0x%x\n", drive->bios_head);
|
||||
printk (KERN_ALERT " sector 0x%x\n", drive->bios_sect);
|
||||
printk (KERN_ALERT " cylinder 0x%x\n", drive->bios_cyl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -51,13 +51,13 @@ typedef struct blk_ring_entry
|
||||
|
||||
typedef struct blk_ring_st
|
||||
{
|
||||
blk_ring_entry_t *tx_ring;
|
||||
unsigned int tx_prod, tx_cons;
|
||||
unsigned int tx_ring_size;
|
||||
blk_ring_entry_t *btx_ring;
|
||||
unsigned int btx_prod, btx_cons;
|
||||
unsigned int btx_ring_size;
|
||||
|
||||
blk_ring_entry_t *rx_ring;
|
||||
unsigned int rx_prod, rx_cons;
|
||||
unsigned int rx_ring_size;
|
||||
blk_ring_entry_t *brx_ring;
|
||||
unsigned int brx_prod, brx_cons;
|
||||
unsigned int brx_ring_size;
|
||||
} blk_ring_t;
|
||||
|
||||
#define MAX_XEN_DISK_COUNT 100
|
||||
|
||||
@@ -107,10 +107,9 @@ typedef struct
|
||||
#define EVENT_BLK_RX 0x02 /* empty buffers for receive. */
|
||||
#define EVENT_TIMER 0x04 /* a timeout has been updated. */
|
||||
#define EVENT_DIE 0x08 /* OS is about to be killed. Clean up please! */
|
||||
#define EVENT_NET_TX 0x10 /* packets for transmission. */
|
||||
#define EVENT_NET_RX 0x20 /* empty buffers for receive. */
|
||||
#define EVENT_NET2_TX 0x40 /* packets for transmission. */
|
||||
#define EVENT_NET2_RX 0x80 /* empty buffers for receive. */
|
||||
#define EVENT_DEBUG 0x10 /* request guest to dump debug info (gross!) */
|
||||
#define EVENT_NET_TX 0x20 /* packets for transmission. */
|
||||
#define EVENT_NET_RX 0x40 /* empty buffers for receive. */
|
||||
|
||||
/* should these macros and the ones below test for range violation? */
|
||||
#define EVENT_NET_TX_FOR_VIF(x) (EVENT_NET_TX << (2 * x))
|
||||
@@ -124,12 +123,12 @@ typedef struct
|
||||
#define _EVENT_DIE 3
|
||||
#define _EVENT_NET_TX 4
|
||||
#define _EVENT_NET_RX 5
|
||||
#define _EVENT_NET2_TX 6
|
||||
#define _EVENT_NET2_RX 7
|
||||
#define _EVENT_DEBUG 6
|
||||
|
||||
#define _EVENT_NET_TX_FOR_VIF(x) (_EVENT_NET_TX + (2 * x))
|
||||
#define _EVENT_NET_RX_FOR_VIF(x) (_EVENT_NET_RX + (2 * x))
|
||||
|
||||
|
||||
/*
|
||||
* NB. We expect that this struct is smaller than a page.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
** We keep an array of 'handlers' for each key code between 0 and 255;
|
||||
** this is intended to allow very simple debugging routines (toggle
|
||||
** debug flag, dump registers, reboot, etc) to be hooked in in a slightly
|
||||
** nicer fashion than just editing the serial/keyboard drivers.
|
||||
*/
|
||||
#include <xeno/sched.h>
|
||||
|
||||
typedef void key_handler(unsigned char key, void *dev_id,
|
||||
struct pt_regs *regs);
|
||||
|
||||
extern void add_key_handler(unsigned char key,
|
||||
key_handler *handler, char *desc);
|
||||
|
||||
extern key_handler *get_key_handler(unsigned char key);
|
||||
|
||||
@@ -1,392 +0,0 @@
|
||||
/******************************************************************************
|
||||
* block.c
|
||||
*
|
||||
* Virtual block driver for XenoLinux.
|
||||
*
|
||||
* adapted from network.c
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <asm/hypervisor-ifs/block.h>
|
||||
|
||||
#ifdef UNDEFINED
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/sock.h>
|
||||
|
||||
#define BLK_TX_IRQ _EVENT_BLK_TX
|
||||
#define BLK_RX_IRQ _EVENT_BLK_RX
|
||||
|
||||
#define TX_MAX_ENTRIES (TX_RING_SIZE - 2)
|
||||
#define RX_MAX_ENTRIES (RX_RING_SIZE - 2)
|
||||
|
||||
#define TX_RING_INC(_i) (((_i)+1) & (TX_RING_SIZE-1))
|
||||
#define RX_RING_INC(_i) (((_i)+1) & (RX_RING_SIZE-1))
|
||||
#define TX_RING_ADD(_i,_j) (((_i)+(_j)) & (TX_RING_SIZE-1))
|
||||
#define RX_RING_ADD(_i,_j) (((_i)+(_j)) & (RX_RING_SIZE-1))
|
||||
|
||||
#define RX_BUF_SIZE 1600 /* Ethernet MTU + plenty of slack! */
|
||||
|
||||
|
||||
|
||||
int network_probe(struct net_device *dev);
|
||||
static int network_open(struct net_device *dev);
|
||||
static int network_start_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
static int network_close(struct net_device *dev);
|
||||
static struct net_device_stats *network_get_stats(struct net_device *dev);
|
||||
static void network_rx_int(int irq, void *dev_id, struct pt_regs *ptregs);
|
||||
static void network_tx_int(int irq, void *dev_id, struct pt_regs *ptregs);
|
||||
static void network_tx_buf_gc(struct net_device *dev);
|
||||
static void network_alloc_rx_buffers(struct net_device *dev);
|
||||
static void network_free_rx_buffers(struct net_device *dev);
|
||||
|
||||
static struct net_device dev_net_xeno;
|
||||
|
||||
/*
|
||||
* RX RING: RX_IDX <= rx_cons <= rx_prod
|
||||
* TX RING: TX_IDX <= tx_cons <= tx_prod
|
||||
* (*_IDX allocated privately here, *_cons & *_prod shared with hypervisor)
|
||||
*/
|
||||
struct net_private
|
||||
{
|
||||
struct net_device_stats stats;
|
||||
struct sk_buff **tx_skb_ring;
|
||||
struct sk_buff **rx_skb_ring;
|
||||
atomic_t tx_entries;
|
||||
unsigned int rx_idx, tx_idx, tx_full;
|
||||
net_ring_t *net_ring;
|
||||
spinlock_t tx_lock;
|
||||
};
|
||||
|
||||
|
||||
int __init network_probe(struct net_device *dev)
|
||||
{
|
||||
SET_MODULE_OWNER(dev);
|
||||
|
||||
memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6);
|
||||
|
||||
dev->open = network_open;
|
||||
dev->hard_start_xmit = network_start_xmit;
|
||||
dev->stop = network_close;
|
||||
dev->get_stats = network_get_stats;
|
||||
|
||||
ether_setup(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int network_open(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np;
|
||||
int error;
|
||||
|
||||
np = kmalloc(sizeof(struct net_private), GFP_KERNEL);
|
||||
if ( np == NULL )
|
||||
{
|
||||
printk(KERN_WARNING "%s: No memory for private data\n", dev->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(np, 0, sizeof(struct net_private));
|
||||
dev->priv = np;
|
||||
|
||||
spin_lock_init(&np->tx_lock);
|
||||
|
||||
atomic_set(&np->tx_entries, 0);
|
||||
|
||||
np->net_ring = start_info.net_rings;
|
||||
np->net_ring->tx_prod = np->net_ring->tx_cons = np->net_ring->tx_event = 0;
|
||||
np->net_ring->rx_prod = np->net_ring->rx_cons = np->net_ring->rx_event = 0;
|
||||
np->net_ring->tx_ring = NULL;
|
||||
np->net_ring->rx_ring = NULL;
|
||||
|
||||
np->tx_skb_ring = kmalloc(TX_RING_SIZE * sizeof(struct sk_buff *),
|
||||
GFP_KERNEL);
|
||||
np->rx_skb_ring = kmalloc(RX_RING_SIZE * sizeof(struct sk_buff *),
|
||||
GFP_KERNEL);
|
||||
np->net_ring->tx_ring = kmalloc(TX_RING_SIZE * sizeof(tx_entry_t),
|
||||
GFP_KERNEL);
|
||||
np->net_ring->rx_ring = kmalloc(RX_RING_SIZE * sizeof(rx_entry_t),
|
||||
GFP_KERNEL);
|
||||
if ( (np->tx_skb_ring == NULL) || (np->rx_skb_ring == NULL) ||
|
||||
(np->net_ring->tx_ring == NULL) || (np->net_ring->rx_ring == NULL) )
|
||||
{
|
||||
printk(KERN_WARNING "%s; Could not allocate ring memory\n", dev->name);
|
||||
error = -ENOBUFS;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
network_alloc_rx_buffers(dev);
|
||||
|
||||
error = request_irq(NET_RX_IRQ, network_rx_int, 0, "net-rx", dev);
|
||||
if ( error )
|
||||
{
|
||||
printk(KERN_WARNING "%s: Could not allocate receive interrupt\n",
|
||||
dev->name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = request_irq(NET_TX_IRQ, network_tx_int, 0, "net-tx", dev);
|
||||
if ( error )
|
||||
{
|
||||
printk(KERN_WARNING "%s: Could not allocate transmit interrupt\n",
|
||||
dev->name);
|
||||
free_irq(NET_RX_IRQ, dev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printk("XenoLinux Virtual Network Driver installed as %s\n", dev->name);
|
||||
|
||||
netif_start_queue(dev);
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if ( np->net_ring->rx_ring ) kfree(np->net_ring->rx_ring);
|
||||
if ( np->net_ring->tx_ring ) kfree(np->net_ring->tx_ring);
|
||||
if ( np->rx_skb_ring ) kfree(np->rx_skb_ring);
|
||||
if ( np->tx_skb_ring ) kfree(np->tx_skb_ring);
|
||||
kfree(np);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static void network_tx_buf_gc(struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&np->tx_lock, flags);
|
||||
|
||||
for ( i = np->tx_idx; i != np->net_ring->tx_cons; i = TX_RING_INC(i) )
|
||||
{
|
||||
skb = np->tx_skb_ring[i];
|
||||
dev_kfree_skb_any(skb);
|
||||
atomic_dec(&np->tx_entries);
|
||||
}
|
||||
|
||||
np->tx_idx = i;
|
||||
|
||||
if ( np->tx_full && (atomic_read(&np->tx_entries) < TX_MAX_ENTRIES) )
|
||||
{
|
||||
np->tx_full = 0;
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&np->tx_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
unsigned int end = RX_RING_ADD(np->rx_idx, RX_MAX_ENTRIES);
|
||||
|
||||
for ( i = np->net_ring->rx_prod; i != end; i = RX_RING_INC(i) )
|
||||
{
|
||||
skb = dev_alloc_skb(RX_BUF_SIZE);
|
||||
if ( skb == NULL ) break;
|
||||
skb->dev = dev;
|
||||
skb_reserve(skb, 2); /* word align the IP header */
|
||||
np->rx_skb_ring[i] = skb;
|
||||
np->net_ring->rx_ring[i].addr = (unsigned long)skb->data;
|
||||
np->net_ring->rx_ring[i].size = RX_BUF_SIZE - 16; /* arbitrary */
|
||||
}
|
||||
|
||||
np->net_ring->rx_prod = i;
|
||||
|
||||
np->net_ring->rx_event = RX_RING_INC(np->rx_idx);
|
||||
|
||||
HYPERVISOR_net_update();
|
||||
}
|
||||
|
||||
|
||||
static void network_free_rx_buffers(struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
for ( i = np->rx_idx; i != np->net_ring->rx_prod; i = RX_RING_INC(i) )
|
||||
{
|
||||
skb = np->rx_skb_ring[i];
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
struct net_private *np = (struct net_private *)dev->priv;
|
||||
|
||||
if ( np->tx_full )
|
||||
{
|
||||
printk(KERN_WARNING "%s: full queue wasn't stopped!\n", dev->name);
|
||||
netif_stop_queue(dev);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
i = np->net_ring->tx_prod;
|
||||
np->tx_skb_ring[i] = skb;
|
||||
np->net_ring->tx_ring[i].addr = (unsigned long)skb->data;
|
||||
np->net_ring->tx_ring[i].size = skb->len;
|
||||
np->net_ring->tx_prod = TX_RING_INC(i);
|
||||
atomic_inc(&np->tx_entries);
|
||||
|
||||
np->stats.tx_bytes += skb->len;
|
||||
np->stats.tx_packets++;
|
||||
|
||||
spin_lock_irq(&np->tx_lock);
|
||||
if ( atomic_read(&np->tx_entries) >= TX_MAX_ENTRIES )
|
||||
{
|
||||
np->tx_full = 1;
|
||||
netif_stop_queue(dev);
|
||||
np->net_ring->tx_event = TX_RING_ADD(np->tx_idx,
|
||||
atomic_read(&np->tx_entries) >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Avoid unnecessary tx interrupts. */
|
||||
np->net_ring->tx_event = TX_RING_INC(np->net_ring->tx_prod);
|
||||
}
|
||||
spin_unlock_irq(&np->tx_lock);
|
||||
|
||||
/* Must do this after setting tx_event: race with updates of tx_cons. */
|
||||
network_tx_buf_gc(dev);
|
||||
|
||||
HYPERVISOR_net_update();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void network_rx_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
{
|
||||
unsigned int i;
|
||||
struct net_device *dev = (struct net_device *)dev_id;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
again:
|
||||
for ( i = np->rx_idx; i != np->net_ring->rx_cons; i = RX_RING_INC(i) )
|
||||
{
|
||||
skb = np->rx_skb_ring[i];
|
||||
skb_put(skb, np->net_ring->rx_ring[i].size);
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
np->stats.rx_packets++;
|
||||
np->stats.rx_bytes += np->net_ring->rx_ring[i].size;
|
||||
netif_rx(skb);
|
||||
dev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
np->rx_idx = i;
|
||||
|
||||
network_alloc_rx_buffers(dev);
|
||||
|
||||
/* Deal with hypervisor racing our resetting of rx_event. */
|
||||
smp_mb();
|
||||
if ( np->net_ring->rx_cons != i ) goto again;
|
||||
}
|
||||
|
||||
|
||||
static void network_tx_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)dev_id;
|
||||
network_tx_buf_gc(dev);
|
||||
}
|
||||
|
||||
|
||||
static int network_close(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
free_irq(NET_RX_IRQ, dev);
|
||||
free_irq(NET_TX_IRQ, dev);
|
||||
network_free_rx_buffers(dev);
|
||||
kfree(np->net_ring->rx_ring);
|
||||
kfree(np->net_ring->tx_ring);
|
||||
kfree(np->rx_skb_ring);
|
||||
kfree(np->tx_skb_ring);
|
||||
kfree(np);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct net_device_stats *network_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = (struct net_private *)dev->priv;
|
||||
return &np->stats;
|
||||
}
|
||||
|
||||
|
||||
static int __init init_module(void)
|
||||
{
|
||||
memset(&dev_net_xeno, 0, sizeof(dev_net_xeno));
|
||||
strcpy(dev_net_xeno.name, "eth%d");
|
||||
dev_net_xeno.init = network_probe;
|
||||
return (register_netdev(&dev_net_xeno) != 0) ? -EIO : 0;
|
||||
}
|
||||
|
||||
|
||||
static void __exit cleanup_module(void)
|
||||
{
|
||||
unregister_netdev(&dev_net_xeno);
|
||||
}
|
||||
|
||||
#endif /* UNDEFINED */
|
||||
|
||||
|
||||
static void block_initialize(void)
|
||||
{
|
||||
blk_ring_t *blk_ring = start_info.blk_ring;
|
||||
|
||||
if ( blk_ring == NULL ) return;
|
||||
|
||||
blk_ring->tx_prod = blk_ring->tx_cons = blk_ring->tx_event = 0;
|
||||
blk_ring->rx_prod = blk_ring->rx_cons = blk_ring->rx_event = 0;
|
||||
blk_ring->tx_ring = NULL;
|
||||
blk_ring->rx_ring = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* block_setup initialized the xeno block device driver
|
||||
*/
|
||||
|
||||
static int __init init_module(void)
|
||||
{
|
||||
block_initialize();
|
||||
printk("XenoLinux Virtual Block Device Driver installed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cleanup_module(void)
|
||||
{
|
||||
printk("XenoLinux Virtual Block Device Driver uninstalled\n");
|
||||
}
|
||||
|
||||
module_init(init_module);
|
||||
module_exit(cleanup_module);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -533,6 +533,8 @@ static inline void add_request(request_queue_t * q, struct request * req,
|
||||
|
||||
if (!q->plugged && q->head_active && insert_here == &q->queue_head) {
|
||||
spin_unlock_irq(&io_request_lock);
|
||||
printk("list_empty(&q->queue_head) is %d\n",
|
||||
list_empty(&q->queue_head));
|
||||
BUG();
|
||||
}
|
||||
|
||||
@@ -771,6 +773,7 @@ get_rq:
|
||||
req->bhtail = bh;
|
||||
req->rq_dev = bh->b_rdev;
|
||||
blk_started_io(count);
|
||||
|
||||
add_request(q, req, insert_here);
|
||||
out:
|
||||
if (freereq)
|
||||
|
||||
@@ -326,7 +326,7 @@ static void floppy_off(unsigned int nr);
|
||||
|
||||
#elif (MAJOR_NR == XLBLK_MAJOR)
|
||||
|
||||
#define DEVICE_NAME "blk"
|
||||
#define DEVICE_NAME "xeno disk"
|
||||
#define DEVICE_REQUEST do_xlblk_request
|
||||
/* #define DEVICE_INTR */
|
||||
#define DEVICE_NR(device) (MINOR(device))
|
||||
|
||||
@@ -149,7 +149,7 @@ static struct dev_name_struct {
|
||||
const int num;
|
||||
} root_dev_names[] __initdata = {
|
||||
{ "nfs", 0x00ff },
|
||||
{ "blk", 0x7b00 },
|
||||
{ "xhda", 0x7b00 },
|
||||
{ "hda", 0x0300 },
|
||||
{ "hdb", 0x0340 },
|
||||
{ "loop", 0x0700 },
|
||||
|
||||