Main Page | Modules | Class List | File List | Class Members | File Members | Related Pages

pci.c

Go to the documentation of this file.
00001 /* $Id: pci.c,v 1.16 2004/04/02 13:39:01 ch12 Exp $ */
00002 /*****************************************************************************/
00011 /* (c) 2003 Technische Universitaet Dresden
00012  * This file is part of DROPS, which is distributed under the terms of the
00013  * GNU General Public License 2. Please see the COPYING file for details.
00014  */
00015 
00046 /* L4 */
00047 #include <l4/env/errno.h>
00048 #include <l4/generic_io/libio.h>
00049 
00050 #include <l4/dde_linux/dde.h>
00051 
00052 /* Linux */
00053 #include <linux/pci.h>
00054 #include <linux/list.h>
00055 
00056 /* local */
00057 #include "internal.h"
00058 #include "__config.h"
00059 
00064 static struct pcidevs
00065 {
00066   struct pci_dev linus;  
00067   l4io_pdev_t l4;        
00068 } pcidevs[PCI_DEVICES];
00069 
00071 LIST_HEAD(pci_devices);
00072 
00074 static struct pci_bus pcibus =
00075 {
00076   name:    "LINUX DDE PCI BUS",
00077   number:  0,
00078 };
00079 
00081 static int _initialized = 0;
00082 
00090 static inline l4io_pdev_t __pci_get_handle(struct pci_dev *linus)
00091 {
00092   return ((struct pcidevs*)linus)->l4;
00093 }
00094 
00102 static inline void __pci_io_to_linux(l4io_pci_dev_t *l4io,
00103                                      struct pci_dev *linus)
00104 {
00105   int i;
00106 
00107   memset(linus, 0, sizeof(struct pci_dev));
00108 
00109   linus->devfn = l4io->devfn;
00110   linus->vendor = l4io->vendor;
00111   linus->device = l4io->device;
00112   linus->subsystem_vendor = l4io->sub_vendor;
00113   linus->subsystem_device = l4io->sub_device;
00114   linus->class = l4io->class;
00115 
00116   linus->irq = l4io->irq;
00117   for (i = 0; i < 12; i++)
00118     {
00119       linus->resource[i].name = linus->name;
00120 
00121       linus->resource[i].start = l4io->res[i].start;
00122       linus->resource[i].end = l4io->res[i].end;
00123       linus->resource[i].flags = l4io->res[i].flags;
00124 
00125       linus->resource[i].parent = NULL;
00126       linus->resource[i].sibling = NULL;
00127       linus->resource[i].child = NULL;
00128     }
00129 
00130   strcpy(&linus->name[0], &l4io->name[0]);
00131   strcpy(&linus->slot_name[0], &l4io->slot_name[0]);
00132 
00133   linus->bus = &pcibus;
00134 
00135   list_add_tail(&linus->global_list, &pci_devices);
00136   list_add_tail(&linus->bus_list, &pcibus.devices);
00137 }
00138 
00151 const struct pci_device_id *pci_match_device(const struct pci_device_id *ids,
00152                                              const struct pci_dev *dev)
00153 {
00154   while (ids->vendor || ids->subvendor || ids->class_mask)
00155     {
00156       if ((ids->vendor == PCI_ANY_ID || ids->vendor == dev->vendor) &&
00157           (ids->device == PCI_ANY_ID || ids->device == dev->device) &&
00158           (ids->subvendor == PCI_ANY_ID || ids->subvendor == dev->subsystem_vendor) &&
00159           (ids->subdevice == PCI_ANY_ID || ids->subdevice == dev->subsystem_device) &&
00160           !((ids->class ^ dev->class) & ids->class_mask))
00161         return ids;
00162       ids++;
00163     }
00164   return NULL;
00165 }
00166 
00174 static int pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
00175 {
00176   const struct pci_device_id *id;
00177   int ret = 0;
00178 
00179   if (drv->id_table)
00180     {
00181       id = pci_match_device(drv->id_table, dev);
00182       if (!id)
00183         {
00184           ret = 0;
00185           goto out;
00186         }
00187     }
00188   else
00189     id = NULL;
00190 
00191 //      dev_probe_lock();
00192   if (drv->probe(dev, id) >= 0)
00193     {
00194       dev->driver = drv;
00195       ret = 1;
00196     }
00197 //      dev_probe_unlock();
00198 out:
00199   return ret;
00200 }
00201 
00209 struct pci_driver *pci_dev_driver(const struct pci_dev *dev)
00210 {
00211   if (dev->driver)
00212     return dev->driver;
00213   return NULL;
00214 }
00215 
00229 int pci_register_driver(struct pci_driver *drv)
00230 {
00231   struct pci_dev *dev;
00232   int count = 0;
00233 
00234   pci_for_each_dev(dev)
00235   {
00236     if (!pci_dev_driver(dev))
00237       count += pci_announce_device(drv, dev);
00238   }
00239   return count;
00240 }
00241 
00249 void pci_unregister_driver(struct pci_driver *drv)
00250 {
00251   struct pci_dev *dev;
00252 
00253   pci_for_each_dev(dev)
00254     {
00255       if (dev->driver == drv)
00256         {
00257           if (drv->remove)
00258             drv->remove(dev);
00259           dev->driver = NULL;
00260         }
00261     }
00262 }
00263 
00273 struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
00274                                 const struct pci_dev *from)
00275 {
00276   struct list_head *n = from ? from->global_list.next : pci_devices.next;
00277 
00278   while (n != &pci_devices)
00279     {
00280       struct pci_dev *dev = pci_dev_g(n);
00281       if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
00282           (device == PCI_ANY_ID || dev->device == device))
00283         return dev;
00284       n = n->next;
00285     }
00286 
00287   return NULL;
00288 }
00289 
00301 struct pci_dev * pci_find_subsys(unsigned int vendor, unsigned int device,
00302                                  unsigned int ss_vendor, unsigned int ss_device,
00303                                  const struct pci_dev *from)
00304 {
00305   struct list_head *n = from ? from->global_list.next : pci_devices.next;
00306 
00307   while (n != &pci_devices)
00308     {
00309       struct pci_dev *dev = pci_dev_g(n);
00310       if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
00311           (device == PCI_ANY_ID || dev->device == device) &&
00312           (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
00313           (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
00314         return dev;
00315       n = n->next;
00316     }
00317 
00318   return NULL;
00319 }
00320 
00329 struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
00330 {
00331   struct pci_dev *dev;
00332 
00333   pci_for_each_dev(dev)
00334     {
00335       if (dev->bus->number == bus && dev->devfn == devfn)
00336         return dev;
00337     }
00338 
00339   return NULL;
00340 }
00341 
00350 struct pci_dev *pci_find_class(unsigned int class, const struct pci_dev *from)
00351 {
00352   struct list_head *n = from ? from->global_list.next : pci_devices.next;
00353 
00354   while (n != &pci_devices)
00355     {
00356       struct pci_dev *dev = pci_dev_g(n);
00357       if (dev->class == class)
00358         return dev;
00359       n = n->next;
00360     }
00361 
00362   return NULL;
00363 }
00364 
00365 /* emulate locally like in drivers/pci.c */
00366 int pci_find_capability (struct pci_dev *dev, int cap)
00367 {
00368   return 0;
00369 }
00370 
00382 int pci_enable_device(struct pci_dev *dev)
00383 {
00384   int err;
00385   l4io_pdev_t pdev;
00386 
00387   if (!(pdev=__pci_get_handle(dev)))
00388     {
00389 #if DEBUG_PCI
00390       LOGdL(DEBUG_ERRORS, "device %p not found", dev);
00391 #endif
00392       return PCIBIOS_DEVICE_NOT_FOUND;
00393     }
00394 
00395   err = l4io_pci_enable(pdev);
00396 
00397 #if DEBUG_PCI
00398   if (err)
00399     LOGdL(DEBUG_ERRORS, "enabling PCI device (%d)", err);
00400 #endif
00401 
00402   return err;
00403 }
00404 
00410 void pci_disable_device(struct pci_dev *dev)
00411 {
00412   int err;
00413   l4io_pdev_t pdev;
00414 
00415   if (!(pdev=__pci_get_handle(dev)))
00416     {
00417 #if DEBUG_PCI
00418       LOGdL(DEBUG_ERRORS, "device %p not found", dev);
00419 #endif
00420       return;
00421     }
00422 
00423   err = l4io_pci_disable(pdev);
00424 
00425 #if DEBUG_PCI
00426   if (err)
00427     LOGdL(DEBUG_ERRORS, "disabling PCI device (%d)", err);
00428 #endif
00429 }
00430 
00438 void pci_set_master(struct pci_dev *dev)
00439 {
00440   l4io_pdev_t pdev;
00441 
00442   if (!(pdev=__pci_get_handle(dev)))
00443     {
00444 #if DEBUG_PCI
00445       Panic("device %p not found", dev);
00446 #endif
00447       return;
00448     }
00449 
00450   l4io_pci_set_master(pdev);
00451 }
00452 
00465 int pci_set_power_state(struct pci_dev *dev, int state)
00466 {
00467   l4io_pdev_t pdev;
00468 
00469   if (!(pdev=__pci_get_handle(dev)))
00470     {
00471 #if DEBUG_PCI
00472       LOGdL(DEBUG_ERRORS, "device %p not found", dev);
00473 #endif
00474       return PCIBIOS_DEVICE_NOT_FOUND;
00475     }
00476 
00477   return l4io_pci_set_pm(pdev, state);
00478 }
00479 
00494 void pci_release_region(struct pci_dev *pdev, int bar)
00495 {
00496   if (pci_resource_len(pdev, bar) == 0)
00497     return;
00498   if (pci_resource_flags(pdev, bar) & IORESOURCE_IO)
00499     release_region(pci_resource_start(pdev, bar),
00500                                       pci_resource_len(pdev, bar));
00501   else
00502     if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM)
00503       release_mem_region(pci_resource_start(pdev, bar),
00504                          pci_resource_len(pdev, bar));
00505 }
00506 
00520 int pci_request_region(struct pci_dev *pdev, int bar, char *res_name)
00521 {
00522   if (pci_resource_len(pdev, bar) == 0)
00523     return 0;
00524 
00525   if (pci_resource_flags(pdev, bar) & IORESOURCE_IO)
00526     {
00527       if (!request_region(pci_resource_start(pdev, bar),
00528                           pci_resource_len(pdev, bar), res_name))
00529         goto err_out;
00530     }
00531   else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM)
00532     {
00533       if (!request_mem_region(pci_resource_start(pdev, bar),
00534                               pci_resource_len(pdev, bar), res_name))
00535         goto err_out;
00536     }
00537 
00538   return 0;
00539 
00540 err_out:
00541   printk(KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n",
00542          pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem",
00543          bar + 1, /* PCI BAR # */
00544          pci_resource_len(pdev, bar), pci_resource_start(pdev, bar),
00545          pdev->slot_name);
00546   return -EBUSY;
00547 }
00548 
00549 
00557 void pci_release_regions(struct pci_dev *pdev)
00558 {
00559   int i;
00560 
00561   for (i = 0; i < 6; i++)
00562     pci_release_region(pdev, i);
00563 }
00564 
00577 int pci_request_regions(struct pci_dev *pdev, char *res_name)
00578 {
00579   int i;
00580 
00581   for (i = 0; i < 6; i++)
00582     if (pci_request_region(pdev, i, res_name))
00583       goto err_out;
00584   return 0;
00585 
00586 err_out:
00587   printk(KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n",
00588          pci_resource_flags(pdev, i) & IORESOURCE_IO ? "I/O" : "mem",
00589          i + 1, /* PCI BAR # */
00590          pci_resource_len(pdev, i), pci_resource_start(pdev, i),
00591          pdev->slot_name);
00592   while(--i >= 0)
00593     pci_release_region(pdev, i);
00594 
00595   return -EBUSY;
00596 }
00597 
00611 struct pci_pool
00612 {
00613   struct list_head page_list;
00614   spinlock_t lock;
00615   size_t blocks_per_page;
00616   size_t size;
00617   int flags;
00618   struct pci_dev *dev;
00619   size_t allocation;
00620   char name [32];
00621   wait_queue_head_t waitq;
00622 };
00623 
00625 struct pci_page
00626 {
00627   struct list_head page_list;
00628   void *vaddr;
00629   dma_addr_t dma;
00630   unsigned long bitmap [0];
00631 };
00632 
00633 #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
00634 #define POOL_POISON_BYTE     0xa7
00635 
00636 // #define CONFIG_PCIPOOL_DEBUG
00637 
00660 struct pci_pool * pci_pool_create(const char *name, struct pci_dev *pdev,
00661                                   size_t size, size_t align, size_t allocation,
00662                                   int flags)
00663 {
00664   struct pci_pool *retval;
00665 
00666   if (align == 0)
00667     align = 1;
00668   if (size == 0)
00669     return 0;
00670   else if (size < align)
00671     size = align;
00672   else if ((size % align) != 0)
00673     {
00674       size += align + 1;
00675       size &= ~(align - 1);
00676     }
00677 
00678   if (allocation == 0)
00679     {
00680       if (PAGE_SIZE < size)
00681         allocation = size;
00682       else
00683         allocation = PAGE_SIZE;
00684     // FIXME: round up for less fragmentation
00685     }
00686   else if (allocation < size)
00687     return 0;
00688 
00689   if (!(retval = kmalloc(sizeof *retval, flags)))
00690     return retval;
00691 
00692 #ifdef CONFIG_PCIPOOL_DEBUG
00693   flags |= SLAB_POISON;
00694 #endif
00695 
00696   strncpy(retval->name, name, sizeof retval->name);
00697   retval->name [sizeof retval->name - 1] = 0;
00698 
00699   retval->dev = pdev;
00700   INIT_LIST_HEAD(&retval->page_list);
00701   spin_lock_init(&retval->lock);
00702   retval->size = size;
00703   retval->flags = flags;
00704   retval->allocation = allocation;
00705   retval->blocks_per_page = allocation / size;
00706   init_waitqueue_head(&retval->waitq);
00707 
00708 #ifdef CONFIG_PCIPOOL_DEBUG
00709   printk(KERN_DEBUG "pcipool create %s/%s size %d, %d/page(%d alloc)\n",
00710          pdev ? pdev->slot_name : NULL, retval->name, size,
00711          retval->blocks_per_page, allocation);
00712 #endif
00713 
00714   return retval;
00715 }
00716 
00718 static struct pci_page * pool_alloc_page(struct pci_pool *pool, int mem_flags)
00719 {
00720   struct pci_page *page;
00721   int mapsize;
00722 
00723   mapsize = pool->blocks_per_page;
00724   mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
00725   mapsize *= sizeof(long);
00726 
00727   page = (struct pci_page *) kmalloc(mapsize + sizeof *page, mem_flags);
00728   if (!page)
00729     return 0;
00730   page->vaddr = pci_alloc_consistent(pool->dev, pool->allocation, &page->dma);
00731   if (page->vaddr)
00732     {
00733       memset(page->bitmap, 0xff, mapsize); // bit set == free
00734       if (pool->flags & SLAB_POISON)
00735         memset(page->vaddr, POOL_POISON_BYTE, pool->allocation);
00736       list_add(&page->page_list, &pool->page_list);
00737     }
00738   else
00739     {
00740       kfree(page);
00741       page = 0;
00742     }
00743   return page;
00744 }
00745 
00746 
00748 static inline int is_page_busy(int blocks, unsigned long *bitmap)
00749 {
00750   while (blocks > 0)
00751     {
00752       if (*bitmap++ != ~0UL)
00753         return 1;
00754       blocks -= BITS_PER_LONG;
00755     }
00756   return 0;
00757 }
00758 
00760 static void pool_free_page(struct pci_pool *pool, struct pci_page *page)
00761 {
00762   dma_addr_t dma = page->dma;
00763 
00764   if (pool->flags & SLAB_POISON)
00765     memset(page->vaddr, POOL_POISON_BYTE, pool->allocation);
00766   pci_free_consistent(pool->dev, pool->allocation, page->vaddr, dma);
00767   list_del(&page->page_list);
00768   kfree(page);
00769 }
00770 
00771 
00780 void pci_pool_destroy(struct pci_pool *pool)
00781 {
00782   unsigned long flags;
00783 
00784 #ifdef CONFIG_PCIPOOL_DEBUG
00785   printk(KERN_DEBUG "pcipool destroy %s/%s\n",
00786          pool->dev ? pool->dev->slot_name : NULL,
00787          pool->name);
00788 #endif
00789 
00790   spin_lock_irqsave(&pool->lock, flags);
00791   while (!list_empty(&pool->page_list))
00792     {
00793       struct pci_page *page;
00794       page = list_entry(pool->page_list.next,
00795                         struct pci_page, page_list);
00796       if (is_page_busy(pool->blocks_per_page, page->bitmap))
00797         {
00798           printk(KERN_ERR "pci_pool_destroy %s/%s, %p busy\n",
00799                  pool->dev ? pool->dev->slot_name : NULL,
00800           pool->name, page->vaddr);
00801           /* leak the still-in-use consistent memory */
00802           list_del(&page->page_list);
00803           kfree(page);
00804         }
00805       else pool_free_page(pool, page);
00806     }
00807   spin_unlock_irqrestore(&pool->lock, flags);
00808   kfree(pool);
00809 }
00810 
00811 
00823 void * pci_pool_alloc(struct pci_pool *pool, int mem_flags, dma_addr_t *handle)
00824 {
00825   unsigned long flags;
00826   struct list_head *entry;
00827   struct pci_page *page;
00828   int map, block;
00829   size_t offset;
00830   void *retval;
00831 
00832 restart:
00833   spin_lock_irqsave(&pool->lock, flags);
00834   list_for_each(entry, &pool->page_list)
00835     {
00836       int i;
00837       page = list_entry(entry, struct pci_page, page_list);
00838       /* only cachable accesses here ... */
00839       for (map = 0, i = 0; i < pool->blocks_per_page; i += BITS_PER_LONG, map++)
00840         {
00841           if (page->bitmap [map] == 0)
00842             continue;
00843           block = ffz(~ page->bitmap [map]);
00844           if ((i + block) < pool->blocks_per_page)
00845             {
00846               clear_bit(block, &page->bitmap [map]);
00847               offset = (BITS_PER_LONG * map) + block;
00848               offset *= pool->size;
00849               goto ready;
00850             }
00851         }
00852     }
00853   if (!(page = pool_alloc_page(pool, mem_flags)))
00854     {
00855       if (mem_flags == SLAB_KERNEL)
00856         {
00857           DECLARE_WAITQUEUE(wait, current);
00858 
00859           current->state = TASK_INTERRUPTIBLE;
00860           add_wait_queue(&pool->waitq, &wait);
00861           spin_unlock_irqrestore(&pool->lock, flags);
00862 
00863           schedule_timeout(POOL_TIMEOUT_JIFFIES);
00864 
00865           current->state = TASK_RUNNING;
00866           remove_wait_queue(&pool->waitq, &wait);
00867           goto restart;
00868         }
00869       retval = 0;
00870       goto done;
00871     }
00872 
00873   clear_bit(0, &page->bitmap [0]);
00874   offset = 0;
00875 ready:
00876   retval = offset + page->vaddr;
00877   *handle = offset + page->dma;
00878 done:
00879   spin_unlock_irqrestore(&pool->lock, flags);
00880   return retval;
00881 }
00882 
00883 
00885 static struct pci_page *
00886 pool_find_page(struct pci_pool *pool, dma_addr_t dma)
00887 {
00888   unsigned long flags;
00889   struct list_head *entry;
00890   struct pci_page *page;
00891 
00892   spin_lock_irqsave(&pool->lock, flags);
00893   list_for_each(entry, &pool->page_list)
00894     {
00895       page = list_entry(entry, struct pci_page, page_list);
00896       if (dma < page->dma)
00897         continue;
00898       if (dma < (page->dma + pool->allocation))
00899         goto done;
00900     }
00901   page = 0;
00902 done:
00903   spin_unlock_irqrestore(&pool->lock, flags);
00904   return page;
00905 }
00906 
00907 
00916 void
00917 pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
00918 {
00919   struct pci_page *page;
00920   unsigned long flags;
00921   int map, block;
00922 
00923   if ((page = pool_find_page (pool, dma)) == 0)
00924     {
00925       printk(KERN_ERR "pci_pool_free %s/%s, %p/%x (bad dma)\n",
00926              pool->dev ? pool->dev->slot_name : NULL,
00927              pool->name, vaddr, (int) (dma & 0xffffffff));
00928       return;
00929     }
00930 #ifdef  CONFIG_PCIPOOL_DEBUG
00931   if (((dma - page->dma) + (void *)page->vaddr) != vaddr)
00932     {
00933       printk(KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%x\n",
00934              pool->dev ? pool->dev->slot_name : NULL,
00935              pool->name, vaddr, (int) (dma & 0xffffffff));
00936       return;
00937     }
00938 #endif
00939 
00940   block = dma - page->dma;
00941   block /= pool->size;
00942   map = block / BITS_PER_LONG;
00943   block %= BITS_PER_LONG;
00944 
00945 #ifdef  CONFIG_PCIPOOL_DEBUG
00946   if (page->bitmap [map] & (1UL << block))
00947     {
00948       printk(KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
00949              pool->dev ? pool->dev->slot_name : NULL,
00950              pool->name, dma);
00951       return;
00952     }
00953 #endif
00954   if (pool->flags & SLAB_POISON)
00955     memset(vaddr, POOL_POISON_BYTE, pool->size);
00956 
00957   spin_lock_irqsave(&pool->lock, flags);
00958   set_bit(block, &page->bitmap [map]);
00959   if (waitqueue_active(&pool->waitq))
00960     wake_up(&pool->waitq);
00961   /*
00962    * Resist a temptation to do
00963    *    if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page);
00964    * it is not interrupt safe. Better have empty pages hang around.
00965    */
00966   spin_unlock_irqrestore(&pool->lock, flags);
00967 }
00968 
00974 void *pci_alloc_consistent(struct pci_dev *hwdev,
00975                            size_t size, dma_addr_t * dma_handle)
00976 {
00977   void *ret;
00978   int gfp = GFP_ATOMIC;
00979 
00980 /* NO ISA now
00981    if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
00982    gfp |= GFP_DMA;
00983 */
00984   ret = (void *) __get_free_pages(gfp, get_order(size));
00985 
00986   if (ret != NULL)
00987     {
00988       memset(ret, 0, size);
00989       *dma_handle = virt_to_bus(ret);
00990     }
00991   LOGdL(DEBUG_PALLOC, "PCI requested pages");
00992   return ret;
00993 }
00994 
01000 void pci_free_consistent(struct pci_dev *hwdev, size_t size,
01001                          void *vaddr, dma_addr_t dma_handle)
01002 {
01003   free_pages((unsigned long) vaddr, get_order(size));
01004   LOGdL(DEBUG_PALLOC, "PCI released pages");
01005 }
01006 
01007 /* XXX think about this */
01008 int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
01009 {
01010   dev->dma_mask = mask;
01011 
01012   return 0;
01013 }
01014 
01028 /*****************************************************************************/
01029 int pci_read_config_byte(struct pci_dev *dev, int pos, l4_uint8_t * val)
01030 {
01031   int err;
01032   l4io_pdev_t pdev;
01033 
01034   if (!(pdev=__pci_get_handle(dev)))
01035     {
01036 #if DEBUG_PCI
01037       LOG_Error("device %p not found", dev);
01038 #endif
01039       return PCIBIOS_DEVICE_NOT_FOUND;
01040     }
01041 
01042   err = l4io_pci_readb_cfg(pdev, pos, val);
01043 
01044 #if DEBUG_PCI
01045   if (err)
01046     LOG_Error("reading PCI config register (%d)", err);
01047 #endif
01048 
01049   return err ? -EIO : 0;
01050 }
01051 
01061 int pci_read_config_word(struct pci_dev *dev, int pos, l4_uint16_t * val)
01062 {
01063   int err;
01064   l4io_pdev_t pdev;
01065 
01066   if (!(pdev=__pci_get_handle(dev)))
01067     {
01068 #if DEBUG_PCI
01069       LOG_Error("device %p not found", dev);
01070 #endif
01071       return PCIBIOS_DEVICE_NOT_FOUND;
01072     }
01073 
01074   err = l4io_pci_readw_cfg(pdev, pos, val);
01075 
01076 #if DEBUG_PCI
01077   if (err)
01078     LOG_Error("reading PCI config register (%d)", err);
01079 #endif
01080 
01081   return err ? -EIO : 0;
01082 }
01083 
01093 int pci_read_config_dword(struct pci_dev *dev, int pos, l4_uint32_t * val)
01094 {
01095   int err;
01096   l4io_pdev_t pdev;
01097 
01098   if (!(pdev=__pci_get_handle(dev)))
01099     {
01100 #if DEBUG_PCI
01101       LOG_Error("device %p not found", dev);
01102 #endif
01103       return PCIBIOS_DEVICE_NOT_FOUND;
01104     }
01105 
01106   err = l4io_pci_readl_cfg(pdev, pos, val);
01107 
01108 #if DEBUG_PCI
01109   if (err)
01110     LOG_Error("reading PCI config register (%d)", err);
01111 #endif
01112 
01113   return err ? -EIO : 0;
01114 }
01115 
01125 int pci_write_config_byte(struct pci_dev *dev, int pos, l4_uint8_t val)
01126 {
01127   int err;
01128   l4io_pdev_t pdev;
01129 
01130   if (!(pdev=__pci_get_handle(dev)))
01131     {
01132 #if DEBUG_PCI
01133       LOG_Error("device %p not found", dev);
01134 #endif
01135       return PCIBIOS_DEVICE_NOT_FOUND;
01136     }
01137 
01138   err = l4io_pci_writeb_cfg(pdev, pos, val);
01139 
01140 #if DEBUG_PCI
01141   if (err)
01142     LOG_Error("writing PCI config register (%d)", err);
01143 #endif
01144 
01145   return err ? -EIO : 0;
01146 }
01147 
01157 int pci_write_config_word(struct pci_dev *dev, int pos, l4_uint16_t val)
01158 {
01159   int err;
01160   l4io_pdev_t pdev;
01161 
01162   if (!(pdev=__pci_get_handle(dev)))
01163     {
01164 #if DEBUG_PCI
01165       LOG_Error("device %p not found", dev);
01166 #endif
01167       return PCIBIOS_DEVICE_NOT_FOUND;
01168     }
01169 
01170   err = l4io_pci_writew_cfg(pdev, pos, val);
01171 
01172 #if DEBUG_PCI
01173   if (err)
01174     LOG_Error("writing PCI config register (%d)", err);
01175 #endif
01176 
01177   return err ? -EIO : 0;
01178 }
01179 
01189 int pci_write_config_dword(struct pci_dev *dev, int pos, l4_uint32_t val)
01190 {
01191   int err;
01192   l4io_pdev_t pdev;
01193 
01194   if (!(pdev=__pci_get_handle(dev)))
01195     {
01196 #if DEBUG_PCI
01197       LOG_Error("device %p not found", dev);
01198 #endif
01199       return PCIBIOS_DEVICE_NOT_FOUND;
01200     }
01201 
01202   err = l4io_pci_writel_cfg(pdev, pos, val);
01203 
01204 #if DEBUG_PCI
01205   if (err)
01206     LOG_Error("writing PCI config register (%d)", err);
01207 #endif
01208 
01209   return err ? -EIO : 0;
01210 }
01211 
01217 #if 0
01218 
01220 int pcibios_find_class(unsigned int class, unsigned short index,
01221                        unsigned char *bus, unsigned char *devfn)
01222 {
01223   const struct pci_dev *dev = NULL;
01224   int cnt = 0;
01225 
01226   while ((dev = pci_find_class(class, dev)))
01227     if (index == cnt++)
01228       {
01229         *bus = dev->bus->number;
01230         *devfn = dev->devfn;
01231         return PCIBIOS_SUCCESSFUL;
01232       }
01233 
01234   return PCIBIOS_DEVICE_NOT_FOUND;
01235 }
01236 #endif
01237 
01240 int pcibios_find_device(unsigned short vendor, unsigned short device,
01241                         unsigned short index, unsigned char *bus,
01242                         unsigned char *devfn)
01243 {
01244   const struct pci_dev *dev = NULL;
01245   int cnt = 0;
01246 
01247   while ((dev = pci_find_device(vendor, device, dev)))
01248     if (index == cnt++)
01249       {
01250         *bus = dev->bus->number;
01251         *devfn = dev->devfn;
01252         return PCIBIOS_SUCCESSFUL;
01253       }
01254 
01255   return PCIBIOS_DEVICE_NOT_FOUND;
01256 }
01257 
01260 #define PCI_OP(rw,size,type)                                                \
01261 int pcibios_##rw##_config_##size (unsigned char bus, unsigned char dev_fn,  \
01262                                   unsigned char where, unsigned type val)   \
01263 {                                                                           \
01264   struct pci_dev *dev = pci_find_slot(bus, dev_fn);                         \
01265   if (!dev) return PCIBIOS_DEVICE_NOT_FOUND;                                \
01266   return pci_##rw##_config_##size(dev, where, val);                         \
01267 }
01268 
01269 PCI_OP(read, byte, char *)
01270 PCI_OP(read, word, short *)
01271 PCI_OP(read, dword, int *)
01272 PCI_OP(write, byte, char)
01273 PCI_OP(write, word, short)
01274 PCI_OP(write, dword, int)
01275 
01276 
01286 int l4dde_pci_init()
01287 {
01288   struct pci_dev *dev = NULL;
01289   int err, i;
01290   l4io_pdev_t start = 0;
01291   l4io_pci_dev_t new;
01292 
01293   if (_initialized)
01294     return -L4_ESKIPPED;
01295 
01296   /* setup virtual bus */
01297   INIT_LIST_HEAD(&pcibus.devices);
01298 
01299   /* setup devices */
01300   for (;;)
01301     {
01302       if (dev && !(start=__pci_get_handle((struct pci_dev*)dev)))
01303         {
01304 #if DEBUG_PCI
01305           Panic("device %p not found -- Maybe you have to setup PCI_DEVICES"
01306                 "properly (default is 12 devices maximum).", dev);
01307 #endif
01308           return -L4_EUNKNOWN;
01309         }
01310 
01311       err = l4io_pci_find_device(PCI_ANY_ID, PCI_ANY_ID, start, &new);
01312 
01313       if (err)
01314         {
01315           if (err == -L4_ENOTFOUND) break;
01316 #if DEBUG_PCI
01317           LOG_Error("locate PCI device (%d)", err);
01318 #endif
01319           return err;
01320         }
01321 
01322       /* look for free slot */
01323       for (i=0; i < PCI_DEVICES; i++)
01324         if (!pcidevs[i].l4)
01325           break;
01326       if (i == PCI_DEVICES)
01327         {
01328 #if DEBUG_PCI
01329           Panic("all PCI device slots occupied");
01330 #endif
01331           return -L4_EUNKNOWN;
01332         }
01333 
01334       /* save information */
01335       __pci_io_to_linux(&new, &pcidevs[i].linus);
01336       pcidevs[i].l4 = new.handle;
01337 
01338       dev = &pcidevs[i].linus;
01339     }
01340 
01341   ++_initialized;
01342   return 0;
01343 }

Linux DDE, written by Christian Helmuth  © 2003 Technische Universitaet Dresden