# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1189607578 -3600
# Node ID 9dd580b8b056860fe7634bb964e2bcf201e87bd6
# Parent 45dbef0ab7a6cb108d6db36392d9ee3661efbb59
x86: allow Dom0 to drive PC speaker
as long as Xen doesn't itself make use of PIT channel 2.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/i8254.c | 8 +++++---
xen/arch/x86/time.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
xen/include/asm-x86/time.h | 13 ++++++++-----
3 files changed, 57 insertions(+), 9 deletions(-)
diff -r 45dbef0ab7a6 -r 9dd580b8b056 xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c Wed Sep 12 09:58:16 2007 +0100
+++ b/xen/arch/x86/hvm/i8254.c Wed Sep 12 15:32:58 2007 +0100
@@ -598,11 +598,13 @@ int pv_pit_handler(int port, int data, i
.size = 1,
.type = IOREQ_TYPE_PIO,
.addr = port,
- .dir = write ? 0 : 1,
- .data = write ? data : 0,
+ .dir = write ? IOREQ_WRITE : IOREQ_READ,
+ .data = data
};
- if ( port == 0x61 )
+ if ( (current->domain->domain_id == 0) && dom0_pit_access(&ioreq) )
+ /* nothing to do */;
+ else if ( port == 0x61 )
handle_speaker_io(&ioreq);
else
handle_pit_io(&ioreq);
diff -r 45dbef0ab7a6 -r 9dd580b8b056 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c Wed Sep 12 09:58:16 2007 +0100
+++ b/xen/arch/x86/time.c Wed Sep 12 15:32:58 2007 +0100
@@ -177,7 +177,6 @@ static u64 init_pit_and_calibrate_tsc(vo
unsigned long count;
/* Set PIT channel 0 to HZ Hz. */
-#define CLOCK_TICK_RATE 1193180 /* crystal freq (Hz) */
#define LATCH (((CLOCK_TICK_RATE)+(HZ/2))/HZ)
outb_p(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff, PIT_CH0); /* LSB */
@@ -972,6 +971,50 @@ int time_resume(void)
return 0;
}
+int dom0_pit_access(struct ioreq *ioreq)
+{
+ /* Is Xen using Channel 2? Then disallow direct dom0 access. */
+ if ( plt_src.read_counter == read_pit_count )
+ return 0;
+
+ switch ( ioreq->addr )
+ {
+ case PIT_CH2:
+ if ( ioreq->dir == IOREQ_READ )
+ ioreq->data = inb(PIT_CH2);
+ else
+ outb(ioreq->data, PIT_CH2);
+ return 1;
+
+ case PIT_MODE:
+ if ( ioreq->dir == IOREQ_READ )
+ return 0; /* urk! */
+ switch ( ioreq->data & 0xc0 )
+ {
+ case 0xc0: /* Read Back */
+ if ( ioreq->data & 0x08 ) /* Select Channel 2? */
+ outb(ioreq->data & 0xf8, PIT_MODE);
+ if ( !(ioreq->data & 0x06) ) /* Select Channel 0/1? */
+ return 1; /* no - we're done */
+ /* Filter Channel 2 and reserved bit 0. */
+ ioreq->data &= ~0x09;
+ return 0; /* emulate ch0/1 readback */
+ case 0x80: /* Select Counter 2 */
+ outb(ioreq->data, PIT_MODE);
+ return 1;
+ }
+
+ case 0x61:
+ if ( ioreq->dir == IOREQ_READ )
+ ioreq->data = inb(0x61);
+ else
+ outb((inb(0x61) & ~3) | (ioreq->data & 3), 0x61);
+ return 1;
+ }
+
+ return 0;
+}
+
/*
* Local variables:
* mode: C
diff -r 45dbef0ab7a6 -r 9dd580b8b056 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h Wed Sep 12 09:58:16 2007 +0100
+++ b/xen/include/asm-x86/time.h Wed Sep 12 15:32:58 2007 +0100
@@ -4,8 +4,8 @@
#include <asm/msr.h>
-extern void calibrate_tsc_bp(void);
-extern void calibrate_tsc_ap(void);
+void calibrate_tsc_bp(void);
+void calibrate_tsc_ap(void);
typedef u64 cycles_t;
@@ -21,9 +21,12 @@ mktime (unsigned int year, unsigned int
unsigned int day, unsigned int hour,
unsigned int min, unsigned int sec);
-extern int time_suspend(void);
-extern int time_resume(void);
+int time_suspend(void);
+int time_resume(void);
-extern void init_percpu_time(void);
+void init_percpu_time(void);
+
+struct ioreq;
+int dom0_pit_access(struct ioreq *ioreq);
#endif /* __X86_TIME_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|