⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
   tmp = *area;   for (r=first; r!=past; r=r->next)    {      alloc_space(&tmp, r);   }}#define BUS0_IO_START           0x10000#define BUS0_IO_END             0x1ffff#define BUS0_MEM_START          0x1000000#define BUS0_MEM_END            0x3f00000#define BUSREST_IO_START        0x20000#define BUSREST_IO_END          0x7ffff#define BUSREST_MEM_START       0x4000000#define BUSREST_MEM_END        0x10000000static void reconfigure_pci(void) {   pci_resource *r;   struct pci_dev *dev;   /* FIXME: for now memory is relocated from low, it's better    * to start from higher addresses.    */   /*   init_free_area(&pci->io, 0x10000, 0x7fffff, 0xfff, 0);   init_free_area(&pci->mem, 0x1000000, 0x3cffffff, 0xfffff, 0);   */   init_free_area(&pci->io, BUS0_IO_START, BUS0_IO_END, 0xfff, 0);   init_free_area(&pci->mem, BUS0_MEM_START, BUS0_MEM_END, 0xfffff, 0);   /* First reconfigure the I/O space, this will be more    * complex when there is more than 1 bus. And 64 bits     * devices are another kind of problems.     */   reconfigure_bus_space(0, PCI_AREA_IO, &pci->io);   reconfigure_bus_space(0, PCI_AREA_MEMORY, &pci->mem);   reconfigure_bus_space(0, PCI_AREA_PREFETCHABLE, &pci->mem);   /* Now we have to touch the configuration space of all    * the devices to remap them better than they are right now.    * This is done in 3 steps:     * 1) first disable I/O and memory response of all devices    * 2) modify the base registers    * 3) restore the original PCI_COMMAND register.    */   for (r=pci->resources; r; r= r->next) {      if (!r->dev->sysdata) {         r->dev->sysdata=r;         pci_read_config_word(r->dev, PCI_COMMAND, &r->cmd);         pci_write_config_word(r->dev, PCI_COMMAND,                               r->cmd & ~(PCI_COMMAND_IO|                                          PCI_COMMAND_MEMORY));      }   }   for (r=pci->resources; r; r= r->next) {      pci_write_config_dword(r->dev,                              PCI_BASE_ADDRESS_0+(r->reg<<2),                             r->base);      if ((r->type&           (PCI_BASE_ADDRESS_SPACE|            PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==           (PCI_BASE_ADDRESS_SPACE_MEMORY|           PCI_BASE_ADDRESS_MEM_TYPE_64)) {         pci_write_config_dword(r->dev,                                PCI_BASE_ADDRESS_1+(r->reg<<2),                                0);      }   }   for (dev=bd->pci_devices; dev; dev= dev->next) {      if (dev->sysdata) {         pci_write_config_word(dev, PCI_COMMAND,                               ((pci_resource *)dev->sysdata)                               ->cmd);         dev->sysdata=NULL;      }   }}static intindirect_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, 			      unsigned char offset, unsigned char *val) {   out_be32(pci->config_addr,             0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));   *val=in_8(pci->config_data + (offset&3));   return PCIBIOS_SUCCESSFUL;}static intindirect_pci_read_config_word(unsigned char bus, unsigned char dev_fn, 			      unsigned char offset, unsigned short *val) {   *val = 0xffff;    if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;   out_be32(pci->config_addr,             0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));   *val=in_le16((volatile u_short *)(pci->config_data + (offset&3)));   return PCIBIOS_SUCCESSFUL;}static intindirect_pci_read_config_dword(unsigned char bus, unsigned char dev_fn,                                unsigned char offset, unsigned int *val) {   *val = 0xffffffff;    if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;   out_be32(pci->config_addr,             0x80|(bus<<8)|(dev_fn<<16)|(offset<<24));   *val=in_le32((volatile u_int *)pci->config_data);   return PCIBIOS_SUCCESSFUL;}static intindirect_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, 			       unsigned char offset, unsigned char val) {   out_be32(pci->config_addr,             0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));   out_8(pci->config_data + (offset&3), val);   return PCIBIOS_SUCCESSFUL;}static intindirect_pci_write_config_word(unsigned char bus, unsigned char dev_fn, 			       unsigned char offset, unsigned short val) {   if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;   out_be32(pci->config_addr,             0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));   out_le16((volatile u_short *)(pci->config_data + (offset&3)), val);   return PCIBIOS_SUCCESSFUL;}static intindirect_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, 				unsigned char offset, unsigned int val) {   if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;   out_be32(pci->config_addr,             0x80|(bus<<8)|(dev_fn<<16)|(offset<<24));   out_le32((volatile u_int *)pci->config_data, val);   return PCIBIOS_SUCCESSFUL;}static const struct pci_config_access_functions indirect_functions = {   indirect_pci_read_config_byte,   indirect_pci_read_config_word,   indirect_pci_read_config_dword,   indirect_pci_write_config_byte,   indirect_pci_write_config_word,   indirect_pci_write_config_dword};static intdirect_pci_read_config_byte(unsigned char bus, unsigned char dev_fn,                             unsigned char offset, unsigned char *val) {   if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {      *val=0xff;      return PCIBIOS_DEVICE_NOT_FOUND;   }   *val=in_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)              + (PCI_FUNC(dev_fn)<<8) + offset);   return PCIBIOS_SUCCESSFUL;}static intdirect_pci_read_config_word(unsigned char bus, unsigned char dev_fn,                             unsigned char offset, unsigned short *val) {   *val = 0xffff;    if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;   if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {      return PCIBIOS_DEVICE_NOT_FOUND;   }   *val=in_le16((volatile u_short *)                (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)                 + (PCI_FUNC(dev_fn)<<8) + offset));   return PCIBIOS_SUCCESSFUL;}static intdirect_pci_read_config_dword(unsigned char bus, unsigned char dev_fn,                              unsigned char offset, unsigned int *val) {   *val = 0xffffffff;    if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;   if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {      return PCIBIOS_DEVICE_NOT_FOUND;   }   *val=in_le32((volatile u_int *)                (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)                 + (PCI_FUNC(dev_fn)<<8) + offset));   return PCIBIOS_SUCCESSFUL;}static intdirect_pci_write_config_byte(unsigned char bus, unsigned char dev_fn,                              unsigned char offset, unsigned char val) {   if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {      return PCIBIOS_DEVICE_NOT_FOUND;   }   out_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)          + (PCI_FUNC(dev_fn)<<8) + offset,          val);   return PCIBIOS_SUCCESSFUL;}static intdirect_pci_write_config_word(unsigned char bus, unsigned char dev_fn,                              unsigned char offset, unsigned short val) {   if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;   if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {      return PCIBIOS_DEVICE_NOT_FOUND;   }   out_le16((volatile u_short *)            (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)             + (PCI_FUNC(dev_fn)<<8) + offset),            val);   return PCIBIOS_SUCCESSFUL;}static intdirect_pci_write_config_dword(unsigned char bus, unsigned char dev_fn,                               unsigned char offset, unsigned int val) {   if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;   if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {      return PCIBIOS_DEVICE_NOT_FOUND;   }   out_le32((volatile u_int *)            (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)             + (PCI_FUNC(dev_fn)<<8) + offset),            val);   return PCIBIOS_SUCCESSFUL;}static const struct pci_config_access_functions direct_functions = {   direct_pci_read_config_byte,   direct_pci_read_config_word,   direct_pci_read_config_dword,   direct_pci_write_config_byte,   direct_pci_write_config_word,   direct_pci_write_config_dword};void pci_read_bases(struct pci_dev *dev, unsigned int howmany){   unsigned int reg, nextreg;#define REG (PCI_BASE_ADDRESS_0 + (reg<<2))   u_short cmd;   u32 l, ml;   pci_read_config_word(dev, PCI_COMMAND, &cmd);   for(reg=0; reg<howmany; reg=nextreg)    {      pci_resource *r;      nextreg=reg+1;      pci_read_config_dword(dev, REG, &l);#if 0      if (l == 0xffffffff /*AJF || !l*/) continue; #endif      /* Note that disabling the memory response of a host bridge        * would lose data if a DMA transfer were in progress. In a        * bootloader we don't care however. Also we can't print any        * message for a while since we might just disable the console.       */      pci_write_config_word(dev, PCI_COMMAND, cmd &                             ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));      pci_write_config_dword(dev, REG, ~0);      pci_read_config_dword(dev, REG, &ml);      pci_write_config_dword(dev, REG, l);      /* Reenable the device now that we've played with        * base registers.        */      pci_write_config_word(dev, PCI_COMMAND, cmd);      /* seems to be an unused entry skip it */      if ( ml == 0 || ml == 0xffffffff ) continue;      if ((l &            (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK))          == (PCI_BASE_ADDRESS_MEM_TYPE_64              |PCI_BASE_ADDRESS_SPACE_MEMORY)) {         nextreg=reg+2;      }      dev->base_address[reg] = l;      r = salloc(sizeof(pci_resource));      if (!r) {         printk("Error allocating pci_resource struct.\n");         continue;      }      r->dev = dev;      r->reg = reg;      if ((l&PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {         r->type = l&~PCI_BASE_ADDRESS_IO_MASK;         r->base = l&PCI_BASE_ADDRESS_IO_MASK;         /* r->size = ~(ml&PCI_BASE_ADDRESS_IO_MASK)+1; */      } else {         r->type = l&~PCI_BASE_ADDRESS_MEM_MASK;         r->base = l&PCI_BASE_ADDRESS_MEM_MASK;         /* r->size = ~(ml&PCI_BASE_ADDRESS_MEM_MASK)+1; */      }      /* find the first bit set to one after the base         address type bits to find length of region */      {         unsigned int c= 16 , val= 0;         while( !(val= ml & c) ) c <<= 1;         r->size = val;      }#ifdef PCI_DEBUG      printk("   readbase bus %d, (%04x:%04x), base %08x, size %08x, type %d\n",             r->dev->bus->number,              r->dev->vendor,             r->dev->device,             r->base,             r->size,             r->type );#endif      /* Check for the blacklisted entries */      insert_resource(r);   }}u_int pci_scan_bus(struct pci_bus *bus){   unsigned int devfn, l, max, class;   unsigned char irq, hdr_type, is_multi = 0;   struct pci_dev *dev, **bus_last;   struct pci_bus *child;#if 0   printk("scanning pci bus %d\n", bus->number );#endif   bus_last = &bus->devices;   max = bus->secondary;   for (devfn = 0; devfn < 0xff; ++devfn) {      if (PCI_FUNC(devfn) && !is_multi) {         /* not a multi-function device */         continue;      }      if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type))         continue;      if (!PCI_FUNC(devfn))         is_multi = hdr_type & 0x80;      if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) ||          /* some broken boards return 0 if a slot is empty: */          l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) {         is_multi = 0;         continue;      }      dev = salloc(sizeof(*dev));      dev->bus = bus;      dev->devfn  = devfn;      dev->vendor = l & 0xffff;      dev->device = (l >> 16) & 0xffff;      pcibios_read_config_dword(bus->number, devfn,                                 PCI_CLASS_REVISION, &class);      class >>= 8;				    /* upper 3 bytes */      dev->class = class;      class >>= 8;      dev->hdr_type = hdr_type;      switch (hdr_type & 0x7f) {		    /* header type */         case PCI_HEADER_TYPE_NORMAL:		    /* standard header */            if (class == PCI_CLASS_BRIDGE_PCI)               goto bad;            /*             * If the card generates interrupts, read IRQ number             * (some architectures change it during pcibios_fixup())             */            pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq);            if (irq)               pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);            dev->irq = irq;            /*             * read base address registers, again pcibios_fixup() can             * tweak these             */            pci_read_bases(dev, 6);            pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l);            dev->rom_address = (l == 0xffffffff) ? 0 : l;            break;         case PCI_HEADER_TYPE_BRIDGE:		    /* bridge header */            if (class != PCI_CLASS_BRIDGE_PCI)               goto bad;            pci_read_bases(dev, 2);            pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l);            dev->rom_address = (l == 0xffffffff) ? 0 : l;            break;         case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */            if (class != PCI_CLASS_BRIDGE_CARDBUS)               goto bad;            pci_read_bases(dev, 1);            break;         default:				    /* unknown header */        bad:            printk("PCI device with unknown header type %d ignored.\n",                   hdr_type&0x7f);            continue;      }      /*       * Put it into the global PCI device chain. It's used to       * find devices once everything is set up.       */      *pci->last_dev_p = dev;      pci->last_dev_p = &dev->next;      /*       * Now insert it into the list of devices held       * by the parent bus.       */      *bus_last = dev;      bus_last = &dev->sibling;   }   /*    * After performing arch-dependent fixup of the bus, look behind    * all PCI-to-PCI bridges on this bus.    */   for(dev=bus->devices; dev; dev=dev->sibling)      /*       * If it's a bridge, scan the bus behind it.       */      if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {         unsigned int buses;         unsigned int devfn = dev->devfn;         unsigned short cr;         /*          * Insert it into the tree of buses.          */         child = salloc(sizeof(*child));         child->next = bus->children;         bus->children = child;         child->self = dev;         child->parent = bus;         /*          * Set up the primary, secondary and subordinate          * bus numbers.          */         child->number = child->secondary = ++max;         child->primary = bus->secondary;         child->subordinate = 0xff;         /*          * Clear all status bits and turn off memory,          * I/O and master enables.          */         pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr);         pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000);         pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff);         /*          * Read the existing primary/secondary/subordinate bus          * number configuration to determine if the PCI bridge          * has already been configured by the system.  If so,          * do not modify the configuration, merely note it.          */         pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -