ia64/xen-unstable

changeset 1173:0920098bad91

bitkeeper revision 1.789 (4051dba62id7XBLQIfBX2kqtjQJzfQ)

physirq.c, pci-pc.c, pci-irq.c, pci-i386.h, pci-i386.c, pci-dma.c, physdev.h:
new file
Many files:
Second half of Rolf's IO patch.
author kaf24@scramble.cl.cam.ac.uk
date Fri Mar 12 15:47:50 2004 +0000 (2004-03-12)
parents 81897ae013e0
children 576575968828
files .rootkeys tools/xc/lib/xc_physdev.c xen/common/domain.c xen/common/physdev.c xen/drivers/pci/pci.c xen/include/asm-i386/pci.h xen/include/hypervisor-ifs/dom0_ops.h xen/include/hypervisor-ifs/hypervisor-if.h xen/include/hypervisor-ifs/physdev.h xen/include/xeno/sched.h xenolinux-2.4.25-sparse/arch/xeno/config.in xenolinux-2.4.25-sparse/arch/xeno/defconfig xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c xenolinux-2.4.25-sparse/arch/xeno/drivers/network/network.c xenolinux-2.4.25-sparse/arch/xeno/kernel/Makefile xenolinux-2.4.25-sparse/arch/xeno/kernel/hypervisor.c xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-dma.c xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.c xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.h xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-irq.c xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-pc.c xenolinux-2.4.25-sparse/arch/xeno/kernel/physirq.c xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h xenolinux-2.4.25-sparse/include/asm-xeno/irq.h xenolinux-2.4.25-sparse/include/asm-xeno/keyboard.h
line diff
     1.1 --- a/.rootkeys	Fri Mar 12 13:36:59 2004 +0000
     1.2 +++ b/.rootkeys	Fri Mar 12 15:47:50 2004 +0000
     1.3 @@ -484,6 +484,7 @@ 403cd194j2pyLqXD8FJ-ukvZzkPenw xen/inclu
     1.4  3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/hypervisor-ifs/hypervisor-if.h
     1.5  3ead095dE_VF-QA88rl_5cWYRWtRVQ xen/include/hypervisor-ifs/kbd.h
     1.6  3ddb79c2oRPrzClk3zbTkRHlpumzKA xen/include/hypervisor-ifs/network.h
     1.7 +4051db79512nOCGweabrFWO2M2h5ng xen/include/hypervisor-ifs/physdev.h
     1.8  404f3d2eR2Owk-ZcGOx9ULGHg3nrww xen/include/hypervisor-ifs/trace.h
     1.9  3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/vbd.h
    1.10  3ddb79c4qbCoOFHrv9sCGshbWzBVlQ xen/include/scsi/scsi.h
    1.11 @@ -609,6 +610,12 @@ 3e5a4e65RMGcuA-HCn3-wNx3fFQwdg xenolinux
    1.12  3e5a4e65MEvZhlr070sK5JsfAQlv7Q xenolinux-2.4.25-sparse/arch/xeno/kernel/ioport.c
    1.13  3e5a4e653U6cELGv528IxOLHvCq8iA xenolinux-2.4.25-sparse/arch/xeno/kernel/irq.c
    1.14  3e5a4e65muT6SU3ck47IP87Q7Ti5hA xenolinux-2.4.25-sparse/arch/xeno/kernel/ldt.c
    1.15 +4051db84bZeRX7a_Kh6VyyDuT5FOIg xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-dma.c
    1.16 +4051db89iiHs38tWGkoW_RukNyaBHw xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.c
    1.17 +4051db8dJYX86ZCLA-WfTW2dAyrehw xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.h
    1.18 +4051db91BenvDZEMZxQCGkQyJYoG5w xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-irq.c
    1.19 +4051db95N9N99FjsRwi49YKUNHWI8A xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-pc.c
    1.20 +4051db99fbdTHgCpjywPCp7vjLCe7Q xenolinux-2.4.25-sparse/arch/xeno/kernel/physirq.c
    1.21  3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ xenolinux-2.4.25-sparse/arch/xeno/kernel/process.c
    1.22  3e5a4e66tR-qJMLj3MppcKqmvuI2XQ xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c
    1.23  3e5a4e66fWSTagLGU2P8BGFGRjhDiw xenolinux-2.4.25-sparse/arch/xeno/kernel/signal.c
     2.1 --- a/tools/xc/lib/xc_physdev.c	Fri Mar 12 13:36:59 2004 +0000
     2.2 +++ b/tools/xc/lib/xc_physdev.c	Fri Mar 12 15:47:50 2004 +0000
     2.3 @@ -7,6 +7,8 @@
     2.4   * Copyright (c) 2004, K A Fraser (University of Cambridge)
     2.5   */
     2.6  
     2.7 +#include "xc_private.h"
     2.8 +
     2.9  int xc_physdev_pci_access_modify(int xc_handle,
    2.10                                   u64 domid,
    2.11                                   int bus,
     3.1 --- a/xen/common/domain.c	Fri Mar 12 13:36:59 2004 +0000
     3.2 +++ b/xen/common/domain.c	Fri Mar 12 15:47:50 2004 +0000
     3.3 @@ -592,6 +592,7 @@ int setup_guestos(struct task_struct *p,
     3.4      l1_pgentry_t *l1tab = NULL, *l1start = NULL;
     3.5      struct pfn_info *page = NULL;
     3.6  
     3.7 +    extern void physdev_init_dom0(struct task_struct *);
     3.8      extern void ide_probe_devices(xen_disk_info_t *);
     3.9      extern void scsi_probe_devices(xen_disk_info_t *);
    3.10      extern void cciss_probe_devices(xen_disk_info_t *);
     4.1 --- a/xen/common/physdev.c	Fri Mar 12 13:36:59 2004 +0000
     4.2 +++ b/xen/common/physdev.c	Fri Mar 12 15:47:50 2004 +0000
     4.3 @@ -35,15 +35,15 @@
     4.4  #include <xeno/pci.h>
     4.5  #include <xeno/irq.h>
     4.6  #include <xeno/event.h>
     4.7 -
     4.8  #include <asm/pci.h>
     4.9 -
    4.10 -
    4.11  #include <hypervisor-ifs/hypervisor-if.h>
    4.12 -#include <hypervisor-ifs/phys_dev.h>
    4.13 +#include <hypervisor-ifs/physdev.h>
    4.14  
    4.15 +#if 1
    4.16  #define DBG(_x...)
    4.17 -//#define DBG(_x...) printk(_x)
    4.18 +#else
    4.19 +#define DBG(_x...) printk(_x)
    4.20 +#endif
    4.21  
    4.22  #define ACC_READ  1
    4.23  #define ACC_WRITE 2
    4.24 @@ -59,7 +59,6 @@
    4.25  #define ST_ROM_ADDRESS   6   /* bit 6: is for rom address access */    
    4.26  #define ST_IRQ_DELIVERED 7   /* bit 7: waiting for end irq call */    
    4.27  
    4.28 -
    4.29  typedef struct _phys_dev_st
    4.30  {
    4.31      int flags;                       /* flags for access etc */
    4.32 @@ -84,7 +83,7 @@ static phys_dev_t *find_pdev(struct task
    4.33      phys_dev_t *t, *res = NULL;
    4.34      struct list_head *tmp;
    4.35  
    4.36 -    list_for_each(tmp, &p->dev_list)
    4.37 +    list_for_each(tmp, &p->pcidev_list)
    4.38      {
    4.39          t = list_entry(tmp,  phys_dev_t, node);
    4.40          if ( dev == t->dev )
    4.41 @@ -120,7 +119,7 @@ static void add_dev_to_task(struct task_
    4.42      pdev->dev = dev;
    4.43      pdev->flags = acc;
    4.44      pdev->state = 0;
    4.45 -    list_add(&pdev->node, &p->dev_list);
    4.46 +    list_add(&pdev->node, &p->pcidev_list);
    4.47  
    4.48      if ( acc == ACC_WRITE )
    4.49          pdev->owner = p;
    4.50 @@ -154,7 +153,7 @@ int physdev_pci_access_modify(
    4.51  
    4.52      DPRINTK("physdev_pci_access_modify: %02x:%02x:%02x\n", bus, dev, func);
    4.53  
    4.54 -    if ( (p = find_domain_by_id(dom) == NULL ) 
    4.55 +    if ( (p = find_domain_by_id(dom)) == NULL ) 
    4.56          return -ESRCH;
    4.57  
    4.58      /* Make the domain privileged. */
    4.59 @@ -181,7 +180,7 @@ int physdev_pci_access_modify(
    4.60      DPRINTK("  add R0 %02x:%02x:%02x\n", 0, 0, 0);
    4.61  
    4.62      /* Grant read access to all devices on the path to the root. */
    4.63 -    while ( tdev = pdev->bus->self; tdev != NULL; tdev = tdev->bus->self )
    4.64 +    for ( tdev = pdev->bus->self; tdev != NULL; tdev = tdev->bus->self )
    4.65      {
    4.66          add_dev_to_task(p, tdev, ACC_READ);
    4.67          DPRINTK("  add RO %02x:%02x:%02x\n", tdev->bus->number,
    4.68 @@ -559,13 +558,13 @@ static void phys_dev_interrupt(int irq, 
    4.69  
    4.70      //printk("owner %p\n", p);
    4.71  
    4.72 -    if ( test_bit(irq, &p->shared_info->virt_phys_irq) )
    4.73 +    if ( test_bit(irq, &p->shared_info->physirq_pend) )
    4.74      {
    4.75          printk("irq %d already delivered to guest\n", irq);
    4.76          return;
    4.77      }
    4.78      /* notify guest */
    4.79 -    set_bit(irq, &p->shared_info->virt_phys_irq);
    4.80 +    set_bit(irq, &p->shared_info->physirq_pend);
    4.81      set_bit(ST_IRQ_DELIVERED, &pdev->state);
    4.82      cpu_mask |= mark_guest_event(p, _EVENT_TIMER);
    4.83      guest_event_notify(cpu_mask);
    4.84 @@ -587,7 +586,7 @@ static void end_virt_irq (unsigned int i
    4.85  static long pci_request_irq(int irq)
    4.86  {
    4.87      int err;
    4.88 -    phys_dev_t *pdev, *t;
    4.89 +    phys_dev_t *pdev = NULL, *t;
    4.90      hw_irq_controller *new, *orig;
    4.91      struct list_head *tmp;
    4.92  
    4.93 @@ -595,7 +594,7 @@ static long pci_request_irq(int irq)
    4.94  
    4.95      /* find pdev */
    4.96  
    4.97 -    list_for_each(tmp, &current->dev_list)
    4.98 +    list_for_each(tmp, &current->pcidev_list)
    4.99      {
   4.100          t = list_entry(tmp,  phys_dev_t, node);
   4.101          if ( t->dev->irq == irq )
   4.102 @@ -605,7 +604,7 @@ static long pci_request_irq(int irq)
   4.103          }
   4.104      }
   4.105  
   4.106 -    if ( !pdev )
   4.107 +    if ( pdev == NULL )
   4.108      {
   4.109          printk("no device matching IRQ %d\n", irq);
   4.110          return -EINVAL;
   4.111 @@ -711,7 +710,7 @@ static long pci_finished_irq(int irq)
   4.112          return -EINVAL;
   4.113      }
   4.114  
   4.115 -    if ( test_bit(irq, &current->shared_info->virt_phys_irq) )
   4.116 +    if ( test_bit(irq, &current->shared_info->physirq_pend) )
   4.117      {
   4.118          printk("finished_irq called for un-acknowleged irq %d\n", irq);        
   4.119          return -EINVAL;
   4.120 @@ -728,54 +727,53 @@ static long pci_finished_irq(int irq)
   4.121  /*
   4.122   * demux hypervisor call.
   4.123   */
   4.124 -long do_phys_dev_op(phys_dev_op_t *uop)
   4.125 +long do_physdev_op(physdev_op_t *uop)
   4.126  {
   4.127 -    phys_dev_op_t op;
   4.128 +    physdev_op_t op;
   4.129      long ret;
   4.130  
   4.131 -
   4.132      if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
   4.133          return -EFAULT;
   4.134  
   4.135      switch ( op.cmd )
   4.136      {
   4.137 -    case DEVOP_CFGREG_READ:
   4.138 +    case PHYSDEVOP_CFGREG_READ:
   4.139          ret = pci_cfgreg_read (op.u.cfg_read.seg, op.u.cfg_read.bus,
   4.140                                 op.u.cfg_read.dev, op.u.cfg_read.func,
   4.141                                 op.u.cfg_read.reg, op.u.cfg_read.len,
   4.142                                 &op.u.cfg_read.value);
   4.143          break;
   4.144  
   4.145 -    case DEVOP_CFGREG_WRITE:
   4.146 +    case PHYSDEVOP_CFGREG_WRITE:
   4.147          ret = pci_cfgreg_write (op.u.cfg_write.seg, op.u.cfg_write.bus,
   4.148                                  op.u.cfg_write.dev, op.u.cfg_write.func,
   4.149                                  op.u.cfg_write.reg, op.u.cfg_write.len,
   4.150                                  op.u.cfg_write.value);
   4.151          break;
   4.152  
   4.153 -    case DEVOP_FIND_IRQ:
   4.154 +    case PHYSDEVOP_FIND_IRQ:
   4.155          ret = pci_find_irq (op.u.find_irq.seg, op.u.find_irq.bus,
   4.156                              op.u.find_irq.dev, op.u.find_irq.func,
   4.157                              &op.u.find_irq.irq);
   4.158          break;
   4.159  
   4.160 -    case DEVOP_REQUEST_IRQ:
   4.161 +    case PHYSDEVOP_REQUEST_IRQ:
   4.162          ret = pci_request_irq (op.u.request_irq.irq);
   4.163          break;
   4.164  
   4.165 -    case DEVOP_FREE_IRQ:
   4.166 +    case PHYSDEVOP_FREE_IRQ:
   4.167          ret = pci_free_irq (op.u.free_irq.irq);
   4.168          break;
   4.169  
   4.170 -    case DEVOP_ENABLE_IRQ:
   4.171 +    case PHYSDEVOP_ENABLE_IRQ:
   4.172          ret = pci_enable_irq (op.u.enable_irq.irq);
   4.173          break;
   4.174  
   4.175 -    case DEVOP_DISABLE_IRQ:
   4.176 +    case PHYSDEVOP_DISABLE_IRQ:
   4.177          ret = pci_disable_irq (op.u.disable_irq.irq);
   4.178          break;
   4.179  
   4.180 -    case DEVOP_FINISHED_IRQ:
   4.181 +    case PHYSDEVOP_FINISHED_IRQ:
   4.182          ret = pci_finished_irq (op.u.finished_irq.irq);
   4.183          break;
   4.184  
   4.185 @@ -798,9 +796,7 @@ void physdev_init_dom0(struct task_struc
   4.186      struct pci_dev *dev;
   4.187      phys_dev_t *pdev;
   4.188  
   4.189 -    printk("Give Dom0 read access to all PCI devices\n");
   4.190 -
   4.191 -    INIT_LIST_HEAD(&p->dev_list);
   4.192 +    printk("Give DOM0 read access to all PCI devices\n");
   4.193  
   4.194      pci_for_each_dev(dev)
   4.195      {
   4.196 @@ -810,6 +806,6 @@ void physdev_init_dom0(struct task_struc
   4.197          pdev->flags = ACC_READ;
   4.198          pdev->state = 0;
   4.199          pdev->owner = p;
   4.200 -        list_add(&pdev->node, &p->dev_list);
   4.201 +        list_add(&pdev->node, &p->pcidev_list);
   4.202  	}    
   4.203  }
     5.1 --- a/xen/drivers/pci/pci.c	Fri Mar 12 13:36:59 2004 +0000
     5.2 +++ b/xen/drivers/pci/pci.c	Fri Mar 12 15:47:50 2004 +0000
     5.3 @@ -13,21 +13,14 @@
     5.4  #include <xeno/sched.h>
     5.5  #include <xeno/module.h>
     5.6  #include <xeno/types.h>
     5.7 -/*#include <xeno/kernel.h>*/
     5.8  #include <xeno/pci.h>
     5.9 -/*#include <xeno/string.h>*/
    5.10  #include <xeno/init.h>
    5.11  #include <xeno/slab.h>
    5.12  #include <xeno/ioport.h>
    5.13  #include <xeno/spinlock.h>
    5.14 -/*#include <xeno/pm.h>*/
    5.15 -/*#include <xeno/kmod.h>*/		/* for hotplug_path */
    5.16 -/*#include <xeno/bitops.h>*/
    5.17  #include <xeno/delay.h>
    5.18  #include <xeno/cache.h>
    5.19 -
    5.20  #include <asm/page.h>
    5.21 -/*#include <asm/dma.h>*/	/* isa_dma_bridge_buggy */
    5.22  
    5.23  #undef DEBUG
    5.24  
    5.25 @@ -1258,6 +1251,10 @@ struct pci_bus * __devinit pci_add_new_b
    5.26  		child->resource[i]->name = child->name;
    5.27  	}
    5.28  
    5.29 +	DBG("pci_add_new_bus(nr=%x,devfn=%02x(%02x:%x),parent=%x)\n",
    5.30 +	    busnr, dev->devfn, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
    5.31 +	    parent->number);
    5.32 +
    5.33  	return child;
    5.34  }
    5.35  
    5.36 @@ -2111,6 +2108,19 @@ void __devinit  pci_init(void)
    5.37  
    5.38  	pci_for_each_dev(dev) {
    5.39  		pci_fixup_device(PCI_FIXUP_FINAL, dev);
    5.40 +#ifdef DEBUG
    5.41 +		printk("PCI: %p %02x:%02x:%02x\n", dev,
    5.42 +		       dev->bus ? dev->bus->number : 0xffffffff, 
    5.43 +		       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
    5.44 +		if (dev->bus) {
    5.45 +			printk(" s=%p ", dev->bus->self);
    5.46 +			if ( dev->bus->self )
    5.47 +				printk(" %02x:%02x)",
    5.48 +				       PCI_SLOT(dev->bus->self->devfn),
    5.49 +				       PCI_FUNC(dev->bus->self->devfn));
    5.50 +			printk("\n");
    5.51 +		}
    5.52 +#endif /* DEBUG */
    5.53  	}
    5.54  
    5.55  #ifdef CONFIG_PM
     6.1 --- a/xen/include/asm-i386/pci.h	Fri Mar 12 13:36:59 2004 +0000
     6.2 +++ b/xen/include/asm-i386/pci.h	Fri Mar 12 15:47:50 2004 +0000
     6.3 @@ -19,6 +19,11 @@ extern unsigned long pci_mem_start;
     6.4  #define PCIBIOS_MIN_IO		0x1000
     6.5  #define PCIBIOS_MIN_MEM		(pci_mem_start)
     6.6  
     6.7 +extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg,
     6.8 +                              int len, u32 *value);
     6.9 +extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg,
    6.10 +                               int len, u32 value);
    6.11 +
    6.12  void pcibios_set_master(struct pci_dev *dev);
    6.13  void pcibios_penalize_isa_irq(int irq);
    6.14  struct irq_routing_table *pcibios_get_irq_routing_table(void);
     7.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h	Fri Mar 12 13:36:59 2004 +0000
     7.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h	Fri Mar 12 15:47:50 2004 +0000
     7.3 @@ -208,6 +208,20 @@ typedef struct dom0_physinfo_st
     7.4      unsigned long free_pages;
     7.5  } dom0_physinfo_t;
     7.6  
     7.7 +/* 
     7.8 + * Allow a domain access to a physical PCI device
     7.9 + */
    7.10 +#define DOM0_PCIDEV_ACCESS    23
    7.11 +typedef struct dom0_pcidev_access_st
    7.12 +{
    7.13 +    /* IN variables. */
    7.14 +    domid_t      domain;
    7.15 +    int          bus; 
    7.16 +    int          dev;
    7.17 +    int          func; 
    7.18 +    int          enable;
    7.19 +} dom0_pcidev_access_t;
    7.20 +
    7.21  typedef struct dom0_op_st
    7.22  {
    7.23      unsigned long cmd;
    7.24 @@ -232,6 +246,7 @@ typedef struct dom0_op_st
    7.25  	dom0_pincpudomain_t     pincpudomain;
    7.26          dom0_gettbufs_t         gettbufs;
    7.27          dom0_physinfo_t         physinfo;
    7.28 +        dom0_pcidev_access_t    pcidev_access;
    7.29      } u;
    7.30  } dom0_op_t;
    7.31  
     8.1 --- a/xen/include/hypervisor-ifs/hypervisor-if.h	Fri Mar 12 13:36:59 2004 +0000
     8.2 +++ b/xen/include/hypervisor-ifs/hypervisor-if.h	Fri Mar 12 15:47:50 2004 +0000
     8.3 @@ -38,6 +38,7 @@
     8.4  #define __HYPERVISOR_event_channel_op     21
     8.5  #define __HYPERVISOR_xen_version          22
     8.6  #define __HYPERVISOR_console_io           23
     8.7 +#define __HYPERVISOR_physdev_op           24
     8.8  
     8.9  /*
    8.10   * MULTICALLS
    8.11 @@ -58,27 +59,30 @@
    8.12   */
    8.13  
    8.14  /* Events that a guest OS may receive from the hypervisor. */
    8.15 -#define EVENT_BLKDEV   0x01 /* A block device response has been queued. */
    8.16 -#define EVENT_TIMER    0x02 /* A timeout has been updated. */
    8.17 -#define EVENT_DIE      0x04 /* OS is about to be killed. Clean up please! */
    8.18 -#define EVENT_DEBUG    0x08 /* Request guest to dump debug info (gross!) */
    8.19 -#define EVENT_NET      0x10 /* There are packets for transmission. */
    8.20 -#define EVENT_PS2      0x20 /* PS/2 keyboard or mouse event(s) */
    8.21 -#define EVENT_STOP     0x40 /* Prepare for stopping and possible pickling */
    8.22 -#define EVENT_EVTCHN   0x80 /* Event pending on an event channel */
    8.23 +#define EVENT_BLKDEV   0x01  /* A block device response has been queued. */
    8.24 +#define EVENT_TIMER    0x02  /* A timeout has been updated. */
    8.25 +#define EVENT_DIE      0x04  /* OS is about to be killed. Clean up please! */
    8.26 +#define EVENT_DEBUG    0x08  /* Request guest to dump debug info (gross!) */
    8.27 +#define EVENT_NET      0x10  /* There are packets for transmission. */
    8.28 +#define EVENT_PS2      0x20  /* PS/2 keyboard or mouse event(s) */
    8.29 +#define EVENT_STOP     0x40  /* Prepare for stopping and possible pickling */
    8.30 +#define EVENT_EVTCHN   0x80  /* Event pending on an event channel */
    8.31  #define EVENT_VBD_UPD  0x100 /* Event to signal VBDs should be reprobed */
    8.32 +#define EVENT_CONSOLE  0x200 /* This is only for domain-0 initial console. */
    8.33 +#define EVENT_PHYSIRQ  0x400 /* Event to signal pending physical IRQs. */
    8.34  
    8.35  /* Bit offsets, as opposed to the above masks. */
    8.36 -#define _EVENT_BLKDEV   0
    8.37 -#define _EVENT_TIMER    1
    8.38 -#define _EVENT_DIE      2
    8.39 -#define _EVENT_DEBUG    3
    8.40 -#define _EVENT_NET      4
    8.41 -#define _EVENT_PS2      5
    8.42 -#define _EVENT_STOP     6
    8.43 -#define _EVENT_EVTCHN   7
    8.44 -#define _EVENT_VBD_UPD  8
    8.45 -#define _EVENT_CONSOLE  9 /* This is only for domain-0 initial console. */
    8.46 +#define _EVENT_BLKDEV    0
    8.47 +#define _EVENT_TIMER     1
    8.48 +#define _EVENT_DIE       2
    8.49 +#define _EVENT_DEBUG     3
    8.50 +#define _EVENT_NET       4
    8.51 +#define _EVENT_PS2       5
    8.52 +#define _EVENT_STOP      6
    8.53 +#define _EVENT_EVTCHN    7
    8.54 +#define _EVENT_VBD_UPD   8
    8.55 +#define _EVENT_CONSOLE   9
    8.56 +#define _EVENT_PHYSIRQ  10
    8.57  
    8.58  
    8.59  /*
    8.60 @@ -205,6 +209,9 @@ typedef struct shared_info_st {
    8.61      u32 event_channel_disc[32];
    8.62      u32 event_channel_disc_sel;
    8.63  
    8.64 +    /* Bitmask of physical IRQ lines that are pending for this domain. */
    8.65 +    unsigned long physirq_pend;
    8.66 +
    8.67      /*
    8.68       * Time: The following abstractions are exposed: System Time, Clock Time,
    8.69       * Domain Virtual Time. Domains can access Cycle counter time directly.
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/include/hypervisor-ifs/physdev.h	Fri Mar 12 15:47:50 2004 +0000
     9.3 @@ -0,0 +1,110 @@
     9.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
     9.5 + ****************************************************************************
     9.6 + * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
     9.7 + ****************************************************************************
     9.8 + *
     9.9 + *        File: physdev.h
    9.10 + *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
    9.11 + *        Date: Feb 2004
    9.12 + * 
    9.13 + * Description: Interface for domains to access physical devices on the PCI bus
    9.14 + */
    9.15 +
    9.16 +#ifndef __HYPERVISOR_IFS_PHYSDEV_H__
    9.17 +#define __HYPERVISOR_IFS_PHYSDEV_H__
    9.18 +
    9.19 +/*
    9.20 + * Commands to HYPERVISOR_physdev_op()
    9.21 + */
    9.22 +#define PHYSDEVOP_CFGREG_READ   0
    9.23 +#define PHYSDEVOP_CFGREG_WRITE  1
    9.24 +#define PHYSDEVOP_FIND_IRQ      2
    9.25 +#define PHYSDEVOP_REQUEST_IRQ   3
    9.26 +#define PHYSDEVOP_FREE_IRQ      4
    9.27 +#define PHYSDEVOP_ENABLE_IRQ    5
    9.28 +#define PHYSDEVOP_DISABLE_IRQ   6
    9.29 +#define PHYSDEVOP_FINISHED_IRQ  7
    9.30 +
    9.31 +/* read pci config */
    9.32 +typedef struct physdevop_cfgreg_read_st
    9.33 +{
    9.34 +    int seg;        /* IN */
    9.35 +    int bus;        /* IN */
    9.36 +    int dev;        /* IN */
    9.37 +    int func;       /* IN */
    9.38 +    int reg;        /* IN  */
    9.39 +    int len;        /* IN  */
    9.40 +    u32 value;      /* OUT */
    9.41 +} physdevop_cfgreg_read_t;
    9.42 +
    9.43 +/* write pci config */
    9.44 +typedef struct physdevop_cfgred_write_st
    9.45 +{
    9.46 +    int seg;        /* IN */
    9.47 +    int bus;        /* IN */
    9.48 +    int dev;        /* IN */
    9.49 +    int func;       /* IN */
    9.50 +    int reg;        /* IN */
    9.51 +    int len;        /* IN */
    9.52 +    u32 value;      /* IN */
    9.53 +} physdevop_cfgreg_write_t;
    9.54 +
    9.55 +/* get the real IRQ for a device */
    9.56 +typedef struct physdevop_find_irq_st
    9.57 +{
    9.58 +    int seg;      /* IN */
    9.59 +    int bus;      /* IN */
    9.60 +    int dev;      /* IN */
    9.61 +    int func;     /* IN */
    9.62 +    u32 irq;      /* OUT */
    9.63 +} physdevop_find_irq_t;
    9.64 +
    9.65 +/* request physical IRQ to be routed to guest */
    9.66 +typedef struct physdevop_request_irq_st
    9.67 +{
    9.68 +    u32 irq;      /* IN */
    9.69 +} physdevop_request_irq_t;
    9.70 +
    9.71 +/* stop routing physical interrupts to guest */
    9.72 +typedef struct physdevop_free_irq_st
    9.73 +{
    9.74 +    u32 irq;      /* IN */
    9.75 +} physdevop_free_irq_t;
    9.76 +
    9.77 +/* enable IRQ for the caller  */
    9.78 +typedef struct physdevop_enable_irq_st
    9.79 +{
    9.80 +    u32 irq;      /* IN */
    9.81 +} physdevop_enable_irq_t;
    9.82 +
    9.83 +/* disable interrupts */
    9.84 +typedef struct physdevop_disable_irq_st
    9.85 +{
    9.86 +    u32 irq;      /* IN */
    9.87 +} physdevop_disable_irq_t;
    9.88 +
    9.89 +typedef struct physdevop_finished_irq_st
    9.90 +{
    9.91 +    u32 irq;      /* IN */
    9.92 +} physdevop_finished_irq_t;
    9.93 +
    9.94 +
    9.95 +typedef struct _physdev_op_st 
    9.96 +{
    9.97 +    unsigned long cmd;
    9.98 +
    9.99 +    /* command parameters */
   9.100 +    union
   9.101 +    {
   9.102 +        physdevop_cfgreg_read_t  cfg_read;
   9.103 +        physdevop_cfgreg_write_t cfg_write;
   9.104 +        physdevop_find_irq_t     find_irq;
   9.105 +        physdevop_request_irq_t  request_irq;
   9.106 +        physdevop_free_irq_t     free_irq;
   9.107 +        physdevop_enable_irq_t   enable_irq;
   9.108 +        physdevop_disable_irq_t  disable_irq;
   9.109 +        physdevop_finished_irq_t finished_irq;
   9.110 +    } u;
   9.111 +} physdev_op_t;
   9.112 +
   9.113 +#endif /* __HYPERVISOR_IFS_PHYSDEV_H__ */
    10.1 --- a/xen/include/xeno/sched.h	Fri Mar 12 13:36:59 2004 +0000
    10.2 +++ b/xen/include/xeno/sched.h	Fri Mar 12 15:47:50 2004 +0000
    10.3 @@ -152,6 +152,10 @@ struct task_struct
    10.4      unsigned int     max_event_channel;
    10.5      spinlock_t       event_channel_lock;
    10.6  
    10.7 +    /* Physical I/O */
    10.8 +    spinlock_t       pcidev_lock;
    10.9 +    struct list_head pcidev_list;
   10.10 +
   10.11      unsigned long flags;
   10.12  
   10.13      atomic_t refcnt;
    11.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/config.in	Fri Mar 12 13:36:59 2004 +0000
    11.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/config.in	Fri Mar 12 15:47:50 2004 +0000
    11.3 @@ -104,6 +104,12 @@ comment 'General setup'
    11.4  
    11.5  bool 'Networking support' CONFIG_NET
    11.6  
    11.7 +bool 'PCI support' CONFIG_PCI
    11.8 +if [ "$CONFIG_PCI" = "y" ]; then
    11.9 +   tristate '    3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
   11.10 +fi
   11.11 +source drivers/pci/Config.in
   11.12 +
   11.13  bool 'System V IPC' CONFIG_SYSVIPC
   11.14  bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
   11.15  bool 'Sysctl support' CONFIG_SYSCTL
    12.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/defconfig	Fri Mar 12 13:36:59 2004 +0000
    12.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/defconfig	Fri Mar 12 15:47:50 2004 +0000
    12.3 @@ -55,6 +55,8 @@ CONFIG_NOHIGHMEM=y
    12.4  # General setup
    12.5  #
    12.6  CONFIG_NET=y
    12.7 +# CONFIG_PCI is not set
    12.8 +# CONFIG_PCI_NAMES is not set
    12.9  CONFIG_SYSVIPC=y
   12.10  # CONFIG_BSD_PROCESS_ACCT is not set
   12.11  CONFIG_SYSCTL=y
    13.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c	Fri Mar 12 13:36:59 2004 +0000
    13.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/block/xl_block.c	Fri Mar 12 15:47:50 2004 +0000
    13.3 @@ -18,9 +18,9 @@
    13.4  
    13.5  typedef unsigned char byte; /* from linux/ide.h */
    13.6  
    13.7 -#define XLBLK_RESPONSE_IRQ _EVENT_BLKDEV
    13.8 -#define XLBLK_UPDATE_IRQ   _EVENT_VBD_UPD
    13.9 -#define DEBUG_IRQ          _EVENT_DEBUG 
   13.10 +#define XLBLK_RESPONSE_IRQ HYPEREVENT_IRQ(_EVENT_BLKDEV)
   13.11 +#define XLBLK_UPDATE_IRQ   HYPEREVENT_IRQ(_EVENT_VBD_UPD)
   13.12 +#define DEBUG_IRQ          HYPEREVENT_IRQ(_EVENT_DEBUG)
   13.13  
   13.14  #define STATE_ACTIVE    0
   13.15  #define STATE_SUSPENDED 1
    14.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c	Fri Mar 12 13:36:59 2004 +0000
    14.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c	Fri Mar 12 15:47:50 2004 +0000
    14.3 @@ -446,7 +446,8 @@ int __init xeno_con_init(void)
    14.4      }
    14.5      else
    14.6      {
    14.7 -        request_irq(_EVENT_CONSOLE, control_irq, 0, "console", NULL);
    14.8 +        request_irq(HYPEREVENT_IRQ(_EVENT_CONSOLE), 
    14.9 +                    control_irq, 0, "console", NULL);
   14.10          control_irq(0, NULL, NULL); /* kickstart the console */
   14.11      }
   14.12  
    15.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c	Fri Mar 12 13:36:59 2004 +0000
    15.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c	Fri Mar 12 15:47:50 2004 +0000
    15.3 @@ -21,6 +21,7 @@
    15.4  #include <linux/devfs_fs_kernel.h>
    15.5  #include <linux/stat.h>
    15.6  #include <linux/poll.h>
    15.7 +#include <linux/irq.h>
    15.8  #include <asm/evtchn.h>
    15.9  
   15.10  /* NB. This must be shared amongst drivers if more things go in /dev/xen */
   15.11 @@ -454,7 +455,8 @@ static int __init init_module(void)
   15.12      /* (DEVFS) automatically destroy the symlink with its destination. */
   15.13      devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
   15.14  
   15.15 -    err = request_irq(_EVENT_EVTCHN, evtchn_interrupt, 0, "evtchn", NULL);
   15.16 +    err = request_irq(HYPEREVENT_IRQ(_EVENT_EVTCHN),
   15.17 +                      evtchn_interrupt, 0, "evtchn", NULL);
   15.18      if ( err != 0 )
   15.19      {
   15.20          printk(KERN_ALERT "Could not allocate evtchn receive interrupt\n");
   15.21 @@ -471,7 +473,7 @@ static int __init init_module(void)
   15.22  
   15.23  static void cleanup_module(void)
   15.24  {
   15.25 -    free_irq(_EVENT_EVTCHN, NULL);
   15.26 +    free_irq(HYPEREVENT_IRQ(_EVENT_EVTCHN), NULL);
   15.27      misc_deregister(&evtchn_miscdev);
   15.28  }
   15.29  
    16.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/network/network.c	Fri Mar 12 13:36:59 2004 +0000
    16.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/network/network.c	Fri Mar 12 15:47:50 2004 +0000
    16.3 @@ -25,8 +25,6 @@
    16.4  #include <net/sock.h>
    16.5  #include <net/pkt_sched.h>
    16.6  
    16.7 -#define NET_IRQ _EVENT_NET
    16.8 -
    16.9  #define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */
   16.10  
   16.11  static void network_interrupt(int irq, void *dev_id, struct pt_regs *ptregs);
   16.12 @@ -546,7 +544,7 @@ static int __init init_module(void)
   16.13      if ( start_info.flags & SIF_INITDOMAIN )
   16.14          (void)register_inetaddr_notifier(&notifier_inetdev);
   16.15  
   16.16 -    err = request_irq(NET_IRQ, network_interrupt, 
   16.17 +    err = request_irq(HYPEREVENT_IRQ(_EVENT_NET), network_interrupt, 
   16.18                        SA_SAMPLE_RANDOM, "network", NULL);
   16.19      if ( err )
   16.20      {
   16.21 @@ -554,8 +552,8 @@ static int __init init_module(void)
   16.22          goto fail;
   16.23      }
   16.24      
   16.25 -    err = request_irq(_EVENT_DEBUG, dbg_network_int, SA_SHIRQ, "net_dbg", 
   16.26 -                      &dbg_network_int);
   16.27 +    err = request_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), dbg_network_int, 
   16.28 +                      SA_SHIRQ, "net_dbg", &dbg_network_int);
   16.29      if ( err )
   16.30          printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n");
   16.31  
    17.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/Makefile	Fri Mar 12 13:36:59 2004 +0000
    17.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/Makefile	Fri Mar 12 15:47:50 2004 +0000
    17.3 @@ -10,6 +10,10 @@ export-objs     := i386_ksyms.o
    17.4  
    17.5  obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o  \
    17.6  		ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \
    17.7 -		i386_ksyms.o i387.o hypervisor.o
    17.8 +		i386_ksyms.o i387.o hypervisor.o physirq.o pci-dma.o
    17.9 +
   17.10 +ifdef CONFIG_PCI
   17.11 +obj-y	+= pci-i386.o pci-pc.o pci-irq.o
   17.12 +endif
   17.13  
   17.14  include $(TOPDIR)/Rules.make
    18.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/hypervisor.c	Fri Mar 12 13:36:59 2004 +0000
    18.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/hypervisor.c	Fri Mar 12 15:47:50 2004 +0000
    18.3 @@ -37,13 +37,14 @@ void do_hypervisor_callback(struct pt_re
    18.4              "   sub  $4,%%esp                      ;"
    18.5              "   jmp  2f                            ;"
    18.6              "1: btrl %%eax,%0                      ;" /* clear bit     */
    18.7 +            "   add  %2,%%eax                      ;"
    18.8              "   mov  %%eax,(%%esp)                 ;"
    18.9              "   call do_IRQ                        ;" /* do_IRQ(event) */
   18.10              "2: bsfl %0,%%eax                      ;" /* %eax == bit # */
   18.11              "   jnz  1b                            ;"
   18.12              "   add  $8,%%esp                      ;"
   18.13              /* we use %ebx because it is callee-saved */
   18.14 -            : : "b" (events), "r" (regs)
   18.15 +            : : "b" (events), "r" (regs), "i" (HYPEREVENT_IRQ_BASE)
   18.16              /* clobbered by callback function calls */
   18.17              : "eax", "ecx", "edx", "memory" ); 
   18.18  
   18.19 @@ -54,41 +55,40 @@ void do_hypervisor_callback(struct pt_re
   18.20      while ( shared->events );
   18.21  }
   18.22  
   18.23 -
   18.24 -
   18.25  /*
   18.26   * Define interface to generic handling in irq.c
   18.27   */
   18.28  
   18.29  static void shutdown_hypervisor_event(unsigned int irq)
   18.30  {
   18.31 -    clear_bit(irq, &event_mask);
   18.32 -    clear_bit(irq, &HYPERVISOR_shared_info->events_mask);
   18.33 +    clear_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
   18.34 +    clear_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
   18.35  }
   18.36  
   18.37  static void enable_hypervisor_event(unsigned int irq)
   18.38  {
   18.39 -    set_bit(irq, &event_mask);
   18.40 -    set_bit(irq, &HYPERVISOR_shared_info->events_mask);
   18.41 -    if ( test_bit(EVENTS_MASTER_ENABLE_BIT, 
   18.42 +    set_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
   18.43 +    set_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
   18.44 +    if ( test_bit(EVENTS_MASTER_ENABLE_BIT,
   18.45                    &HYPERVISOR_shared_info->events_mask) )
   18.46          do_hypervisor_callback(NULL);
   18.47  }
   18.48  
   18.49  static void disable_hypervisor_event(unsigned int irq)
   18.50  {
   18.51 -    clear_bit(irq, &event_mask);
   18.52 -    clear_bit(irq, &HYPERVISOR_shared_info->events_mask);
   18.53 +    clear_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
   18.54 +    clear_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
   18.55  }
   18.56  
   18.57  static void ack_hypervisor_event(unsigned int irq)
   18.58  {
   18.59 -    if ( !(event_mask & (1<<irq)) )
   18.60 +    int ev = HYPEREVENT_FROM_IRQ(irq);
   18.61 +    if ( !(event_mask & (1<<ev)) )
   18.62      {
   18.63 -        printk("Unexpected hypervisor event %d\n", irq);
   18.64 +        printk("Unexpected hypervisor event %d\n", ev);
   18.65          atomic_inc(&irq_err_count);
   18.66      }
   18.67 -    set_bit(irq, &HYPERVISOR_shared_info->events_mask);
   18.68 +    set_bit(ev, &HYPERVISOR_shared_info->events_mask);
   18.69  }
   18.70  
   18.71  static unsigned int startup_hypervisor_event(unsigned int irq)
   18.72 @@ -116,11 +116,14 @@ void __init init_IRQ(void)
   18.73  {
   18.74      int i;
   18.75  
   18.76 -    for ( i = 0; i < NR_IRQS; i++ )
   18.77 +    for ( i = 0; i < NR_HYPEREVENT_IRQS; i++ )
   18.78      {
   18.79 -        irq_desc[i].status  = IRQ_DISABLED;
   18.80 -        irq_desc[i].action  = 0;
   18.81 -        irq_desc[i].depth   = 1;
   18.82 -        irq_desc[i].handler = &hypervisor_irq_type;
   18.83 +        irq_desc[i + HYPEREVENT_IRQ_BASE].status  = IRQ_DISABLED;
   18.84 +        irq_desc[i + HYPEREVENT_IRQ_BASE].action  = 0;
   18.85 +        irq_desc[i + HYPEREVENT_IRQ_BASE].depth   = 1;
   18.86 +        irq_desc[i + HYPEREVENT_IRQ_BASE].handler = &hypervisor_irq_type;
   18.87      }
   18.88 +
   18.89 +    /* Also initialise the physical IRQ handlers. */
   18.90 +    physirq_init();
   18.91  }
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-dma.c	Fri Mar 12 15:47:50 2004 +0000
    19.3 @@ -0,0 +1,37 @@
    19.4 +/*
    19.5 + * Dynamic DMA mapping support.
    19.6 + *
    19.7 + * On i386 there is no hardware dynamic DMA address translation,
    19.8 + * so consistent alloc/free are merely page allocation/freeing.
    19.9 + * The rest of the dynamic DMA mapping interface is implemented
   19.10 + * in asm/pci.h.
   19.11 + */
   19.12 +
   19.13 +#include <linux/types.h>
   19.14 +#include <linux/mm.h>
   19.15 +#include <linux/string.h>
   19.16 +#include <linux/pci.h>
   19.17 +#include <asm/io.h>
   19.18 +
   19.19 +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
   19.20 +			   dma_addr_t *dma_handle)
   19.21 +{
   19.22 +	void *ret;
   19.23 +	int gfp = GFP_ATOMIC;
   19.24 +
   19.25 +	if (hwdev == NULL || ((u32)hwdev->dma_mask < 0xffffffff))
   19.26 +		gfp |= GFP_DMA;
   19.27 +	ret = (void *)__get_free_pages(gfp, get_order(size));
   19.28 +
   19.29 +	if (ret != NULL) {
   19.30 +		memset(ret, 0, size);
   19.31 +		*dma_handle = virt_to_bus(ret);
   19.32 +	}
   19.33 +	return ret;
   19.34 +}
   19.35 +
   19.36 +void pci_free_consistent(struct pci_dev *hwdev, size_t size,
   19.37 +			 void *vaddr, dma_addr_t dma_handle)
   19.38 +{
   19.39 +	free_pages((unsigned long)vaddr, get_order(size));
   19.40 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.c	Fri Mar 12 15:47:50 2004 +0000
    20.3 @@ -0,0 +1,410 @@
    20.4 +/*
    20.5 + *	Low-Level PCI Access for i386 machines
    20.6 + *
    20.7 + * Copyright 1993, 1994 Drew Eckhardt
    20.8 + *      Visionary Computing
    20.9 + *      (Unix and Linux consulting and custom programming)
   20.10 + *      Drew@Colorado.EDU
   20.11 + *      +1 (303) 786-7975
   20.12 + *
   20.13 + * Drew's work was sponsored by:
   20.14 + *	iX Multiuser Multitasking Magazine
   20.15 + *	Hannover, Germany
   20.16 + *	hm@ix.de
   20.17 + *
   20.18 + * Copyright 1997--2000 Martin Mares <mj@ucw.cz>
   20.19 + *
   20.20 + * For more information, please consult the following manuals (look at
   20.21 + * http://www.pcisig.com/ for how to get them):
   20.22 + *
   20.23 + * PCI BIOS Specification
   20.24 + * PCI Local Bus Specification
   20.25 + * PCI to PCI Bridge Specification
   20.26 + * PCI System Design Guide
   20.27 + *
   20.28 + *
   20.29 + * CHANGELOG :
   20.30 + * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
   20.31 + *	Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
   20.32 + *
   20.33 + * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
   20.34 + *     Potter, potter@cao-vlsi.ibp.fr
   20.35 + *
   20.36 + * Jan 10, 1995 : Modified to store the information about configured pci
   20.37 + *      devices into a list, which can be accessed via /proc/pci by
   20.38 + *      Curtis Varner, cvarner@cs.ucr.edu
   20.39 + *
   20.40 + * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
   20.41 + *	Alpha version. Intel & UMC chipset support only.
   20.42 + *
   20.43 + * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
   20.44 + *	moved to drivers/pci/pci.c.
   20.45 + *
   20.46 + * Dec 7, 1996  : Added support for direct configuration access of boards
   20.47 + *      with Intel compatible access schemes (tsbogend@alpha.franken.de)
   20.48 + *
   20.49 + * Feb 3, 1997  : Set internal functions to static, save/restore flags
   20.50 + *	avoid dead locks reading broken PCI BIOS, werner@suse.de 
   20.51 + *
   20.52 + * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
   20.53 + *	(mj@atrey.karlin.mff.cuni.cz)
   20.54 + *
   20.55 + * May 7,  1997 : Added some missing cli()'s. [mj]
   20.56 + * 
   20.57 + * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
   20.58 + *      (paubert@iram.es)
   20.59 + *
   20.60 + * Aug 2,  1997 : Split to PCI BIOS handling and direct PCI access parts
   20.61 + *	and cleaned it up...     Martin Mares <mj@atrey.karlin.mff.cuni.cz>
   20.62 + *
   20.63 + * Feb 6,  1998 : No longer using BIOS to find devices and device classes. [mj]
   20.64 + *
   20.65 + * May 1,  1998 : Support for peer host bridges. [mj]
   20.66 + *
   20.67 + * Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space
   20.68 + *	can be accessed from interrupts even on SMP systems. [mj]
   20.69 + *
   20.70 + * August  1998 : Better support for peer host bridges and more paranoid
   20.71 + *	checks for direct hardware access. Ugh, this file starts to look as
   20.72 + *	a large gallery of common hardware bug workarounds (watch the comments)
   20.73 + *	-- the PCI specs themselves are sane, but most implementors should be
   20.74 + *	hit hard with \hammer scaled \magstep5. [mj]
   20.75 + *
   20.76 + * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
   20.77 + *
   20.78 + * Feb 8,  1999 : Added UM8886BF I/O address fixup. [mj]
   20.79 + *
   20.80 + * August  1999 : New resource management and configuration access stuff. [mj]
   20.81 + *
   20.82 + * Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges.
   20.83 + *		  Based on ideas by Chris Frantz and David Hinds. [mj]
   20.84 + *
   20.85 + * Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi
   20.86 + *		  for a lot of patience during testing. [mj]
   20.87 + *
   20.88 + * Oct  8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj]
   20.89 + */
   20.90 +
   20.91 +#include <linux/types.h>
   20.92 +#include <linux/kernel.h>
   20.93 +#include <linux/pci.h>
   20.94 +#include <linux/init.h>
   20.95 +#include <linux/ioport.h>
   20.96 +#include <linux/errno.h>
   20.97 +
   20.98 +#include "pci-i386.h"
   20.99 +
  20.100 +void
  20.101 +pcibios_update_resource(struct pci_dev *dev, struct resource *root,
  20.102 +			struct resource *res, int resource)
  20.103 +{
  20.104 +    u32 new, check;
  20.105 +    int reg;
  20.106 +
  20.107 +    new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
  20.108 +    if (resource < 6) {
  20.109 +        reg = PCI_BASE_ADDRESS_0 + 4*resource;
  20.110 +    } else if (resource == PCI_ROM_RESOURCE) {
  20.111 +        res->flags |= PCI_ROM_ADDRESS_ENABLE;
  20.112 +        new |= PCI_ROM_ADDRESS_ENABLE;
  20.113 +        reg = dev->rom_base_reg;
  20.114 +    } else {
  20.115 +        /* Somebody might have asked allocation of a non-standard resource */
  20.116 +        return;
  20.117 +    }
  20.118 +	
  20.119 +    pci_write_config_dword(dev, reg, new);
  20.120 +    pci_read_config_dword(dev, reg, &check);
  20.121 +    if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
  20.122 +        printk(KERN_ERR "PCI: Error while updating region "
  20.123 +               "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
  20.124 +               new, check);
  20.125 +    }
  20.126 +}
  20.127 +
  20.128 +/*
  20.129 + * We need to avoid collisions with `mirrored' VGA ports
  20.130 + * and other strange ISA hardware, so we always want the
  20.131 + * addresses to be allocated in the 0x000-0x0ff region
  20.132 + * modulo 0x400.
  20.133 + *
  20.134 + * Why? Because some silly external IO cards only decode
  20.135 + * the low 10 bits of the IO address. The 0x00-0xff region
  20.136 + * is reserved for motherboard devices that decode all 16
  20.137 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
  20.138 + * but we want to try to avoid allocating at 0x2900-0x2bff
  20.139 + * which might have be mirrored at 0x0100-0x03ff..
  20.140 + */
  20.141 +void
  20.142 +pcibios_align_resource(void *data, struct resource *res,
  20.143 +		       unsigned long size, unsigned long align)
  20.144 +{
  20.145 +    if (res->flags & IORESOURCE_IO) {
  20.146 +        unsigned long start = res->start;
  20.147 +
  20.148 +        if (start & 0x300) {
  20.149 +            start = (start + 0x3ff) & ~0x3ff;
  20.150 +            res->start = start;
  20.151 +        }
  20.152 +    }
  20.153 +}
  20.154 +
  20.155 +
  20.156 +/*
  20.157 + *  Handle resources of PCI devices.  If the world were perfect, we could
  20.158 + *  just allocate all the resource regions and do nothing more.  It isn't.
  20.159 + *  On the other hand, we cannot just re-allocate all devices, as it would
  20.160 + *  require us to know lots of host bridge internals.  So we attempt to
  20.161 + *  keep as much of the original configuration as possible, but tweak it
  20.162 + *  when it's found to be wrong.
  20.163 + *
  20.164 + *  Known BIOS problems we have to work around:
  20.165 + *	- I/O or memory regions not configured
  20.166 + *	- regions configured, but not enabled in the command register
  20.167 + *	- bogus I/O addresses above 64K used
  20.168 + *	- expansion ROMs left enabled (this may sound harmless, but given
  20.169 + *	  the fact the PCI specs explicitly allow address decoders to be
  20.170 + *	  shared between expansion ROMs and other resource regions, it's
  20.171 + *	  at least dangerous)
  20.172 + *
  20.173 + *  Our solution:
  20.174 + *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
  20.175 + *	    This gives us fixed barriers on where we can allocate.
  20.176 + *	(2) Allocate resources for all enabled devices.  If there is
  20.177 + *	    a collision, just mark the resource as unallocated. Also
  20.178 + *	    disable expansion ROMs during this step.
  20.179 + *	(3) Try to allocate resources for disabled devices.  If the
  20.180 + *	    resources were assigned correctly, everything goes well,
  20.181 + *	    if they weren't, they won't disturb allocation of other
  20.182 + *	    resources.
  20.183 + *	(4) Assign new addresses to resources which were either
  20.184 + *	    not configured at all or misconfigured.  If explicitly
  20.185 + *	    requested by the user, configure expansion ROM address
  20.186 + *	    as well.
  20.187 + */
  20.188 +
  20.189 +static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
  20.190 +{
  20.191 +    struct list_head *ln;
  20.192 +    struct pci_bus *bus;
  20.193 +    struct pci_dev *dev;
  20.194 +    int idx;
  20.195 +    struct resource *r, *pr;
  20.196 +
  20.197 +    /* Depth-First Search on bus tree */
  20.198 +    for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
  20.199 +        bus = pci_bus_b(ln);
  20.200 +        if ((dev = bus->self)) {
  20.201 +            printk("alloc bus res: %s\n", dev->slot_name);
  20.202 +            for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
  20.203 +                r = &dev->resource[idx];
  20.204 +                if (!r->start)
  20.205 +                {
  20.206 +                    printk("  res1: 0x%08lx-0x%08lx f=%lx\n",
  20.207 +                           r->start, r->end, r->flags);
  20.208 +
  20.209 +                    continue;
  20.210 +                }
  20.211 +                pr = pci_find_parent_resource(dev, r);
  20.212 +                if (!pr || request_resource(pr, r) < 0)
  20.213 +                    printk(KERN_ERR "PCI: Cannot allocate resource region %d "
  20.214 +                           "of bridge %s (%p)\n", idx, dev->slot_name, pr);
  20.215 +                printk("  res2: %08lx-%08lx f=%lx\n",
  20.216 +                       r->start, r->end, r->flags);
  20.217 +            }
  20.218 +        }
  20.219 +        pcibios_allocate_bus_resources(&bus->children);
  20.220 +    }
  20.221 +}
  20.222 +
  20.223 +static void __init pcibios_allocate_resources(int pass)
  20.224 +{
  20.225 +    struct pci_dev *dev;
  20.226 +    int idx, disabled;
  20.227 +    u16 command;
  20.228 +    struct resource *r, *pr;
  20.229 +
  20.230 +    pci_for_each_dev(dev) {
  20.231 +        pci_read_config_word(dev, PCI_COMMAND, &command);
  20.232 +        for(idx = 0; idx < 6; idx++) {
  20.233 +            r = &dev->resource[idx];
  20.234 +            if (r->parent)		/* Already allocated */
  20.235 +                continue;
  20.236 +            if (!r->start)		/* Address not assigned at all */
  20.237 +                continue;
  20.238 +            if (r->flags & IORESOURCE_IO)
  20.239 +                disabled = !(command & PCI_COMMAND_IO);
  20.240 +            else
  20.241 +                disabled = !(command & PCI_COMMAND_MEMORY);
  20.242 +            if (pass == disabled) {
  20.243 +                printk("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d) (%s)\n",
  20.244 +                       r->start, r->end, r->flags, disabled, pass, dev->slot_name);
  20.245 +                pr = pci_find_parent_resource(dev, r);
  20.246 +                if (!pr || request_resource(pr, r) < 0) {
  20.247 +                    printk(KERN_ERR "PCI: Cannot allocate resource region %d"
  20.248 +                           " of device %s (%p)\n", idx, dev->slot_name, pr);
  20.249 +                    /* We'll assign a new address later */
  20.250 +                    r->end -= r->start;
  20.251 +                    r->start = 0;
  20.252 +                }
  20.253 +            }
  20.254 +        }
  20.255 +        if (!pass) {
  20.256 +            r = &dev->resource[PCI_ROM_RESOURCE];
  20.257 +            if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
  20.258 +				/* Turn the ROM off, leave the resource region, but keep it unregistered. */
  20.259 +                u32 reg;
  20.260 +                printk("PCI: Switching off ROM of %s\n", dev->slot_name);
  20.261 +                r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
  20.262 +                pci_read_config_dword(dev, dev->rom_base_reg, &reg);
  20.263 +                pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
  20.264 +            }
  20.265 +        }
  20.266 +    }
  20.267 +}
  20.268 +
  20.269 +static void __init pcibios_assign_resources(void)
  20.270 +{
  20.271 +    struct pci_dev *dev;
  20.272 +    int idx;
  20.273 +    struct resource *r;
  20.274 +
  20.275 +    pci_for_each_dev(dev) {
  20.276 +        int class = dev->class >> 8;
  20.277 +
  20.278 +        /* Don't touch classless devices and host bridges */
  20.279 +        if (!class || class == PCI_CLASS_BRIDGE_HOST)
  20.280 +            continue;
  20.281 +
  20.282 +        for(idx=0; idx<6; idx++) {
  20.283 +            r = &dev->resource[idx];
  20.284 +
  20.285 +            /*
  20.286 +             *  Don't touch IDE controllers and I/O ports of video cards!
  20.287 +             */
  20.288 +            if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
  20.289 +                (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
  20.290 +                continue;
  20.291 +
  20.292 +            /*
  20.293 +             *  We shall assign a new address to this resource, either because
  20.294 +             *  the BIOS forgot to do so or because we have decided the old
  20.295 +             *  address was unusable for some reason.
  20.296 +             */
  20.297 +            if (!r->start && r->end)
  20.298 +                pci_assign_resource(dev, idx);
  20.299 +        }
  20.300 +
  20.301 +        if (pci_probe & PCI_ASSIGN_ROMS) {
  20.302 +            r = &dev->resource[PCI_ROM_RESOURCE];
  20.303 +            r->end -= r->start;
  20.304 +            r->start = 0;
  20.305 +            if (r->end)
  20.306 +                pci_assign_resource(dev, PCI_ROM_RESOURCE);
  20.307 +        }
  20.308 +    }
  20.309 +}
  20.310 +
  20.311 +void __init pcibios_set_cacheline_size(void)
  20.312 +{
  20.313 +    struct cpuinfo_x86 *c = &boot_cpu_data;
  20.314 +
  20.315 +    pci_cache_line_size = 32 >> 2;
  20.316 +    if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
  20.317 +        pci_cache_line_size = 64 >> 2;	/* K7 & K8 */
  20.318 +    else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
  20.319 +        pci_cache_line_size = 128 >> 2;	/* P4 */
  20.320 +}
  20.321 +
  20.322 +void __init pcibios_resource_survey(void)
  20.323 +{
  20.324 +    DBG("PCI: Allocating resources\n");
  20.325 +    pcibios_allocate_bus_resources(&pci_root_buses);
  20.326 +    pcibios_allocate_resources(0);
  20.327 +    pcibios_allocate_resources(1);
  20.328 +    pcibios_assign_resources();
  20.329 +}
  20.330 +
  20.331 +int pcibios_enable_resources(struct pci_dev *dev, int mask)
  20.332 +{
  20.333 +    u16 cmd, old_cmd;
  20.334 +    int idx;
  20.335 +    struct resource *r;
  20.336 +
  20.337 +    pci_read_config_word(dev, PCI_COMMAND, &cmd);
  20.338 +    old_cmd = cmd;
  20.339 +    for(idx=0; idx<6; idx++) {
  20.340 +        /* Only set up the requested stuff */
  20.341 +        if (!(mask & (1<<idx)))
  20.342 +            continue;
  20.343 +			
  20.344 +        r = &dev->resource[idx];
  20.345 +        if (!r->start && r->end) {
  20.346 +            printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
  20.347 +            return -EINVAL;
  20.348 +        }
  20.349 +        if (r->flags & IORESOURCE_IO)
  20.350 +            cmd |= PCI_COMMAND_IO;
  20.351 +        if (r->flags & IORESOURCE_MEM)
  20.352 +            cmd |= PCI_COMMAND_MEMORY;
  20.353 +    }
  20.354 +    if (dev->resource[PCI_ROM_RESOURCE].start)
  20.355 +        cmd |= PCI_COMMAND_MEMORY;
  20.356 +    if (cmd != old_cmd) {
  20.357 +        printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
  20.358 +        pci_write_config_word(dev, PCI_COMMAND, cmd);
  20.359 +    }
  20.360 +    return 0;
  20.361 +}
  20.362 +
  20.363 +/*
  20.364 + *  If we set up a device for bus mastering, we need to check the latency
  20.365 + *  timer as certain crappy BIOSes forget to set it properly.
  20.366 + */
  20.367 +unsigned int pcibios_max_latency = 255;
  20.368 +
  20.369 +void pcibios_set_master(struct pci_dev *dev)
  20.370 +{
  20.371 +    u8 lat;
  20.372 +    pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
  20.373 +    if (lat < 16)
  20.374 +        lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
  20.375 +    else if (lat > pcibios_max_latency)
  20.376 +        lat = pcibios_max_latency;
  20.377 +    else
  20.378 +        return;
  20.379 +    printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
  20.380 +    pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
  20.381 +}
  20.382 +
  20.383 +int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
  20.384 +			enum pci_mmap_state mmap_state, int write_combine)
  20.385 +{
  20.386 +    unsigned long prot;
  20.387 +
  20.388 +    /* I/O space cannot be accessed via normal processor loads and
  20.389 +     * stores on this platform.
  20.390 +     */
  20.391 +    if (mmap_state == pci_mmap_io)
  20.392 +        return -EINVAL;
  20.393 +
  20.394 +    /* Leave vm_pgoff as-is, the PCI space address is the physical
  20.395 +     * address on this platform.
  20.396 +     */
  20.397 +    vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
  20.398 +
  20.399 +    prot = pgprot_val(vma->vm_page_prot);
  20.400 +    if (boot_cpu_data.x86 > 3)
  20.401 +        prot |= _PAGE_PCD | _PAGE_PWT;
  20.402 +    vma->vm_page_prot = __pgprot(prot);
  20.403 +
  20.404 +    /* Write-combine setting is ignored, it is changed via the mtrr
  20.405 +     * interfaces on this platform.
  20.406 +     */
  20.407 +    if (remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
  20.408 +                         vma->vm_end - vma->vm_start,
  20.409 +                         vma->vm_page_prot))
  20.410 +        return -EAGAIN;
  20.411 +
  20.412 +    return 0;
  20.413 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-i386.h	Fri Mar 12 15:47:50 2004 +0000
    21.3 @@ -0,0 +1,71 @@
    21.4 +/*
    21.5 + *	Low-Level PCI Access for i386 machines.
    21.6 + *
    21.7 + *	(c) 1999 Martin Mares <mj@ucw.cz>
    21.8 + */
    21.9 +
   21.10 +#undef DEBUG
   21.11 +
   21.12 +#ifdef DEBUG
   21.13 +#define DBG(x...) printk(x)
   21.14 +#else
   21.15 +#define DBG(x...)
   21.16 +#endif
   21.17 +
   21.18 +#define PCI_PROBE_BIOS		0x0001
   21.19 +#define PCI_PROBE_CONF1		0x0002
   21.20 +#define PCI_PROBE_CONF2		0x0004
   21.21 +#define PCI_NO_SORT		0x0100
   21.22 +#define PCI_BIOS_SORT		0x0200
   21.23 +#define PCI_NO_CHECKS		0x0400
   21.24 +#define PCI_ASSIGN_ROMS		0x1000
   21.25 +#define PCI_BIOS_IRQ_SCAN	0x2000
   21.26 +#define PCI_ASSIGN_ALL_BUSSES	0x4000
   21.27 +
   21.28 +extern unsigned int pci_probe;
   21.29 +
   21.30 +/* pci-i386.c */
   21.31 +
   21.32 +extern unsigned int pcibios_max_latency;
   21.33 +extern u8 pci_cache_line_size;
   21.34 +
   21.35 +void pcibios_resource_survey(void);
   21.36 +void pcibios_set_cacheline_size(void);
   21.37 +int pcibios_enable_resources(struct pci_dev *, int);
   21.38 +
   21.39 +/* pci-pc.c */
   21.40 +
   21.41 +extern int pcibios_last_bus;
   21.42 +extern struct pci_bus *pci_root_bus;
   21.43 +extern struct pci_ops *pci_root_ops;
   21.44 +
   21.45 +/* pci-irq.c */
   21.46 +
   21.47 +struct irq_info {
   21.48 +	u8 bus, devfn;			/* Bus, device and function */
   21.49 +	struct {
   21.50 +		u8 link;		/* IRQ line ID, chipset dependent, 0=not routed */
   21.51 +		u16 bitmap;		/* Available IRQs */
   21.52 +	} __attribute__((packed)) irq[4];
   21.53 +	u8 slot;			/* Slot number, 0=onboard */
   21.54 +	u8 rfu;
   21.55 +} __attribute__((packed));
   21.56 +
   21.57 +struct irq_routing_table {
   21.58 +	u32 signature;			/* PIRQ_SIGNATURE should be here */
   21.59 +	u16 version;			/* PIRQ_VERSION */
   21.60 +	u16 size;			/* Table size in bytes */
   21.61 +	u8 rtr_bus, rtr_devfn;		/* Where the interrupt router lies */
   21.62 +	u16 exclusive_irqs;		/* IRQs devoted exclusively to PCI usage */
   21.63 +	u16 rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
   21.64 +	u32 miniport_data;		/* Crap */
   21.65 +	u8 rfu[11];
   21.66 +	u8 checksum;			/* Modulo 256 checksum must give zero */
   21.67 +	struct irq_info slots[0];
   21.68 +} __attribute__((packed));
   21.69 +
   21.70 +extern unsigned int pcibios_irq_mask;
   21.71 +
   21.72 +void pcibios_irq_init(void);
   21.73 +void pcibios_fixup_irqs(void);
   21.74 +void pcibios_enable_irq(struct pci_dev *dev);
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-irq.c	Fri Mar 12 15:47:50 2004 +0000
    22.3 @@ -0,0 +1,90 @@
    22.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
    22.5 + ****************************************************************************
    22.6 + * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
    22.7 + ****************************************************************************
    22.8 + *
    22.9 + *        File: phys_dev.c
   22.10 + *      Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
   22.11 + *        Date: Mar 2004
   22.12 + *
   22.13 + * Description: XenoLinux wrappers for PCI interrupt handling.
   22.14 + *              very simple since someone else is doing all the hard bits
   22.15 + */
   22.16 +
   22.17 +
   22.18 +/*
   22.19 + *	Low-Level PCI Support for PC -- Routing of Interrupts
   22.20 + *
   22.21 + *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
   22.22 + */
   22.23 +
   22.24 +#include <linux/config.h>
   22.25 +#include <linux/types.h>
   22.26 +#include <linux/kernel.h>
   22.27 +#include <linux/pci.h>
   22.28 +#include <linux/init.h>
   22.29 +#include <linux/interrupt.h>
   22.30 +#include <linux/irq.h>
   22.31 +
   22.32 +#include "pci-i386.h"
   22.33 +
   22.34 +#include <asm/hypervisor-ifs/physdev.h>
   22.35 +
   22.36 +unsigned int pcibios_irq_mask = 0xfff8;
   22.37 +
   22.38 +void eisa_set_level_irq(unsigned int irq)
   22.39 +{
   22.40 +    /* dummy */
   22.41 +}
   22.42 +
   22.43 +void __init pcibios_irq_init(void)
   22.44 +{
   22.45 +	printk("PCI: IRQ init\n");
   22.46 +}
   22.47 +
   22.48 +void __init pcibios_fixup_irqs(void)
   22.49 +{
   22.50 +	struct pci_dev *dev;
   22.51 +    physdev_op_t op;
   22.52 +	int ret;
   22.53 +
   22.54 +
   22.55 +	printk("PCI: IRQ fixup\n");
   22.56 +	pci_for_each_dev(dev) {
   22.57 +
   22.58 +        op.cmd  = PHYSDEVOP_FIND_IRQ;
   22.59 +        op.u.find_irq.seg  = 0;
   22.60 +        op.u.find_irq.bus  = dev->bus->number;
   22.61 +        op.u.find_irq.dev  = PCI_SLOT(dev->devfn);
   22.62 +        op.u.find_irq.func = PCI_FUNC(dev->devfn);
   22.63 +
   22.64 +        if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
   22.65 +        {
   22.66 +            printk(KERN_ALERT "pci find irq error\n");
   22.67 +            return;
   22.68 +        }
   22.69 +
   22.70 +        dev->irq = op.u.find_irq.irq;
   22.71 +        printk(KERN_INFO "PCI IRQ: [%02x:%02x:%02x] -> %d\n",
   22.72 +               dev->bus->number, PCI_SLOT(dev->devfn),
   22.73 +               PCI_FUNC(dev->devfn), dev->irq);
   22.74 +    }
   22.75 +    return;
   22.76 +}
   22.77 +
   22.78 +void pcibios_penalize_isa_irq(int irq)
   22.79 +{
   22.80 +    /* dummy */
   22.81 +}
   22.82 +
   22.83 +void pcibios_enable_irq(struct pci_dev *dev)
   22.84 +{
   22.85 +	u8 pin;
   22.86 +	
   22.87 +	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
   22.88 +
   22.89 +	if (pin  && !dev->irq) {
   22.90 +		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of "
   22.91 +               "device %s.\n", 'A' + pin - 1, dev->slot_name);
   22.92 +	}
   22.93 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/pci-pc.c	Fri Mar 12 15:47:50 2004 +0000
    23.3 @@ -0,0 +1,364 @@
    23.4 +/*
    23.5 + *	Low-Level PCI Support for PC
    23.6 + *
    23.7 + *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
    23.8 + *
    23.9 + * adjusted to use Xen's interface by Rolf Neugebauer
   23.10 + */
   23.11 +
   23.12 +#include <linux/config.h>
   23.13 +#include <linux/types.h>
   23.14 +#include <linux/kernel.h>
   23.15 +#include <linux/sched.h>
   23.16 +#include <linux/pci.h>
   23.17 +#include <linux/init.h>
   23.18 +#include <linux/ioport.h>
   23.19 +
   23.20 +#include <asm/segment.h>
   23.21 +#include <asm/io.h>
   23.22 +
   23.23 +#include <asm/hypervisor-ifs/hypervisor-if.h>
   23.24 +#include <asm/hypervisor-ifs/physdev.h>
   23.25 +
   23.26 +#include "pci-i386.h"
   23.27 +
   23.28 +int pcibios_last_bus = -1;
   23.29 +struct pci_bus *pci_root_bus = NULL;
   23.30 +struct pci_ops *pci_root_ops = NULL;
   23.31 +
   23.32 +int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
   23.33 +int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
   23.34 +
   23.35 +static int pci_using_acpi_prt = 0;
   23.36 +
   23.37 +/*
   23.38 + * This interrupt-safe spinlock protects all accesses to PCI
   23.39 + * configuration space.
   23.40 + */
   23.41 +static spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
   23.42 +
   23.43 +unsigned int pci_probe = PCI_PROBE_BIOS;
   23.44 +
   23.45 +/*
   23.46 + * Functions for accessing PCI configuration space with type 1 accesses
   23.47 + */
   23.48 +
   23.49 +static int pci_confx_read (int seg, int bus, int dev, int fn, int reg, 
   23.50 +                           int len, u32 *value)
   23.51 +{
   23.52 +    int ret;
   23.53 +    physdev_op_t op;
   23.54 +
   23.55 +    if (bus > 255 || dev > 31 || fn > 7 || reg > 255)
   23.56 +        return -EINVAL;
   23.57 +
   23.58 +    op.cmd = PHYSDEVOP_CFGREG_READ;
   23.59 +    op.u.cfg_read.seg  = seg;
   23.60 +    op.u.cfg_read.bus  = bus;
   23.61 +    op.u.cfg_read.dev  = dev;
   23.62 +    op.u.cfg_read.func = fn;
   23.63 +    op.u.cfg_read.reg  = reg;
   23.64 +    op.u.cfg_read.len  = len;
   23.65 +
   23.66 +    if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
   23.67 +    {
   23.68 +        //printk(KERN_ALERT "pci config read error\n");
   23.69 +        return ret;
   23.70 +    }
   23.71 +
   23.72 +    *value = op.u.cfg_read.value;
   23.73 +
   23.74 +    return 0;
   23.75 +}
   23.76 +
   23.77 +static int pci_confx_write (int seg, int bus, int dev, int fn, int reg, 
   23.78 +                            int len, u32 value)
   23.79 +{
   23.80 +    int ret;
   23.81 +    physdev_op_t op;
   23.82 +
   23.83 +    if ((bus > 255 || dev > 31 || fn > 7 || reg > 255)) 
   23.84 +        return -EINVAL;
   23.85 +
   23.86 +    op.cmd = PHYSDEVOP_CFGREG_WRITE;
   23.87 +    op.u.cfg_write.seg   = seg;
   23.88 +    op.u.cfg_write.bus   = bus;
   23.89 +    op.u.cfg_write.dev   = dev;
   23.90 +    op.u.cfg_write.func  = fn;
   23.91 +    op.u.cfg_write.reg   = reg;
   23.92 +    op.u.cfg_write.len   = len;
   23.93 +    op.u.cfg_write.value = value;
   23.94 +
   23.95 +    if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
   23.96 +    {
   23.97 +        //printk(KERN_ALERT "pci config write error\n");
   23.98 +        return ret;
   23.99 +    }
  23.100 +    return 0;
  23.101 +}
  23.102 +
  23.103 +
  23.104 +static int pci_confx_read_config_byte(struct pci_dev *dev, int where, u8 *value)
  23.105 +{
  23.106 +    int result; 
  23.107 +    u32 data;
  23.108 +
  23.109 +    result = pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
  23.110 +                            PCI_FUNC(dev->devfn), where, 1, &data);
  23.111 +
  23.112 +    *value = (u8)data;
  23.113 +
  23.114 +    return result;
  23.115 +}
  23.116 +
  23.117 +static int pci_confx_read_config_word(struct pci_dev *dev, int where, u16 *value)
  23.118 +{
  23.119 +    int result; 
  23.120 +    u32 data;
  23.121 +
  23.122 +    result = pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
  23.123 +                            PCI_FUNC(dev->devfn), where, 2, &data);
  23.124 +
  23.125 +    *value = (u16)data;
  23.126 +
  23.127 +    return result;
  23.128 +}
  23.129 +
  23.130 +static int pci_confx_read_config_dword(struct pci_dev *dev, int where, u32 *value)
  23.131 +{
  23.132 +    return pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
  23.133 +                          PCI_FUNC(dev->devfn), where, 4, value);
  23.134 +}
  23.135 +
  23.136 +static int pci_confx_write_config_byte(struct pci_dev *dev, int where, u8 value)
  23.137 +{
  23.138 +    return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
  23.139 +                           PCI_FUNC(dev->devfn), where, 1, value);
  23.140 +}
  23.141 +
  23.142 +static int pci_confx_write_config_word(struct pci_dev *dev, int where, u16 value)
  23.143 +{
  23.144 +    return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
  23.145 +                           PCI_FUNC(dev->devfn), where, 2, value);
  23.146 +}
  23.147 +
  23.148 +static int pci_confx_write_config_dword(struct pci_dev *dev, int where, u32 value)
  23.149 +{
  23.150 +    return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
  23.151 +                           PCI_FUNC(dev->devfn), where, 4, value);
  23.152 +}
  23.153 +
  23.154 +static struct pci_ops pci_direct_confx = {
  23.155 +    pci_confx_read_config_byte,
  23.156 +    pci_confx_read_config_word,
  23.157 +    pci_confx_read_config_dword,
  23.158 +    pci_confx_write_config_byte,
  23.159 +    pci_confx_write_config_word,
  23.160 +    pci_confx_write_config_dword
  23.161 +};
  23.162 +
  23.163 +
  23.164 +
  23.165 +static struct pci_ops * __devinit pci_check_xen(void)
  23.166 +{
  23.167 +    unsigned long flags;
  23.168 +
  23.169 +    __save_flags(flags); __cli();
  23.170 +
  23.171 +    printk(KERN_INFO "PCI: Using Xen interface\n");
  23.172 +
  23.173 +    __restore_flags(flags);
  23.174 +
  23.175 +    return &pci_direct_confx;
  23.176 +}
  23.177 +
  23.178 +struct pci_fixup pcibios_fixups[] = { {0}};
  23.179 +
  23.180 +
  23.181 +struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
  23.182 +{
  23.183 +    return NULL;
  23.184 +}
  23.185 +
  23.186 +int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
  23.187 +{
  23.188 +    return 0;
  23.189 +}
  23.190 +
  23.191 +/*
  23.192 + * Several buggy motherboards address only 16 devices and mirror
  23.193 + * them to next 16 IDs. We try to detect this `feature' on all
  23.194 + * primary buses (those containing host bridges as they are
  23.195 + * expected to be unique) and remove the ghost devices.
  23.196 + */
  23.197 +
  23.198 +static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
  23.199 +{
  23.200 +    struct list_head *ln, *mn;
  23.201 +    struct pci_dev *d, *e;
  23.202 +    int mirror = PCI_DEVFN(16,0);
  23.203 +    int seen_host_bridge = 0;
  23.204 +    int i;
  23.205 +
  23.206 +    DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
  23.207 +    for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
  23.208 +        d = pci_dev_b(ln);
  23.209 +        if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
  23.210 +            seen_host_bridge++;
  23.211 +        for (mn=ln->next; mn != &b->devices; mn=mn->next) {
  23.212 +            e = pci_dev_b(mn);
  23.213 +            if (e->devfn != d->devfn + mirror ||
  23.214 +                e->vendor != d->vendor ||
  23.215 +                e->device != d->device ||
  23.216 +                e->class != d->class)
  23.217 +                continue;
  23.218 +            for(i=0; i<PCI_NUM_RESOURCES; i++)
  23.219 +                if (e->resource[i].start != d->resource[i].start ||
  23.220 +                    e->resource[i].end != d->resource[i].end ||
  23.221 +                    e->resource[i].flags != d->resource[i].flags)
  23.222 +                    continue;
  23.223 +            break;
  23.224 +        }
  23.225 +        if (mn == &b->devices)
  23.226 +            return;
  23.227 +    }
  23.228 +    if (!seen_host_bridge)
  23.229 +        return;
  23.230 +    printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number);
  23.231 +
  23.232 +    ln = &b->devices;
  23.233 +    while (ln->next != &b->devices) {
  23.234 +        d = pci_dev_b(ln->next);
  23.235 +        if (d->devfn >= mirror) {
  23.236 +            list_del(&d->global_list);
  23.237 +            list_del(&d->bus_list);
  23.238 +            kfree(d);
  23.239 +        } else
  23.240 +            ln = ln->next;
  23.241 +    }
  23.242 +}
  23.243 +
  23.244 +/*
  23.245 + * Discover remaining PCI buses in case there are peer host bridges.
  23.246 + * We use the number of last PCI bus provided by the PCI BIOS.
  23.247 + */
  23.248 +static void __devinit pcibios_fixup_peer_bridges(void)
  23.249 +{
  23.250 +    int n;
  23.251 +    struct pci_bus bus;
  23.252 +    struct pci_dev dev;
  23.253 +    u16 l;
  23.254 +    
  23.255 +    if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
  23.256 +        return;
  23.257 +    DBG("PCI: Peer bridge fixup\n");
  23.258 +    for (n=0; n <= pcibios_last_bus; n++) {
  23.259 +        if (pci_bus_exists(&pci_root_buses, n))
  23.260 +            continue;
  23.261 +        bus.number = n;
  23.262 +        bus.ops = pci_root_ops;
  23.263 +        dev.bus = &bus;
  23.264 +        for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
  23.265 +            if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
  23.266 +                l != 0x0000 && l != 0xffff) {
  23.267 +                DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
  23.268 +                printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
  23.269 +                pci_scan_bus(n, pci_root_ops, NULL);
  23.270 +                break;
  23.271 +            }
  23.272 +    }
  23.273 +}
  23.274 +
  23.275 +
  23.276 +/*
  23.277 + *  Called after each bus is probed, but before its children
  23.278 + *  are examined.
  23.279 + */
  23.280 +
  23.281 +void __devinit  pcibios_fixup_bus(struct pci_bus *b)
  23.282 +{
  23.283 +    pcibios_fixup_ghosts(b);
  23.284 +    pci_read_bridge_bases(b);
  23.285 +    return;
  23.286 +}
  23.287 +
  23.288 +struct pci_bus * __devinit pcibios_scan_root(int busnum)
  23.289 +{
  23.290 +    struct list_head *list;
  23.291 +    struct pci_bus *bus;
  23.292 +
  23.293 +    list_for_each(list, &pci_root_buses) {
  23.294 +        bus = pci_bus_b(list);
  23.295 +        if (bus->number == busnum) {
  23.296 +            /* Already scanned */
  23.297 +            return bus;
  23.298 +        }
  23.299 +    }
  23.300 +
  23.301 +    printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);
  23.302 +
  23.303 +    return pci_scan_bus(busnum, pci_root_ops, NULL);
  23.304 +}
  23.305 +
  23.306 +void __devinit pcibios_config_init(void)
  23.307 +{
  23.308 +    /*
  23.309 +     * Try all known PCI access methods. Note that we support using 
  23.310 +     * both PCI BIOS and direct access, with a preference for direct.
  23.311 +     */
  23.312 +
  23.313 +    pci_root_ops = pci_check_xen();
  23.314 +    pci_config_read = pci_confx_read;
  23.315 +    pci_config_write = pci_confx_write;
  23.316 +
  23.317 +    return;
  23.318 +}
  23.319 +
  23.320 +void __init pcibios_init(void)
  23.321 +{
  23.322 +    if (!pci_root_ops)
  23.323 +        pcibios_config_init();
  23.324 +    if (!pci_root_ops) {
  23.325 +        printk(KERN_WARNING "PCI: System does not support PCI\n");
  23.326 +        return;
  23.327 +    }
  23.328 +
  23.329 +    pcibios_set_cacheline_size();
  23.330 +
  23.331 +    printk(KERN_INFO "PCI: Probing PCI hardware\n");
  23.332 +
  23.333 +    if (!pci_using_acpi_prt) {
  23.334 +        pci_root_bus = pcibios_scan_root(0);
  23.335 +        pcibios_irq_init();
  23.336 +        pcibios_fixup_peer_bridges();
  23.337 +        pcibios_fixup_irqs();
  23.338 +    }
  23.339 +
  23.340 +    pcibios_resource_survey();
  23.341 +}
  23.342 +
  23.343 +char * __devinit  pcibios_setup(char *str)
  23.344 +{
  23.345 +    if (!strcmp(str, "off")) {
  23.346 +        pci_probe = 0;
  23.347 +        return NULL;
  23.348 +    }
  23.349 +    return NULL;
  23.350 +}
  23.351 +
  23.352 +unsigned int pcibios_assign_all_busses(void)
  23.353 +{
  23.354 +    return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
  23.355 +}
  23.356 +
  23.357 +int pcibios_enable_device(struct pci_dev *dev, int mask)
  23.358 +{
  23.359 +    int err;
  23.360 +
  23.361 +    if ((err = pcibios_enable_resources(dev, mask)) < 0)
  23.362 +        return err;
  23.363 +
  23.364 +    pcibios_enable_irq(dev);
  23.365 +
  23.366 +    return 0;
  23.367 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/physirq.c	Fri Mar 12 15:47:50 2004 +0000
    24.3 @@ -0,0 +1,156 @@
    24.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
    24.5 + ****************************************************************************
    24.6 + * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
    24.7 + ****************************************************************************
    24.8 + *
    24.9 + *        File: physirq.c
   24.10 + *      Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
   24.11 + *        Date: Mar 2004
   24.12 + * 
   24.13 + * Description: guests may receive virtual interrupts directly 
   24.14 + *              corresponding to physical interrupts. these virtual
   24.15 + *              interrupts require special handling provided 
   24.16 + *              by the virq irq type.
   24.17 + */
   24.18 +
   24.19 +
   24.20 +#include <linux/config.h>
   24.21 +#include <asm/atomic.h>
   24.22 +#include <asm/irq.h>
   24.23 +#include <asm/hypervisor.h>
   24.24 +#include <asm/system.h>
   24.25 +
   24.26 +#include <linux/irq.h>
   24.27 +#include <linux/sched.h>
   24.28 +
   24.29 +#include <asm/hypervisor-ifs/hypervisor-if.h>
   24.30 +#include <asm/hypervisor-ifs/physdev.h>
   24.31 +
   24.32 +static void physirq_interrupt(int irq, void *unused, struct pt_regs *ptregs);
   24.33 +
   24.34 +static int setup_event_handler = 0;
   24.35 +
   24.36 +static unsigned int startup_physirq_event(unsigned int irq)
   24.37 +{
   24.38 +    physdev_op_t op;
   24.39 +    int err;
   24.40 +
   24.41 +    printk("startup_physirq_event %d\n", irq);
   24.42 +
   24.43 +    /*
   24.44 +     * install a interrupt handler for physirq event when called thefirst tim
   24.45 +     */
   24.46 +    if ( !setup_event_handler )
   24.47 +    {
   24.48 +        printk("startup_physirq_event %d: setup event handler\n", irq);
   24.49 +        /* set up a event handler to demux virtualised physical interrupts */
   24.50 +        err = request_irq(HYPEREVENT_IRQ(_EVENT_PHYSIRQ), physirq_interrupt, 
   24.51 +                          SA_SAMPLE_RANDOM, "physirq", NULL);
   24.52 +        if ( err )
   24.53 +        {
   24.54 +            printk(KERN_WARNING "Could not allocate physirq interrupt\n");
   24.55 +            return err;
   24.56 +        }
   24.57 +        setup_event_handler = 1;
   24.58 +    }
   24.59 +
   24.60 +    /*
   24.61 +     * request the irq from hypervisor
   24.62 +     */
   24.63 +    op.cmd = PHYSDEVOP_REQUEST_IRQ;
   24.64 +    op.u.request_irq.irq   = irq;
   24.65 +    if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
   24.66 +    {
   24.67 +        printk(KERN_ALERT "could not get IRQ %d from Xen\n", irq);
   24.68 +        return err;
   24.69 +    }
   24.70 +    return 0;
   24.71 +}
   24.72 +
   24.73 +static void shutdown_physirq_event(unsigned int irq)
   24.74 +{
   24.75 +
   24.76 +    /* call xen to free IRQ */
   24.77 +
   24.78 +}
   24.79 +
   24.80 +
   24.81 +static void enable_physirq_event(unsigned int irq)
   24.82 +{
   24.83 +    /* XXX just enable all interrupts for now */
   24.84 +}
   24.85 +
   24.86 +static void disable_physirq_event(unsigned int irq)
   24.87 +{
   24.88 +    /* XXX just disable all interrupts for now */
   24.89 +}
   24.90 +
   24.91 +static void ack_physirq_event(unsigned int irq)
   24.92 +{
   24.93 +    /* clear bit */
   24.94 +    if ( irq <= 0 || irq >= 32 )
   24.95 +    {
   24.96 +        printk("wrong irq %d\n", irq);
   24.97 +    }
   24.98 +
   24.99 +    clear_bit(irq, &HYPERVISOR_shared_info->physirq_pend);
  24.100 +}
  24.101 +
  24.102 +static void end_physirq_event(unsigned int irq)
  24.103 +{
  24.104 +    int err;
  24.105 +    physdev_op_t op;
  24.106 +    /* call hypervisor */
  24.107 +    op.cmd = PHYSDEVOP_FINISHED_IRQ;
  24.108 +    op.u.finished_irq.irq   = irq;
  24.109 +    if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
  24.110 +    {
  24.111 +        printk(KERN_ALERT "could not finish IRQ %d\n", irq);
  24.112 +        return;
  24.113 +    }
  24.114 +    return;
  24.115 +}
  24.116 +
  24.117 +static struct hw_interrupt_type physirq_irq_type = {
  24.118 +    "physical-irq",
  24.119 +    startup_physirq_event,
  24.120 +    shutdown_physirq_event,
  24.121 +    enable_physirq_event,
  24.122 +    disable_physirq_event,
  24.123 +    ack_physirq_event,
  24.124 +    end_physirq_event,
  24.125 +    NULL
  24.126 +};
  24.127 +
  24.128 +
  24.129 +/*
  24.130 + * this interrupt handler demuxes the virt phys event and the virt phys 
  24.131 + * bitmask and calls the interrupt handlers for virtualised physical interrupts
  24.132 + */
  24.133 +static void physirq_interrupt(int irq, void *unused, struct pt_regs *ptregs)
  24.134 +{
  24.135 +#if 0
  24.136 +    unsigned long flags;
  24.137 +    int virq;
  24.138 +    local_irq_save(flags);
  24.139 +    do_IRQ(virq);
  24.140 +    local_irq_restore(flags);
  24.141 +#endif
  24.142 +}
  24.143 +
  24.144 +
  24.145 +void __init physirq_init(void)
  24.146 +{
  24.147 +    int i;
  24.148 +
  24.149 +    printk("Initialise irq handlers [%d-%d] for physical interrupts.\n",
  24.150 +           PHYS_IRQ_BASE, PHYS_IRQ_BASE+NR_PHYS_IRQS-1);
  24.151 +
  24.152 +    for ( i = 0; i < NR_PHYS_IRQS; i++ )
  24.153 +    {
  24.154 +        irq_desc[i + PHYS_IRQ_BASE].status  = IRQ_DISABLED;
  24.155 +        irq_desc[i + PHYS_IRQ_BASE].action  = 0;
  24.156 +        irq_desc[i + PHYS_IRQ_BASE].depth   = 1;
  24.157 +        irq_desc[i + PHYS_IRQ_BASE].handler = &physirq_irq_type;
  24.158 +    }
  24.159 +}
    25.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c	Fri Mar 12 13:36:59 2004 +0000
    25.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/setup.c	Fri Mar 12 15:47:50 2004 +0000
    25.3 @@ -1124,7 +1124,7 @@ static void die_irq(int irq, void *unuse
    25.4  
    25.5  static int __init setup_die_event(void)
    25.6  {
    25.7 -    (void)request_irq(_EVENT_DIE, die_irq, 0, "die", NULL);
    25.8 +    (void)request_irq(HYPEREVENT_IRQ(_EVENT_DIE), die_irq, 0, "die", NULL);
    25.9      return 0;
   25.10  }
   25.11  
   25.12 @@ -1249,7 +1249,7 @@ static void stop_irq(int irq, void *unus
   25.13  
   25.14  static int __init setup_stop_event(void)
   25.15  {
   25.16 -    (void)request_irq(_EVENT_STOP, stop_irq, 0, "stop", NULL);
   25.17 +    (void)request_irq(HYPEREVENT_IRQ(_EVENT_STOP), stop_irq, 0, "stop", NULL);
   25.18      return 0;
   25.19  }
   25.20  
    26.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c	Fri Mar 12 13:36:59 2004 +0000
    26.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c	Fri Mar 12 15:47:50 2004 +0000
    26.3 @@ -623,9 +623,9 @@ void __init time_init(void)
    26.4      __get_time_values_from_xen();
    26.5      processed_system_time = shadow_system_time;
    26.6  
    26.7 -    (void)setup_irq(TIMER_IRQ, &irq_timer);
    26.8 +    (void)setup_irq(HYPEREVENT_IRQ(_EVENT_TIMER), &irq_timer);
    26.9  
   26.10 -    (void)setup_irq(_EVENT_DEBUG, &dbg_time);
   26.11 +    (void)setup_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), &dbg_time);
   26.12  
   26.13      rdtscll(alarm);
   26.14  
    27.1 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h	Fri Mar 12 13:36:59 2004 +0000
    27.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h	Fri Mar 12 15:47:50 2004 +0000
    27.3 @@ -451,4 +451,15 @@ static inline int HYPERVISOR_console_io(
    27.4      return ret;
    27.5  }
    27.6  
    27.7 +static inline int HYPERVISOR_physdev_op(void *physdev_op)
    27.8 +{
    27.9 +    int ret;
   27.10 +    __asm__ __volatile__ (
   27.11 +        TRAP_INSTR
   27.12 +        : "=a" (ret) : "0" (__HYPERVISOR_physdev_op),
   27.13 +        "b" (physdev_op) : "memory" );
   27.14 +
   27.15 +    return ret;
   27.16 +}
   27.17 +
   27.18  #endif /* __HYPERVISOR_H__ */
    28.1 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/irq.h	Fri Mar 12 13:36:59 2004 +0000
    28.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/irq.h	Fri Mar 12 15:47:50 2004 +0000
    28.3 @@ -14,9 +14,18 @@
    28.4  #include <asm/hypervisor.h>
    28.5  #include <asm/ptrace.h>
    28.6  
    28.7 -#define TIMER_IRQ _EVENT_TIMER
    28.8 +#define NR_IRQS             256
    28.9 +
   28.10 +#define PHYS_IRQ_BASE         0
   28.11 +#define NR_PHYS_IRQS        128
   28.12  
   28.13 -#define NR_IRQS (sizeof(HYPERVISOR_shared_info->events) * 8)
   28.14 +#define HYPEREVENT_IRQ_BASE 128
   28.15 +#define NR_HYPEREVENT_IRQS  128
   28.16 +
   28.17 +#define HYPEREVENT_IRQ(_ev)       ((_ev)  + HYPEREVENT_IRQ_BASE)
   28.18 +#define HYPEREVENT_FROM_IRQ(_irq) ((_irq) - HYPEREVENT_IRQ_BASE)
   28.19 +
   28.20 +extern void physirq_init(void);
   28.21  
   28.22  #define irq_cannonicalize(_irq) (_irq)
   28.23  
    29.1 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/keyboard.h	Fri Mar 12 13:36:59 2004 +0000
    29.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/keyboard.h	Fri Mar 12 15:47:50 2004 +0000
    29.3 @@ -60,7 +60,7 @@ static inline int xen_kbd_controller_pre
    29.4  #define kbd_request_region()     \
    29.5      do { } while (0)
    29.6  #define kbd_request_irq(handler) \
    29.7 -    request_irq(_EVENT_PS2, handler, 0, "ps/2", NULL)
    29.8 +    request_irq(HYPEREVENT_IRQ(_EVENT_PS2), handler, 0, "ps/2", NULL)
    29.9  
   29.10  /* could implement these with command to xen to filter mouse stuff... */
   29.11  #define aux_request_irq(hand, dev_id) 0