diff options
29 files changed, 1414 insertions, 93 deletions
@@ -484,6 +484,7 @@ 3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/hypervisor-ifs/hypervisor-if.h 3ead095dE_VF-QA88rl_5cWYRWtRVQ xen/include/hypervisor-ifs/kbd.h 3ddb79c2oRPrzClk3zbTkRHlpumzKA xen/include/hypervisor-ifs/network.h +4051db79512nOCGweabrFWO2M2h5ng xen/include/hypervisor-ifs/physdev.h 404f3d2eR2Owk-ZcGOx9ULGHg3nrww xen/include/hypervisor-ifs/trace.h 3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/vbd.h 3ddb79c4qbCoOFHrv9sCGshbWzBVlQ xen/include/scsi/scsi.h @@ -609,6 +610,12 @@ 3e5a4e65MEvZhlr070sK5JsfAQlv7Q xenolinux-2.4.25-sparse/arch/xeno/kernel/ioport.c 3e5a4e653U6cELGv528IxOLHvCq8iA xenolinux-2.4.25-sparse/arch/xeno/kernel/irq.c 3e5a4e65muT6SU3ck47IP87Q7Ti5hA xenolinux-2.4.25-sparse/arch/xeno/kernel/ldt.c +4051db84bZeRX7a_Kh6VyyDuT5FOIg xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-dma.c +4051db89iiHs38tWGkoW_RukNyaBHw xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.c +4051db8dJYX86ZCLA-WfTW2dAyrehw xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.h +4051db91BenvDZEMZxQCGkQyJYoG5w xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-irq.c +4051db95N9N99FjsRwi49YKUNHWI8A xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-pc.c +4051db99fbdTHgCpjywPCp7vjLCe7Q xenolinux-2.4.25-sparse/arch/xeno/kernel/physirq.c 3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ xenolinux-2.4.25-sparse/arch/xeno/kernel/process.c 3e5a4e66tR-qJMLj3MppcKqmvuI2XQ xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c 3e5a4e66fWSTagLGU2P8BGFGRjhDiw xenolinux-2.4.25-sparse/arch/xeno/kernel/signal.c diff --git a/tools/xc/lib/xc_physdev.c b/tools/xc/lib/xc_physdev.c index 6fa2851734..fb35843586 100644 --- a/tools/xc/lib/xc_physdev.c +++ b/tools/xc/lib/xc_physdev.c @@ -7,6 +7,8 @@ * Copyright (c) 2004, K A Fraser (University of Cambridge) */ +#include "xc_private.h" + int xc_physdev_pci_access_modify(int xc_handle, u64 domid, int bus, diff --git a/xen/common/domain.c b/xen/common/domain.c index 1c363390c7..53cea06285 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -592,6 +592,7 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params, l1_pgentry_t *l1tab = NULL, *l1start = NULL; struct pfn_info *page = NULL; + extern void physdev_init_dom0(struct task_struct *); extern void ide_probe_devices(xen_disk_info_t *); extern void scsi_probe_devices(xen_disk_info_t *); extern void cciss_probe_devices(xen_disk_info_t *); diff --git a/xen/common/physdev.c b/xen/common/physdev.c index 3055ad2e30..6daeb169e3 100644 --- a/xen/common/physdev.c +++ b/xen/common/physdev.c @@ -35,15 +35,15 @@ #include <xeno/pci.h> #include <xeno/irq.h> #include <xeno/event.h> - #include <asm/pci.h> - - #include <hypervisor-ifs/hypervisor-if.h> -#include <hypervisor-ifs/phys_dev.h> +#include <hypervisor-ifs/physdev.h> +#if 1 #define DBG(_x...) -//#define DBG(_x...) printk(_x) +#else +#define DBG(_x...) printk(_x) +#endif #define ACC_READ 1 #define ACC_WRITE 2 @@ -59,7 +59,6 @@ #define ST_ROM_ADDRESS 6 /* bit 6: is for rom address access */ #define ST_IRQ_DELIVERED 7 /* bit 7: waiting for end irq call */ - typedef struct _phys_dev_st { int flags; /* flags for access etc */ @@ -84,7 +83,7 @@ static phys_dev_t *find_pdev(struct task_struct *p, struct pci_dev *dev) phys_dev_t *t, *res = NULL; struct list_head *tmp; - list_for_each(tmp, &p->dev_list) + list_for_each(tmp, &p->pcidev_list) { t = list_entry(tmp, phys_dev_t, node); if ( dev == t->dev ) @@ -120,7 +119,7 @@ static void add_dev_to_task(struct task_struct *p, pdev->dev = dev; pdev->flags = acc; pdev->state = 0; - list_add(&pdev->node, &p->dev_list); + list_add(&pdev->node, &p->pcidev_list); if ( acc == ACC_WRITE ) pdev->owner = p; @@ -154,7 +153,7 @@ int physdev_pci_access_modify( DPRINTK("physdev_pci_access_modify: %02x:%02x:%02x\n", bus, dev, func); - if ( (p = find_domain_by_id(dom) == NULL ) + if ( (p = find_domain_by_id(dom)) == NULL ) return -ESRCH; /* Make the domain privileged. */ @@ -181,7 +180,7 @@ int physdev_pci_access_modify( DPRINTK(" add R0 %02x:%02x:%02x\n", 0, 0, 0); /* Grant read access to all devices on the path to the root. */ - while ( tdev = pdev->bus->self; tdev != NULL; tdev = tdev->bus->self ) + for ( tdev = pdev->bus->self; tdev != NULL; tdev = tdev->bus->self ) { add_dev_to_task(p, tdev, ACC_READ); DPRINTK(" add RO %02x:%02x:%02x\n", tdev->bus->number, @@ -559,13 +558,13 @@ static void phys_dev_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) //printk("owner %p\n", p); - if ( test_bit(irq, &p->shared_info->virt_phys_irq) ) + if ( test_bit(irq, &p->shared_info->physirq_pend) ) { printk("irq %d already delivered to guest\n", irq); return; } /* notify guest */ - set_bit(irq, &p->shared_info->virt_phys_irq); + set_bit(irq, &p->shared_info->physirq_pend); set_bit(ST_IRQ_DELIVERED, &pdev->state); cpu_mask |= mark_guest_event(p, _EVENT_TIMER); guest_event_notify(cpu_mask); @@ -587,7 +586,7 @@ static void end_virt_irq (unsigned int i) static long pci_request_irq(int irq) { int err; - phys_dev_t *pdev, *t; + phys_dev_t *pdev = NULL, *t; hw_irq_controller *new, *orig; struct list_head *tmp; @@ -595,7 +594,7 @@ static long pci_request_irq(int irq) /* find pdev */ - list_for_each(tmp, ¤t->dev_list) + list_for_each(tmp, ¤t->pcidev_list) { t = list_entry(tmp, phys_dev_t, node); if ( t->dev->irq == irq ) @@ -605,7 +604,7 @@ static long pci_request_irq(int irq) } } - if ( !pdev ) + if ( pdev == NULL ) { printk("no device matching IRQ %d\n", irq); return -EINVAL; @@ -711,7 +710,7 @@ static long pci_finished_irq(int irq) return -EINVAL; } - if ( test_bit(irq, ¤t->shared_info->virt_phys_irq) ) + if ( test_bit(irq, ¤t->shared_info->physirq_pend) ) { printk("finished_irq called for un-acknowleged irq %d\n", irq); return -EINVAL; @@ -728,54 +727,53 @@ static long pci_finished_irq(int irq) /* * demux hypervisor call. */ -long do_phys_dev_op(phys_dev_op_t *uop) +long do_physdev_op(physdev_op_t *uop) { - phys_dev_op_t op; + physdev_op_t op; long ret; - if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) ) return -EFAULT; switch ( op.cmd ) { - case DEVOP_CFGREG_READ: + case PHYSDEVOP_CFGREG_READ: ret = pci_cfgreg_read (op.u.cfg_read.seg, op.u.cfg_read.bus, op.u.cfg_read.dev, op.u.cfg_read.func, op.u.cfg_read.reg, op.u.cfg_read.len, &op.u.cfg_read.value); break; - case DEVOP_CFGREG_WRITE: + case PHYSDEVOP_CFGREG_WRITE: ret = pci_cfgreg_write (op.u.cfg_write.seg, op.u.cfg_write.bus, op.u.cfg_write.dev, op.u.cfg_write.func, op.u.cfg_write.reg, op.u.cfg_write.len, op.u.cfg_write.value); break; - case DEVOP_FIND_IRQ: + case PHYSDEVOP_FIND_IRQ: ret = pci_find_irq (op.u.find_irq.seg, op.u.find_irq.bus, op.u.find_irq.dev, op.u.find_irq.func, &op.u.find_irq.irq); break; - case DEVOP_REQUEST_IRQ: + case PHYSDEVOP_REQUEST_IRQ: ret = pci_request_irq (op.u.request_irq.irq); break; - case DEVOP_FREE_IRQ: + case PHYSDEVOP_FREE_IRQ: ret = pci_free_irq (op.u.free_irq.irq); break; - case DEVOP_ENABLE_IRQ: + case PHYSDEVOP_ENABLE_IRQ: ret = pci_enable_irq (op.u.enable_irq.irq); break; - case DEVOP_DISABLE_IRQ: + case PHYSDEVOP_DISABLE_IRQ: ret = pci_disable_irq (op.u.disable_irq.irq); break; - case DEVOP_FINISHED_IRQ: + case PHYSDEVOP_FINISHED_IRQ: ret = pci_finished_irq (op.u.finished_irq.irq); break; @@ -798,9 +796,7 @@ void physdev_init_dom0(struct task_struct *p) struct pci_dev *dev; phys_dev_t *pdev; - printk("Give Dom0 read access to all PCI devices\n"); - - INIT_LIST_HEAD(&p->dev_list); + printk("Give DOM0 read access to all PCI devices\n"); pci_for_each_dev(dev) { @@ -810,6 +806,6 @@ void physdev_init_dom0(struct task_struct *p) pdev->flags = ACC_READ; pdev->state = 0; pdev->owner = p; - list_add(&pdev->node, &p->dev_list); + list_add(&pdev->node, &p->pcidev_list); } } diff --git a/xen/drivers/pci/pci.c b/xen/drivers/pci/pci.c index a478610564..41834c2b8c 100644 --- a/xen/drivers/pci/pci.c +++ b/xen/drivers/pci/pci.c @@ -13,21 +13,14 @@ #include <xeno/sched.h> #include <xeno/module.h> #include <xeno/types.h> -/*#include <xeno/kernel.h>*/ #include <xeno/pci.h> -/*#include <xeno/string.h>*/ #include <xeno/init.h> #include <xeno/slab.h> #include <xeno/ioport.h> #include <xeno/spinlock.h> -/*#include <xeno/pm.h>*/ -/*#include <xeno/kmod.h>*/ /* for hotplug_path */ -/*#include <xeno/bitops.h>*/ #include <xeno/delay.h> #include <xeno/cache.h> - #include <asm/page.h> -/*#include <asm/dma.h>*/ /* isa_dma_bridge_buggy */ #undef DEBUG @@ -1258,6 +1251,10 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de child->resource[i]->name = child->name; } + DBG("pci_add_new_bus(nr=%x,devfn=%02x(%02x:%x),parent=%x)\n", + busnr, dev->devfn, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), + parent->number); + return child; } @@ -2111,6 +2108,19 @@ void __devinit pci_init(void) pci_for_each_dev(dev) { pci_fixup_device(PCI_FIXUP_FINAL, dev); +#ifdef DEBUG + printk("PCI: %p %02x:%02x:%02x\n", dev, + dev->bus ? dev->bus->number : 0xffffffff, + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + if (dev->bus) { + printk(" s=%p ", dev->bus->self); + if ( dev->bus->self ) + printk(" %02x:%02x)", + PCI_SLOT(dev->bus->self->devfn), + PCI_FUNC(dev->bus->self->devfn)); + printk("\n"); + } +#endif /* DEBUG */ } #ifdef CONFIG_PM diff --git a/xen/include/asm-i386/pci.h b/xen/include/asm-i386/pci.h index c6be1fd992..0905e62f9f 100644 --- a/xen/include/asm-i386/pci.h +++ b/xen/include/asm-i386/pci.h @@ -19,6 +19,11 @@ extern unsigned long pci_mem_start; #define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM (pci_mem_start) +extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, + int len, u32 *value); +extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, + int len, u32 value); + void pcibios_set_master(struct pci_dev *dev); void pcibios_penalize_isa_irq(int irq); struct irq_routing_table *pcibios_get_irq_routing_table(void); diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index e2220295be..1345293284 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -208,6 +208,20 @@ typedef struct dom0_physinfo_st unsigned long free_pages; } dom0_physinfo_t; +/* + * Allow a domain access to a physical PCI device + */ +#define DOM0_PCIDEV_ACCESS 23 +typedef struct dom0_pcidev_access_st +{ + /* IN variables. */ + domid_t domain; + int bus; + int dev; + int func; + int enable; +} dom0_pcidev_access_t; + typedef struct dom0_op_st { unsigned long cmd; @@ -232,6 +246,7 @@ typedef struct dom0_op_st dom0_pincpudomain_t pincpudomain; dom0_gettbufs_t gettbufs; dom0_physinfo_t physinfo; + dom0_pcidev_access_t pcidev_access; } u; } dom0_op_t; diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 80cc7b8aee..7614d7165a 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -38,6 +38,7 @@ #define __HYPERVISOR_event_channel_op 21 #define __HYPERVISOR_xen_version 22 #define __HYPERVISOR_console_io 23 +#define __HYPERVISOR_physdev_op 24 /* * MULTICALLS @@ -58,27 +59,30 @@ */ /* Events that a guest OS may receive from the hypervisor. */ -#define EVENT_BLKDEV 0x01 /* A block device response has been queued. */ -#define EVENT_TIMER 0x02 /* A timeout has been updated. */ -#define EVENT_DIE 0x04 /* OS is about to be killed. Clean up please! */ -#define EVENT_DEBUG 0x08 /* Request guest to dump debug info (gross!) */ -#define EVENT_NET 0x10 /* There are packets for transmission. */ -#define EVENT_PS2 0x20 /* PS/2 keyboard or mouse event(s) */ -#define EVENT_STOP 0x40 /* Prepare for stopping and possible pickling */ -#define EVENT_EVTCHN 0x80 /* Event pending on an event channel */ +#define EVENT_BLKDEV 0x01 /* A block device response has been queued. */ +#define EVENT_TIMER 0x02 /* A timeout has been updated. */ +#define EVENT_DIE 0x04 /* OS is about to be killed. Clean up please! */ +#define EVENT_DEBUG 0x08 /* Request guest to dump debug info (gross!) */ +#define EVENT_NET 0x10 /* There are packets for transmission. */ +#define EVENT_PS2 0x20 /* PS/2 keyboard or mouse event(s) */ +#define EVENT_STOP 0x40 /* Prepare for stopping and possible pickling */ +#define EVENT_EVTCHN 0x80 /* Event pending on an event channel */ #define EVENT_VBD_UPD 0x100 /* Event to signal VBDs should be reprobed */ +#define EVENT_CONSOLE 0x200 /* This is only for domain-0 initial console. */ +#define EVENT_PHYSIRQ 0x400 /* Event to signal pending physical IRQs. */ /* Bit offsets, as opposed to the above masks. */ -#define _EVENT_BLKDEV 0 -#define _EVENT_TIMER 1 -#define _EVENT_DIE 2 -#define _EVENT_DEBUG 3 -#define _EVENT_NET 4 -#define _EVENT_PS2 5 -#define _EVENT_STOP 6 -#define _EVENT_EVTCHN 7 -#define _EVENT_VBD_UPD 8 -#define _EVENT_CONSOLE 9 /* This is only for domain-0 initial console. */ +#define _EVENT_BLKDEV 0 +#define _EVENT_TIMER 1 +#define _EVENT_DIE 2 +#define _EVENT_DEBUG 3 +#define _EVENT_NET 4 +#define _EVENT_PS2 5 +#define _EVENT_STOP 6 +#define _EVENT_EVTCHN 7 +#define _EVENT_VBD_UPD 8 +#define _EVENT_CONSOLE 9 +#define _EVENT_PHYSIRQ 10 /* @@ -205,6 +209,9 @@ typedef struct shared_info_st { u32 event_channel_disc[32]; u32 event_channel_disc_sel; + /* Bitmask of physical IRQ lines that are pending for this domain. */ + unsigned long physirq_pend; + /* * Time: The following abstractions are exposed: System Time, Clock Time, * Domain Virtual Time. Domains can access Cycle counter time directly. diff --git a/xen/include/hypervisor-ifs/physdev.h b/xen/include/hypervisor-ifs/physdev.h new file mode 100644 index 0000000000..925023056c --- /dev/null +++ b/xen/include/hypervisor-ifs/physdev.h @@ -0,0 +1,110 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- + **************************************************************************** + * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: physdev.h + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * Date: Feb 2004 + * + * Description: Interface for domains to access physical devices on the PCI bus + */ + +#ifndef __HYPERVISOR_IFS_PHYSDEV_H__ +#define __HYPERVISOR_IFS_PHYSDEV_H__ + +/* + * Commands to HYPERVISOR_physdev_op() + */ +#define PHYSDEVOP_CFGREG_READ 0 +#define PHYSDEVOP_CFGREG_WRITE 1 +#define PHYSDEVOP_FIND_IRQ 2 +#define PHYSDEVOP_REQUEST_IRQ 3 +#define PHYSDEVOP_FREE_IRQ 4 +#define PHYSDEVOP_ENABLE_IRQ 5 +#define PHYSDEVOP_DISABLE_IRQ 6 +#define PHYSDEVOP_FINISHED_IRQ 7 + +/* read pci config */ +typedef struct physdevop_cfgreg_read_st +{ + int seg; /* IN */ + int bus; /* IN */ + int dev; /* IN */ + int func; /* IN */ + int reg; /* IN */ + int len; /* IN */ + u32 value; /* OUT */ +} physdevop_cfgreg_read_t; + +/* write pci config */ +typedef struct physdevop_cfgred_write_st +{ + int seg; /* IN */ + int bus; /* IN */ + int dev; /* IN */ + int func; /* IN */ + int reg; /* IN */ + int len; /* IN */ + u32 value; /* IN */ +} physdevop_cfgreg_write_t; + +/* get the real IRQ for a device */ +typedef struct physdevop_find_irq_st +{ + int seg; /* IN */ + int bus; /* IN */ + int dev; /* IN */ + int func; /* IN */ + u32 irq; /* OUT */ +} physdevop_find_irq_t; + +/* request physical IRQ to be routed to guest */ +typedef struct physdevop_request_irq_st +{ + u32 irq; /* IN */ +} physdevop_request_irq_t; + +/* stop routing physical interrupts to guest */ +typedef struct physdevop_free_irq_st +{ + u32 irq; /* IN */ +} physdevop_free_irq_t; + +/* enable IRQ for the caller */ +typedef struct physdevop_enable_irq_st +{ + u32 irq; /* IN */ +} physdevop_enable_irq_t; + +/* disable interrupts */ +typedef struct physdevop_disable_irq_st +{ + u32 irq; /* IN */ +} physdevop_disable_irq_t; + +typedef struct physdevop_finished_irq_st +{ + u32 irq; /* IN */ +} physdevop_finished_irq_t; + + +typedef struct _physdev_op_st +{ + unsigned long cmd; + + /* command parameters */ + union + { + physdevop_cfgreg_read_t cfg_read; + physdevop_cfgreg_write_t cfg_write; + physdevop_find_irq_t find_irq; + physdevop_request_irq_t request_irq; + physdevop_free_irq_t free_irq; + physdevop_enable_irq_t enable_irq; + physdevop_disable_irq_t disable_irq; + physdevop_finished_irq_t finished_irq; + } u; +} physdev_op_t; + +#endif /* __HYPERVISOR_IFS_PHYSDEV_H__ */ diff --git a/xen/include/xeno/sched.h b/xen/include/xeno/sched.h index 2e17b6b526..5f728565ca 100644 --- a/xen/include/xeno/sched.h +++ b/xen/include/xeno/sched.h @@ -152,6 +152,10 @@ struct task_struct unsigned int max_event_channel; spinlock_t event_channel_lock; + /* Physical I/O */ + spinlock_t pcidev_lock; + struct list_head pcidev_list; + unsigned long flags; atomic_t refcnt; diff --git a/xenolinux-2.4.25-sparse/arch/xeno/config.in b/xenolinux-2.4.25-sparse/arch/xeno/config.in index 57e339165b..39e821556a 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/config.in +++ b/xenolinux-2.4.25-sparse/arch/xeno/config.in @@ -104,6 +104,12 @@ comment 'General setup' bool 'Networking support' CONFIG_NET +bool 'PCI support' CONFIG_PCI +if [ "$CONFIG_PCI" = "y" ]; then + tristate ' 3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX +fi +source drivers/pci/Config.in + bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL diff --git a/xenolinux-2.4.25-sparse/arch/xeno/defconfig b/xenolinux-2.4.25-sparse/arch/xeno/defconfig index 33dcb7f653..b7bedbcf3d 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/defconfig +++ b/xenolinux-2.4.25-sparse/arch/xeno/defconfig @@ -55,6 +55,8 @@ CONFIG_NOHIGHMEM=y # General setup # CONFIG_NET=y +# CONFIG_PCI is not set +# CONFIG_PCI_NAMES is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y diff --git a/xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c index a91ed32a74..dac8c2665f 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c @@ -18,9 +18,9 @@ typedef unsigned char byte; /* from linux/ide.h */ -#define XLBLK_RESPONSE_IRQ _EVENT_BLKDEV -#define XLBLK_UPDATE_IRQ _EVENT_VBD_UPD -#define DEBUG_IRQ _EVENT_DEBUG +#define XLBLK_RESPONSE_IRQ HYPEREVENT_IRQ(_EVENT_BLKDEV) +#define XLBLK_UPDATE_IRQ HYPEREVENT_IRQ(_EVENT_VBD_UPD) +#define DEBUG_IRQ HYPEREVENT_IRQ(_EVENT_DEBUG) #define STATE_ACTIVE 0 #define STATE_SUSPENDED 1 diff --git a/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c b/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c index 2e18d72854..367b9b4f0e 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c @@ -446,7 +446,8 @@ int __init xeno_con_init(void) } else { - request_irq(_EVENT_CONSOLE, control_irq, 0, "console", NULL); + request_irq(HYPEREVENT_IRQ(_EVENT_CONSOLE), + control_irq, 0, "console", NULL); control_irq(0, NULL, NULL); /* kickstart the console */ } diff --git a/xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c b/xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c index f060562529..f642d082cd 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c @@ -21,6 +21,7 @@ #include <linux/devfs_fs_kernel.h> #include <linux/stat.h> #include <linux/poll.h> +#include <linux/irq.h> #include <asm/evtchn.h> /* NB. This must be shared amongst drivers if more things go in /dev/xen */ @@ -454,7 +455,8 @@ static int __init init_module(void) /* (DEVFS) automatically destroy the symlink with its destination. */ devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle); - err = request_irq(_EVENT_EVTCHN, evtchn_interrupt, 0, "evtchn", NULL); + err = request_irq(HYPEREVENT_IRQ(_EVENT_EVTCHN), + evtchn_interrupt, 0, "evtchn", NULL); if ( err != 0 ) { printk(KERN_ALERT "Could not allocate evtchn receive interrupt\n"); @@ -471,7 +473,7 @@ static int __init init_module(void) static void cleanup_module(void) { - free_irq(_EVENT_EVTCHN, NULL); + free_irq(HYPEREVENT_IRQ(_EVENT_EVTCHN), NULL); misc_deregister(&evtchn_miscdev); } diff --git a/xenolinux-2.4.25-sparse/arch/xeno/drivers/network/network.c b/xenolinux-2.4.25-sparse/arch/xeno/drivers/network/network.c index 95b4c45501..512f6530a5 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/network/network.c +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/network/network.c @@ -25,8 +25,6 @@ #include <net/sock.h> #include <net/pkt_sched.h> -#define NET_IRQ _EVENT_NET - #define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */ static void network_interrupt(int irq, void *dev_id, struct pt_regs *ptregs); @@ -546,7 +544,7 @@ static int __init init_module(void) if ( start_info.flags & SIF_INITDOMAIN ) (void)register_inetaddr_notifier(¬ifier_inetdev); - err = request_irq(NET_IRQ, network_interrupt, + err = request_irq(HYPEREVENT_IRQ(_EVENT_NET), network_interrupt, SA_SAMPLE_RANDOM, "network", NULL); if ( err ) { @@ -554,8 +552,8 @@ static int __init init_module(void) goto fail; } - err = request_irq(_EVENT_DEBUG, dbg_network_int, SA_SHIRQ, "net_dbg", - &dbg_network_int); + err = request_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), dbg_network_int, + SA_SHIRQ, "net_dbg", &dbg_network_int); if ( err ) printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n"); diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/Makefile b/xenolinux-2.4.25-sparse/arch/xeno/kernel/Makefile index a43a615e2f..10fc43e742 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/Makefile +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/Makefile @@ -10,6 +10,10 @@ export-objs := i386_ksyms.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \ - i386_ksyms.o i387.o hypervisor.o + i386_ksyms.o i387.o hypervisor.o physirq.o pci-dma.o + +ifdef CONFIG_PCI +obj-y += pci-i386.o pci-pc.o pci-irq.o +endif include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/hypervisor.c b/xenolinux-2.4.25-sparse/arch/xeno/kernel/hypervisor.c index 8e7e144137..64a3590362 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/hypervisor.c +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/hypervisor.c @@ -37,13 +37,14 @@ void do_hypervisor_callback(struct pt_regs *regs) " sub $4,%%esp ;" " jmp 2f ;" "1: btrl %%eax,%0 ;" /* clear bit */ + " add %2,%%eax ;" " mov %%eax,(%%esp) ;" " call do_IRQ ;" /* do_IRQ(event) */ "2: bsfl %0,%%eax ;" /* %eax == bit # */ " jnz 1b ;" " add $8,%%esp ;" /* we use %ebx because it is callee-saved */ - : : "b" (events), "r" (regs) + : : "b" (events), "r" (regs), "i" (HYPEREVENT_IRQ_BASE) /* clobbered by callback function calls */ : "eax", "ecx", "edx", "memory" ); @@ -54,41 +55,40 @@ void do_hypervisor_callback(struct pt_regs *regs) while ( shared->events ); } - - /* * Define interface to generic handling in irq.c */ static void shutdown_hypervisor_event(unsigned int irq) { - clear_bit(irq, &event_mask); - clear_bit(irq, &HYPERVISOR_shared_info->events_mask); + clear_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask); + clear_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask); } static void enable_hypervisor_event(unsigned int irq) { - set_bit(irq, &event_mask); - set_bit(irq, &HYPERVISOR_shared_info->events_mask); - if ( test_bit(EVENTS_MASTER_ENABLE_BIT, + set_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask); + set_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask); + if ( test_bit(EVENTS_MASTER_ENABLE_BIT, &HYPERVISOR_shared_info->events_mask) ) do_hypervisor_callback(NULL); } static void disable_hypervisor_event(unsigned int irq) { - clear_bit(irq, &event_mask); - clear_bit(irq, &HYPERVISOR_shared_info->events_mask); + clear_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask); + clear_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask); } static void ack_hypervisor_event(unsigned int irq) { - if ( !(event_mask & (1<<irq)) ) + int ev = HYPEREVENT_FROM_IRQ(irq); + if ( !(event_mask & (1<<ev)) ) { - printk("Unexpected hypervisor event %d\n", irq); + printk("Unexpected hypervisor event %d\n", ev); atomic_inc(&irq_err_count); } - set_bit(irq, &HYPERVISOR_shared_info->events_mask); + set_bit(ev, &HYPERVISOR_shared_info->events_mask); } static unsigned int startup_hypervisor_event(unsigned int irq) @@ -116,11 +116,14 @@ void __init init_IRQ(void) { int i; - for ( i = 0; i < NR_IRQS; i++ ) + for ( i = 0; i < NR_HYPEREVENT_IRQS; i++ ) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &hypervisor_irq_type; + irq_desc[i + HYPEREVENT_IRQ_BASE].status = IRQ_DISABLED; + irq_desc[i + HYPEREVENT_IRQ_BASE].action = 0; + irq_desc[i + HYPEREVENT_IRQ_BASE].depth = 1; + irq_desc[i + HYPEREVENT_IRQ_BASE].handler = &hypervisor_irq_type; } + + /* Also initialise the physical IRQ handlers. */ + physirq_init(); } diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-dma.c b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-dma.c new file mode 100644 index 0000000000..dd8842719e --- /dev/null +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-dma.c @@ -0,0 +1,37 @@ +/* + * Dynamic DMA mapping support. + * + * On i386 there is no hardware dynamic DMA address translation, + * so consistent alloc/free are merely page allocation/freeing. + * The rest of the dynamic DMA mapping interface is implemented + * in asm/pci.h. + */ + +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/pci.h> +#include <asm/io.h> + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + if (hwdev == NULL || ((u32)hwdev->dma_mask < 0xffffffff)) + gfp |= GFP_DMA; + ret = (void *)__get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + return ret; +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.c b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.c new file mode 100644 index 0000000000..96dcdde6b3 --- /dev/null +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.c @@ -0,0 +1,410 @@ +/* + * Low-Level PCI Access for i386 machines + * + * Copyright 1993, 1994 Drew Eckhardt + * Visionary Computing + * (Unix and Linux consulting and custom programming) + * Drew@Colorado.EDU + * +1 (303) 786-7975 + * + * Drew's work was sponsored by: + * iX Multiuser Multitasking Magazine + * Hannover, Germany + * hm@ix.de + * + * Copyright 1997--2000 Martin Mares <mj@ucw.cz> + * + * For more information, please consult the following manuals (look at + * http://www.pcisig.com/ for how to get them): + * + * PCI BIOS Specification + * PCI Local Bus Specification + * PCI to PCI Bridge Specification + * PCI System Design Guide + * + * + * CHANGELOG : + * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION + * Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard. + * + * Jan 5, 1995 : Modified to probe PCI hardware at boot time by Frederic + * Potter, potter@cao-vlsi.ibp.fr + * + * Jan 10, 1995 : Modified to store the information about configured pci + * devices into a list, which can be accessed via /proc/pci by + * Curtis Varner, cvarner@cs.ucr.edu + * + * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter. + * Alpha version. Intel & UMC chipset support only. + * + * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code + * moved to drivers/pci/pci.c. + * + * Dec 7, 1996 : Added support for direct configuration access of boards + * with Intel compatible access schemes (tsbogend@alpha.franken.de) + * + * Feb 3, 1997 : Set internal functions to static, save/restore flags + * avoid dead locks reading broken PCI BIOS, werner@suse.de + * + * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS + * (mj@atrey.karlin.mff.cuni.cz) + * + * May 7, 1997 : Added some missing cli()'s. [mj] + * + * Jun 20, 1997 : Corrected problems in "conf1" type accesses. + * (paubert@iram.es) + * + * Aug 2, 1997 : Split to PCI BIOS handling and direct PCI access parts + * and cleaned it up... Martin Mares <mj@atrey.karlin.mff.cuni.cz> + * + * Feb 6, 1998 : No longer using BIOS to find devices and device classes. [mj] + * + * May 1, 1998 : Support for peer host bridges. [mj] + * + * Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space + * can be accessed from interrupts even on SMP systems. [mj] + * + * August 1998 : Better support for peer host bridges and more paranoid + * checks for direct hardware access. Ugh, this file starts to look as + * a large gallery of common hardware bug workarounds (watch the comments) + * -- the PCI specs themselves are sane, but most implementors should be + * hit hard with \hammer scaled \magstep5. [mj] + * + * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj] + * + * Feb 8, 1999 : Added UM8886BF I/O address fixup. [mj] + * + * August 1999 : New resource management and configuration access stuff. [mj] + * + * Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges. + * Based on ideas by Chris Frantz and David Hinds. [mj] + * + * Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi + * for a lot of patience during testing. [mj] + * + * Oct 8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj] + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/errno.h> + +#include "pci-i386.h" + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + u32 new, check; + int reg; + + new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + if (resource < 6) { + reg = PCI_BASE_ADDRESS_0 + 4*resource; + } else if (resource == PCI_ROM_RESOURCE) { + res->flags |= PCI_ROM_ADDRESS_ENABLE; + new |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else { + /* Somebody might have asked allocation of a non-standard resource */ + return; + } + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { + printk(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resource, + new, check); + } +} + +/* + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + * + * Why? Because some silly external IO cards only decode + * the low 10 bits of the IO address. The 0x00-0xff region + * is reserved for motherboard devices that decode all 16 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff, + * but we want to try to avoid allocating at 0x2900-0x2bff + * which might have be mirrored at 0x0100-0x03ff.. + */ +void +pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } + } +} + + +/* + * Handle resources of PCI devices. If the world were perfect, we could + * just allocate all the resource regions and do nothing more. It isn't. + * On the other hand, we cannot just re-allocate all devices, as it would + * require us to know lots of host bridge internals. So we attempt to + * keep as much of the original configuration as possible, but tweak it + * when it's found to be wrong. + * + * Known BIOS problems we have to work around: + * - I/O or memory regions not configured + * - regions configured, but not enabled in the command register + * - bogus I/O addresses above 64K used + * - expansion ROMs left enabled (this may sound harmless, but given + * the fact the PCI specs explicitly allow address decoders to be + * shared between expansion ROMs and other resource regions, it's + * at least dangerous) + * + * Our solution: + * (1) Allocate resources for all buses behind PCI-to-PCI bridges. + * This gives us fixed barriers on where we can allocate. + * (2) Allocate resources for all enabled devices. If there is + * a collision, just mark the resource as unallocated. Also + * disable expansion ROMs during this step. + * (3) Try to allocate resources for disabled devices. If the + * resources were assigned correctly, everything goes well, + * if they weren't, they won't disturb allocation of other + * resources. + * (4) Assign new addresses to resources which were either + * not configured at all or misconfigured. If explicitly + * requested by the user, configure expansion ROM address + * as well. + */ + +static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) +{ + struct list_head *ln; + struct pci_bus *bus; + struct pci_dev *dev; + int idx; + struct resource *r, *pr; + + /* Depth-First Search on bus tree */ + for (ln=bus_list->next; ln != bus_list; ln=ln->next) { + bus = pci_bus_b(ln); + if ((dev = bus->self)) { + printk("alloc bus res: %s\n", dev->slot_name); + for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { + r = &dev->resource[idx]; + if (!r->start) + { + printk(" res1: 0x%08lx-0x%08lx f=%lx\n", + r->start, r->end, r->flags); + + continue; + } + pr = pci_find_parent_resource(dev, r); + if (!pr || request_resource(pr, r) < 0) + printk(KERN_ERR "PCI: Cannot allocate resource region %d " + "of bridge %s (%p)\n", idx, dev->slot_name, pr); + printk(" res2: %08lx-%08lx f=%lx\n", + r->start, r->end, r->flags); + } + } + pcibios_allocate_bus_resources(&bus->children); + } +} + +static void __init pcibios_allocate_resources(int pass) +{ + struct pci_dev *dev; + int idx, disabled; + u16 command; + struct resource *r, *pr; + + pci_for_each_dev(dev) { + pci_read_config_word(dev, PCI_COMMAND, &command); + for(idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + if (r->parent) /* Already allocated */ + continue; + if (!r->start) /* Address not assigned at all */ + continue; + if (r->flags & IORESOURCE_IO) + disabled = !(command & PCI_COMMAND_IO); + else + disabled = !(command & PCI_COMMAND_MEMORY); + if (pass == disabled) { + printk("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d) (%s)\n", + r->start, r->end, r->flags, disabled, pass, dev->slot_name); + pr = pci_find_parent_resource(dev, r); + if (!pr || request_resource(pr, r) < 0) { + printk(KERN_ERR "PCI: Cannot allocate resource region %d" + " of device %s (%p)\n", idx, dev->slot_name, pr); + /* We'll assign a new address later */ + r->end -= r->start; + r->start = 0; + } + } + } + if (!pass) { + r = &dev->resource[PCI_ROM_RESOURCE]; + if (r->flags & PCI_ROM_ADDRESS_ENABLE) { + /* Turn the ROM off, leave the resource region, but keep it unregistered. */ + u32 reg; + printk("PCI: Switching off ROM of %s\n", dev->slot_name); + r->flags &= ~PCI_ROM_ADDRESS_ENABLE; + pci_read_config_dword(dev, dev->rom_base_reg, ®); + pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); + } + } + } +} + +static void __init pcibios_assign_resources(void) +{ + struct pci_dev *dev; + int idx; + struct resource *r; + + pci_for_each_dev(dev) { + int class = dev->class >> 8; + + /* Don't touch classless devices and host bridges */ + if (!class || class == PCI_CLASS_BRIDGE_HOST) + continue; + + for(idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + + /* + * Don't touch IDE controllers and I/O ports of video cards! + */ + if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) || + (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO))) + continue; + + /* + * We shall assign a new address to this resource, either because + * the BIOS forgot to do so or because we have decided the old + * address was unusable for some reason. + */ + if (!r->start && r->end) + pci_assign_resource(dev, idx); + } + + if (pci_probe & PCI_ASSIGN_ROMS) { + r = &dev->resource[PCI_ROM_RESOURCE]; + r->end -= r->start; + r->start = 0; + if (r->end) + pci_assign_resource(dev, PCI_ROM_RESOURCE); + } + } +} + +void __init pcibios_set_cacheline_size(void) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + + pci_cache_line_size = 32 >> 2; + if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD) + pci_cache_line_size = 64 >> 2; /* K7 & K8 */ + else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL) + pci_cache_line_size = 128 >> 2; /* P4 */ +} + +void __init pcibios_resource_survey(void) +{ + DBG("PCI: Allocating resources\n"); + pcibios_allocate_bus_resources(&pci_root_buses); + pcibios_allocate_resources(0); + pcibios_allocate_resources(1); + pcibios_assign_resources(); +} + +int pcibios_enable_resources(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for(idx=0; idx<6; idx++) { + /* Only set up the requested stuff */ + if (!(mask & (1<<idx))) + continue; + + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +/* + * If we set up a device for bus mastering, we need to check the latency + * timer as certain crappy BIOSes forget to set it properly. + */ +unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + +int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, int write_combine) +{ + unsigned long prot; + + /* I/O space cannot be accessed via normal processor loads and + * stores on this platform. + */ + if (mmap_state == pci_mmap_io) + return -EINVAL; + + /* Leave vm_pgoff as-is, the PCI space address is the physical + * address on this platform. + */ + vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO); + + prot = pgprot_val(vma->vm_page_prot); + if (boot_cpu_data.x86 > 3) + prot |= _PAGE_PCD | _PAGE_PWT; + vma->vm_page_prot = __pgprot(prot); + + /* Write-combine setting is ignored, it is changed via the mtrr + * interfaces on this platform. + */ + if (remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.h b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.h new file mode 100644 index 0000000000..fe70b10166 --- /dev/null +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.h @@ -0,0 +1,71 @@ +/* + * Low-Level PCI Access for i386 machines. + * + * (c) 1999 Martin Mares <mj@ucw.cz> + */ + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define PCI_PROBE_BIOS 0x0001 +#define PCI_PROBE_CONF1 0x0002 +#define PCI_PROBE_CONF2 0x0004 +#define PCI_NO_SORT 0x0100 +#define PCI_BIOS_SORT 0x0200 +#define PCI_NO_CHECKS 0x0400 +#define PCI_ASSIGN_ROMS 0x1000 +#define PCI_BIOS_IRQ_SCAN 0x2000 +#define PCI_ASSIGN_ALL_BUSSES 0x4000 + +extern unsigned int pci_probe; + +/* pci-i386.c */ + +extern unsigned int pcibios_max_latency; +extern u8 pci_cache_line_size; + +void pcibios_resource_survey(void); +void pcibios_set_cacheline_size(void); +int pcibios_enable_resources(struct pci_dev *, int); + +/* pci-pc.c */ + +extern int pcibios_last_bus; +extern struct pci_bus *pci_root_bus; +extern struct pci_ops *pci_root_ops; + +/* pci-irq.c */ + +struct irq_info { + u8 bus, devfn; /* Bus, device and function */ + struct { + u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ + u16 bitmap; /* Available IRQs */ + } __attribute__((packed)) irq[4]; + u8 slot; /* Slot number, 0=onboard */ + u8 rfu; +} __attribute__((packed)); + +struct irq_routing_table { + u32 signature; /* PIRQ_SIGNATURE should be here */ + u16 version; /* PIRQ_VERSION */ + u16 size; /* Table size in bytes */ + u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ + u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ + u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ + u32 miniport_data; /* Crap */ + u8 rfu[11]; + u8 checksum; /* Modulo 256 checksum must give zero */ + struct irq_info slots[0]; +} __attribute__((packed)); + +extern unsigned int pcibios_irq_mask; + +void pcibios_irq_init(void); +void pcibios_fixup_irqs(void); +void pcibios_enable_irq(struct pci_dev *dev); diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-irq.c b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-irq.c new file mode 100644 index 0000000000..f530244f6a --- /dev/null +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-irq.c @@ -0,0 +1,90 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- + **************************************************************************** + * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: phys_dev.c + * Author: Rolf Neugebauer (rolf.neugebauer@intel.com) + * Date: Mar 2004 + * + * Description: XenoLinux wrappers for PCI interrupt handling. + * very simple since someone else is doing all the hard bits + */ + + +/* + * Low-Level PCI Support for PC -- Routing of Interrupts + * + * (c) 1999--2000 Martin Mares <mj@ucw.cz> + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include "pci-i386.h" + +#include <asm/hypervisor-ifs/physdev.h> + +unsigned int pcibios_irq_mask = 0xfff8; + +void eisa_set_level_irq(unsigned int irq) +{ + /* dummy */ +} + +void __init pcibios_irq_init(void) +{ + printk("PCI: IRQ init\n"); +} + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev; + physdev_op_t op; + int ret; + + + printk("PCI: IRQ fixup\n"); + pci_for_each_dev(dev) { + + op.cmd = PHYSDEVOP_FIND_IRQ; + op.u.find_irq.seg = 0; + op.u.find_irq.bus = dev->bus->number; + op.u.find_irq.dev = PCI_SLOT(dev->devfn); + op.u.find_irq.func = PCI_FUNC(dev->devfn); + + if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 ) + { + printk(KERN_ALERT "pci find irq error\n"); + return; + } + + dev->irq = op.u.find_irq.irq; + printk(KERN_INFO "PCI IRQ: [%02x:%02x:%02x] -> %d\n", + dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), dev->irq); + } + return; +} + +void pcibios_penalize_isa_irq(int irq) +{ + /* dummy */ +} + +void pcibios_enable_irq(struct pci_dev *dev) +{ + u8 pin; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + + if (pin && !dev->irq) { + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of " + "device %s.\n", 'A' + pin - 1, dev->slot_name); + } +} diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-pc.c b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-pc.c new file mode 100644 index 0000000000..afe6e4d494 --- /dev/null +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-pc.c @@ -0,0 +1,364 @@ +/* + * Low-Level PCI Support for PC + * + * (c) 1999--2000 Martin Mares <mj@ucw.cz> + * + * adjusted to use Xen's interface by Rolf Neugebauer + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/ioport.h> + +#include <asm/segment.h> +#include <asm/io.h> + +#include <asm/hypervisor-ifs/hypervisor-if.h> +#include <asm/hypervisor-ifs/physdev.h> + +#include "pci-i386.h" + +int pcibios_last_bus = -1; +struct pci_bus *pci_root_bus = NULL; +struct pci_ops *pci_root_ops = NULL; + +int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL; +int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL; + +static int pci_using_acpi_prt = 0; + +/* + * This interrupt-safe spinlock protects all accesses to PCI + * configuration space. + */ +static spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED; + +unsigned int pci_probe = PCI_PROBE_BIOS; + +/* + * Functions for accessing PCI configuration space with type 1 accesses + */ + +static int pci_confx_read (int seg, int bus, int dev, int fn, int reg, + int len, u32 *value) +{ + int ret; + physdev_op_t op; + + if (bus > 255 || dev > 31 || fn > 7 || reg > 255) + return -EINVAL; + + op.cmd = PHYSDEVOP_CFGREG_READ; + op.u.cfg_read.seg = seg; + op.u.cfg_read.bus = bus; + op.u.cfg_read.dev = dev; + op.u.cfg_read.func = fn; + op.u.cfg_read.reg = reg; + op.u.cfg_read.len = len; + + if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 ) + { + //printk(KERN_ALERT "pci config read error\n"); + return ret; + } + + *value = op.u.cfg_read.value; + + return 0; +} + +static int pci_confx_write (int seg, int bus, int dev, int fn, int reg, + int len, u32 value) +{ + int ret; + physdev_op_t op; + + if ((bus > 255 || dev > 31 || fn > 7 || reg > 255)) + return -EINVAL; + + op.cmd = PHYSDEVOP_CFGREG_WRITE; + op.u.cfg_write.seg = seg; + op.u.cfg_write.bus = bus; + op.u.cfg_write.dev = dev; + op.u.cfg_write.func = fn; + op.u.cfg_write.reg = reg; + op.u.cfg_write.len = len; + op.u.cfg_write.value = value; + + if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 ) + { + //printk(KERN_ALERT "pci config write error\n"); + return ret; + } + return 0; +} + + +static int pci_confx_read_config_byte(struct pci_dev *dev, int where, u8 *value) +{ + int result; + u32 data; + + result = pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, &data); + + *value = (u8)data; + + return result; +} + +static int pci_confx_read_config_word(struct pci_dev *dev, int where, u16 *value) +{ + int result; + u32 data; + + result = pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, &data); + + *value = (u16)data; + + return result; +} + +static int pci_confx_read_config_dword(struct pci_dev *dev, int where, u32 *value) +{ + return pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); +} + +static int pci_confx_write_config_byte(struct pci_dev *dev, int where, u8 value) +{ + return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, value); +} + +static int pci_confx_write_config_word(struct pci_dev *dev, int where, u16 value) +{ + return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, value); +} + +static int pci_confx_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); +} + +static struct pci_ops pci_direct_confx = { + pci_confx_read_config_byte, + pci_confx_read_config_word, + pci_confx_read_config_dword, + pci_confx_write_config_byte, + pci_confx_write_config_word, + pci_confx_write_config_dword +}; + + + +static struct pci_ops * __devinit pci_check_xen(void) +{ + unsigned long flags; + + __save_flags(flags); __cli(); + + printk(KERN_INFO "PCI: Using Xen interface\n"); + + __restore_flags(flags); + + return &pci_direct_confx; +} + +struct pci_fixup pcibios_fixups[] = { {0}}; + + +struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void) +{ + return NULL; +} + +int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) +{ + return 0; +} + +/* + * Several buggy motherboards address only 16 devices and mirror + * them to next 16 IDs. We try to detect this `feature' on all + * primary buses (those containing host bridges as they are + * expected to be unique) and remove the ghost devices. + */ + +static void __devinit pcibios_fixup_ghosts(struct pci_bus *b) +{ + struct list_head *ln, *mn; + struct pci_dev *d, *e; + int mirror = PCI_DEVFN(16,0); + int seen_host_bridge = 0; + int i; + + DBG("PCI: Scanning for ghost devices on bus %d\n", b->number); + for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { + d = pci_dev_b(ln); + if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST) + seen_host_bridge++; + for (mn=ln->next; mn != &b->devices; mn=mn->next) { + e = pci_dev_b(mn); + if (e->devfn != d->devfn + mirror || + e->vendor != d->vendor || + e->device != d->device || + e->class != d->class) + continue; + for(i=0; i<PCI_NUM_RESOURCES; i++) + if (e->resource[i].start != d->resource[i].start || + e->resource[i].end != d->resource[i].end || + e->resource[i].flags != d->resource[i].flags) + continue; + break; + } + if (mn == &b->devices) + return; + } + if (!seen_host_bridge) + return; + printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number); + + ln = &b->devices; + while (ln->next != &b->devices) { + d = pci_dev_b(ln->next); + if (d->devfn >= mirror) { + list_del(&d->global_list); + list_del(&d->bus_list); + kfree(d); + } else + ln = ln->next; + } +} + +/* + * Discover remaining PCI buses in case there are peer host bridges. + * We use the number of last PCI bus provided by the PCI BIOS. + */ +static void __devinit pcibios_fixup_peer_bridges(void) +{ + int n; + struct pci_bus bus; + struct pci_dev dev; + u16 l; + + if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) + return; + DBG("PCI: Peer bridge fixup\n"); + for (n=0; n <= pcibios_last_bus; n++) { + if (pci_bus_exists(&pci_root_buses, n)) + continue; + bus.number = n; + bus.ops = pci_root_ops; + dev.bus = &bus; + for(dev.devfn=0; dev.devfn<256; dev.devfn += 8) + if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) && + l != 0x0000 && l != 0xffff) { + DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); + printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); + pci_scan_bus(n, pci_root_ops, NULL); + break; + } + } +} + + +/* + * Called after each bus is probed, but before its children + * are examined. + */ + +void __devinit pcibios_fixup_bus(struct pci_bus *b) +{ + pcibios_fixup_ghosts(b); + pci_read_bridge_bases(b); + return; +} + +struct pci_bus * __devinit pcibios_scan_root(int busnum) +{ + struct list_head *list; + struct pci_bus *bus; + + list_for_each(list, &pci_root_buses) { + bus = pci_bus_b(list); + if (bus->number == busnum) { + /* Already scanned */ + return bus; + } + } + + printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); + + return pci_scan_bus(busnum, pci_root_ops, NULL); +} + +void __devinit pcibios_config_init(void) +{ + /* + * Try all known PCI access methods. Note that we support using + * both PCI BIOS and direct access, with a preference for direct. + */ + + pci_root_ops = pci_check_xen(); + pci_config_read = pci_confx_read; + pci_config_write = pci_confx_write; + + return; +} + +void __init pcibios_init(void) +{ + if (!pci_root_ops) + pcibios_config_init(); + if (!pci_root_ops) { + printk(KERN_WARNING "PCI: System does not support PCI\n"); + return; + } + + pcibios_set_cacheline_size(); + + printk(KERN_INFO "PCI: Probing PCI hardware\n"); + + if (!pci_using_acpi_prt) { + pci_root_bus = pcibios_scan_root(0); + pcibios_irq_init(); + pcibios_fixup_peer_bridges(); + pcibios_fixup_irqs(); + } + + pcibios_resource_survey(); +} + +char * __devinit pcibios_setup(char *str) +{ + if (!strcmp(str, "off")) { + pci_probe = 0; + return NULL; + } + return NULL; +} + +unsigned int pcibios_assign_all_busses(void) +{ + return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + int err; + + if ((err = pcibios_enable_resources(dev, mask)) < 0) + return err; + + pcibios_enable_irq(dev); + + return 0; +} diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/physirq.c b/xenolinux-2.4.25-sparse/arch/xeno/kernel/physirq.c new file mode 100644 index 0000000000..3a6083b24e --- /dev/null +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/physirq.c @@ -0,0 +1,156 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- + **************************************************************************** + * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: physirq.c + * Author: Rolf Neugebauer (rolf.neugebauer@intel.com) + * Date: Mar 2004 + * + * Description: guests may receive virtual interrupts directly + * corresponding to physical interrupts. these virtual + * interrupts require special handling provided + * by the virq irq type. + */ + + +#include <linux/config.h> +#include <asm/atomic.h> +#include <asm/irq.h> +#include <asm/hypervisor.h> +#include <asm/system.h> + +#include <linux/irq.h> +#include <linux/sched.h> + +#include <asm/hypervisor-ifs/hypervisor-if.h> +#include <asm/hypervisor-ifs/physdev.h> + +static void physirq_interrupt(int irq, void *unused, struct pt_regs *ptregs); + +static int setup_event_handler = 0; + +static unsigned int startup_physirq_event(unsigned int irq) +{ + physdev_op_t op; + int err; + + printk("startup_physirq_event %d\n", irq); + + /* + * install a interrupt handler for physirq event when called thefirst tim + */ + if ( !setup_event_handler ) + { + printk("startup_physirq_event %d: setup event handler\n", irq); + /* set up a event handler to demux virtualised physical interrupts */ + err = request_irq(HYPEREVENT_IRQ(_EVENT_PHYSIRQ), physirq_interrupt, + SA_SAMPLE_RANDOM, "physirq", NULL); + if ( err ) + { + printk(KERN_WARNING "Could not allocate physirq interrupt\n"); + return err; + } + setup_event_handler = 1; + } + + /* + * request the irq from hypervisor + */ + op.cmd = PHYSDEVOP_REQUEST_IRQ; + op.u.request_irq.irq = irq; + if ( (err = HYPERVISOR_physdev_op(&op)) != 0 ) + { + printk(KERN_ALERT "could not get IRQ %d from Xen\n", irq); + return err; + } + return 0; +} + +static void shutdown_physirq_event(unsigned int irq) +{ + + /* call xen to free IRQ */ + +} + + +static void enable_physirq_event(unsigned int irq) +{ + /* XXX just enable all interrupts for now */ +} + +static void disable_physirq_event(unsigned int irq) +{ + /* XXX just disable all interrupts for now */ +} + +static void ack_physirq_event(unsigned int irq) +{ + /* clear bit */ + if ( irq <= 0 || irq >= 32 ) + { + printk("wrong irq %d\n", irq); + } + + clear_bit(irq, &HYPERVISOR_shared_info->physirq_pend); +} + +static void end_physirq_event(unsigned int irq) +{ + int err; + physdev_op_t op; + /* call hypervisor */ + op.cmd = PHYSDEVOP_FINISHED_IRQ; + op.u.finished_irq.irq = irq; + if ( (err = HYPERVISOR_physdev_op(&op)) != 0 ) + { + printk(KERN_ALERT "could not finish IRQ %d\n", irq); + return; + } + return; +} + +static struct hw_interrupt_type physirq_irq_type = { + "physical-irq", + startup_physirq_event, + shutdown_physirq_event, + enable_physirq_event, + disable_physirq_event, + ack_physirq_event, + end_physirq_event, + NULL +}; + + +/* + * this interrupt handler demuxes the virt phys event and the virt phys + * bitmask and calls the interrupt handlers for virtualised physical interrupts + */ +static void physirq_interrupt(int irq, void *unused, struct pt_regs *ptregs) +{ +#if 0 + unsigned long flags; + int virq; + local_irq_save(flags); + do_IRQ(virq); + local_irq_restore(flags); +#endif +} + + +void __init physirq_init(void) +{ + int i; + + printk("Initialise irq handlers [%d-%d] for physical interrupts.\n", + PHYS_IRQ_BASE, PHYS_IRQ_BASE+NR_PHYS_IRQS-1); + + for ( i = 0; i < NR_PHYS_IRQS; i++ ) + { + irq_desc[i + PHYS_IRQ_BASE].status = IRQ_DISABLED; + irq_desc[i + PHYS_IRQ_BASE].action = 0; + irq_desc[i + PHYS_IRQ_BASE].depth = 1; + irq_desc[i + PHYS_IRQ_BASE].handler = &physirq_irq_type; + } +} diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c b/xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c index 762a9946ae..c593bddec7 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c @@ -1124,7 +1124,7 @@ static void die_irq(int irq, void *unused, struct pt_regs *regs) static int __init setup_die_event(void) { - (void)request_irq(_EVENT_DIE, die_irq, 0, "die", NULL); + (void)request_irq(HYPEREVENT_IRQ(_EVENT_DIE), die_irq, 0, "die", NULL); return 0; } @@ -1249,7 +1249,7 @@ static void stop_irq(int irq, void *unused, struct pt_regs *regs) static int __init setup_stop_event(void) { - (void)request_irq(_EVENT_STOP, stop_irq, 0, "stop", NULL); + (void)request_irq(HYPEREVENT_IRQ(_EVENT_STOP), stop_irq, 0, "stop", NULL); return 0; } diff --git a/xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c b/xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c index 0d41748c82..574ba786b4 100644 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c @@ -623,9 +623,9 @@ void __init time_init(void) __get_time_values_from_xen(); processed_system_time = shadow_system_time; - (void)setup_irq(TIMER_IRQ, &irq_timer); + (void)setup_irq(HYPEREVENT_IRQ(_EVENT_TIMER), &irq_timer); - (void)setup_irq(_EVENT_DEBUG, &dbg_time); + (void)setup_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), &dbg_time); rdtscll(alarm); diff --git a/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h b/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h index 8a25957722..fe13471aa5 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h @@ -451,4 +451,15 @@ static inline int HYPERVISOR_console_io(int cmd, int count, char *str) return ret; } +static inline int HYPERVISOR_physdev_op(void *physdev_op) +{ + int ret; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) : "0" (__HYPERVISOR_physdev_op), + "b" (physdev_op) : "memory" ); + + return ret; +} + #endif /* __HYPERVISOR_H__ */ diff --git a/xenolinux-2.4.25-sparse/include/asm-xeno/irq.h b/xenolinux-2.4.25-sparse/include/asm-xeno/irq.h index 3a4a3e394f..917a05334d 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/irq.h +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/irq.h @@ -14,9 +14,18 @@ #include <asm/hypervisor.h> #include <asm/ptrace.h> -#define TIMER_IRQ _EVENT_TIMER +#define NR_IRQS 256 -#define NR_IRQS (sizeof(HYPERVISOR_shared_info->events) * 8) +#define PHYS_IRQ_BASE 0 +#define NR_PHYS_IRQS 128 + +#define HYPEREVENT_IRQ_BASE 128 +#define NR_HYPEREVENT_IRQS 128 + +#define HYPEREVENT_IRQ(_ev) ((_ev) + HYPEREVENT_IRQ_BASE) +#define HYPEREVENT_FROM_IRQ(_irq) ((_irq) - HYPEREVENT_IRQ_BASE) + +extern void physirq_init(void); #define irq_cannonicalize(_irq) (_irq) diff --git a/xenolinux-2.4.25-sparse/include/asm-xeno/keyboard.h b/xenolinux-2.4.25-sparse/include/asm-xeno/keyboard.h index 4afd25cd42..82e10faab2 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/keyboard.h +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/keyboard.h @@ -60,7 +60,7 @@ static inline int xen_kbd_controller_present () #define kbd_request_region() \ do { } while (0) #define kbd_request_irq(handler) \ - request_irq(_EVENT_PS2, handler, 0, "ps/2", NULL) + request_irq(HYPEREVENT_IRQ(_EVENT_PS2), handler, 0, "ps/2", NULL) /* could implement these with command to xen to filter mouse stuff... */ #define aux_request_irq(hand, dev_id) 0 |