static int __devinit agp_nvidia_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; nvidia_private.dev_1 = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); nvidia_private.dev_2 = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); nvidia_private.dev_3 = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 " "chipset, but could not find the secondary devices.\n"); return -ENODEV; } cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) return -ENODEV; switch (pdev->device) { case PCI_DEVICE_ID_NVIDIA_NFORCE: printk(KERN_INFO PFX "Detected NVIDIA nForce chipset\n"); nvidia_private.wbc_mask = 0x00010000; break; case PCI_DEVICE_ID_NVIDIA_NFORCE2: printk(KERN_INFO PFX "Detected NVIDIA nForce2 chipset\n"); nvidia_private.wbc_mask = 0x80000000; break; default: printk(KERN_ERR PFX "Unsupported NVIDIA chipset (device id: %04x)\n", pdev->device); return -ENODEV; } bridge = agp_alloc_bridge(); if (!bridge) return -ENOMEM; bridge->driver = &nvidia_driver; bridge->dev_private_data = &nvidia_private, bridge->dev = pdev; bridge->capndx = cap_ptr; /* Fill in the mode register */ pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); }
static void ixdp2400_pci_postinit(void) { struct pci_dev *dev; if (ixdp2x00_master_npu()) { dev = pci_find_slot(1, IXDP2400_SLAVE_ENET_DEVFN); pci_remove_bus_device(dev); } else { dev = pci_find_slot(1, IXDP2400_MASTER_ENET_DEVFN); pci_remove_bus_device(dev); ixdp2x00_slave_pci_postinit(); } }
acpi_status acpi_os_write_pci_configuration ( acpi_pci_id *pci_id, u32 reg, NATIVE_UINT value, u32 width) { int devfn = PCI_DEVFN(pci_id->device, pci_id->function); struct pci_dev *dev = pci_find_slot(pci_id->bus, devfn); if (!dev) return AE_ERROR; switch (width) { case 8: if (pci_write_config_byte(dev, reg, value)) return AE_ERROR; break; case 16: if (pci_write_config_word(dev, reg, value)) return AE_ERROR; break; case 32: if (pci_write_config_dword(dev, reg, value)) return AE_ERROR; break; default: BUG(); } return AE_OK; }
VOID *RTMPFindHostPCIDev(VOID *pPciDevSrc) { struct pci_dev *pci_dev = (struct pci_dev *)pPciDevSrc; //struct pci_dev *parent_pci_dev; USHORT reg16; UCHAR reg8; UINT DevFn; PPCI_DEV pPci_dev; MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s.===>\n", __FUNCTION__)); //parent_pci_dev = NULL; if (pci_dev->bus->parent) { for (DevFn = 0; DevFn < 255; DevFn++) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) pPci_dev = pci_get_slot(pci_dev->bus->parent, DevFn); #else pPci_dev = pci_find_slot(pci_dev->bus->parent->number, DevFn); #endif if (pPci_dev) { pci_read_config_word(pPci_dev, PCI_CLASS_DEVICE, ®16); reg16 = le2cpu16(reg16); pci_read_config_byte(pPci_dev, PCI_CB_CARD_BUS, ®8); if ((reg16 == PCI_CLASS_BRIDGE_PCI) && (reg8 == pci_dev->bus->number)) return pPci_dev; } } } return NULL; }
static int dhahelper_free_irq(dhahelper_irq_t *arg) { dhahelper_irq_t irq; struct pci_dev *pci; int irqn; if (copy_from_user(&irq, arg, sizeof(dhahelper_irq_t))) { if (dhahelper_verbosity > 0) printk(KERN_ERR "dhahelper: failed copy from userspace\n"); return -EFAULT; } pci = pci_find_slot(irq.bus, PCI_DEVFN(irq.dev, irq.func)); if(!pci) return -EINVAL; irqn = pci->irq; spin_lock_irqsave(&dha_irqs[irqn].lock, dha_irqs[irqn].flags); if(dha_irqs[irqn].handled) { free_irq(irqn, pci); dha_irqs[irqn].handled = 0; printk("IRQ %i: %li\n", irqn, dha_irqs[irqn].count); } spin_unlock_irqrestore(&dha_irqs[irqn].lock, dha_irqs[irqn].flags); return 0; }
int pcidata_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *data) { int i, pos=0; int bus, devfn; if (!pcibios_present()) return sprintf(buf,"No PCI bios present\n"); /* * This code is derived from "drivers/pci/pci.c". This means that * the GPL applies to this source file and credit is due to the * original authors (Drew Eckhardt, Frederic Potter, David * Mosberger-Tang) */ for (bus=0; !bus; bus++) { /* only bus 0 :-) */ for (devfn=0; devfn < 0x100 && pos < PAGE_SIZE/2; devfn++) { struct pci_dev *dev = NULL; dev = pci_find_slot(bus, devfn); if (!dev) continue; /* Ok, we've found a device, copy its cfg space to the buffer*/ for (i=0; i<256; i += sizeof(u32), pos += sizeof(u32)) pci_read_config_dword(dev,i,(u32 *)(buf+pos)); pci_release_device(dev); /* 2.0 compatibility */ } } *eof=1; return pos; }
/* * It looks like the master IOC3 is usually on bus 0, device 4. Hope * that's right */ static __init int efi_ioc3_time_init(void) { struct pci_dev *dev; static struct ioc3 *ioc3; dev = pci_find_slot(0, PCI_DEVFN(4, 0)); if (!dev) { printk(KERN_CRIT "Couldn't find master IOC3\n"); return -ENODEV; } ioc3 = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0)); nvram_base = (unsigned long) ioc3 + IOC3_BYTEBUS_DEV0; tod_chip_type = get_tod_chip_type(); if (tod_chip_type == 1) printk(KERN_NOTICE "TOD type is SGS M48T35\n"); else if (tod_chip_type == 2) printk(KERN_NOTICE "TOD type is Dallas DS1386\n"); else printk(KERN_CRIT "No or unknown TOD\n"); efi.get_time = ioc3_get_time; efi.set_time = ioc3_set_time; efi.get_wakeup_time = ioc3_get_wakeup_time; efi.set_wakeup_time = ioc3_set_wakeup_time; return 0; }
static int __devinit hc_found_ohci (struct pci_dev *dev, int irq, void *mem_base, const struct pci_device_id *id) { unsigned long flags = id->driver_data; printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name); /* Check for NSC87560. We have to look at the bridge (fn1) to identify the USB (fn2). This quirk might apply to more or even all NSC stuff I don't know.. */ if(dev->vendor == PCI_VENDOR_ID_NS) { struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1)); if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO) flags |= OHCI_QUIRK_SUCKYIO; } if (flags & OHCI_QUIRK_SUCKYIO) printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n"); if (flags & OHCI_QUIRK_AMD756) printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); return hc_add_ohci(dev, irq, mem_base, flags, ohci_pci_driver.name, dev->slot_name); }
static dev_node_t *serial_attach(dev_locator_t *loc) { u_int io; u_char irq; int line; struct serial_struct serial; struct pci_dev *pdev; dev_node_t *node; MOD_INC_USE_COUNT; if (loc->bus != LOC_PCI) goto err_out; pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn); if (!pdev) goto err_out; if (pci_enable_device(pdev)) goto err_out; printk(KERN_INFO "serial_attach(bus %d, fn %d)\n", pdev->bus->number, pdev->devfn); io = pci_resource_start (pdev, 0); irq = pdev->irq; if (!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) { printk(KERN_NOTICE "serial_cb: PCI base address 0 is not IO\n"); goto err_out; } device_setup(pdev, io); memset(&serial, 0, sizeof(serial)); serial.port = io; serial.irq = irq; serial.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ; /* Some devices seem to need extra time */ __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/50); line = register_serial(&serial); if (line < 0) { printk(KERN_NOTICE "serial_cb: register_serial() at 0x%04x, " "irq %d failed\n", serial.port, serial.irq); goto err_out; } node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); if (!node) goto err_out_unregister; sprintf(node->dev_name, "ttyS%d", line); node->major = TTY_MAJOR; node->minor = 0x40 + line; node->next = NULL; return node; err_out_unregister: unregister_serial(line); err_out: MOD_DEC_USE_COUNT; return NULL; }
asmlinkage long sys_pciconfig_write(unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len, void __user *buf) { struct pci_dev *dev; u8 byte; u16 word; u32 dword; int err = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; dev = pci_find_slot(bus, dfn); if (!dev) return -ENODEV; lock_kernel(); switch(len) { case 1: err = get_user(byte, (u8 __user *)buf); if (err) break; err = pci_write_config_byte(dev, off, byte); if (err != PCIBIOS_SUCCESSFUL) err = -EIO; break; case 2: err = get_user(word, (u16 __user *)buf); if (err) break; err = pci_write_config_word(dev, off, word); if (err != PCIBIOS_SUCCESSFUL) err = -EIO; break; case 4: err = get_user(dword, (u32 __user *)buf); if (err) break; err = pci_write_config_dword(dev, off, dword); if (err != PCIBIOS_SUCCESSFUL) err = -EIO; break; default: err = -EINVAL; break; }; unlock_kernel(); return err; }
static int __init cpcihp_generic_init(void) { int status; struct resource* r; struct pci_dev* dev; info(DRIVER_DESC " version: " DRIVER_VERSION); status = validate_parameters(); if(status != 0) return status; r = request_region(port, 1, "#ENUM hotswap signal register"); if(!r) return -EBUSY; dev = pci_find_slot(bridge_busnr, PCI_DEVFN(bridge_slot, 0)); if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { err("Invalid bridge device %s", bridge); return -EINVAL; } bus = dev->subordinate; memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller)); generic_hpc_ops.query_enum = query_enum; generic_hpc.ops = &generic_hpc_ops; status = cpci_hp_register_controller(&generic_hpc); if(status != 0) { err("Could not register cPCI hotplug controller"); return -ENODEV; } dbg("registered controller"); status = cpci_hp_register_bus(bus, first_slot, last_slot); if(status != 0) { err("Could not register cPCI hotplug bus"); goto init_bus_register_error; } dbg("registered bus"); status = cpci_hp_start(); if(status != 0) { err("Could not started cPCI hotplug system"); goto init_start_error; } dbg("started cpci hp system"); return 0; init_start_error: cpci_hp_unregister_bus(bus); init_bus_register_error: cpci_hp_unregister_controller(&generic_hpc); err("status = %d", status); return status; }
int __init ixdp2800_pci_init(void) { if (machine_is_ixdp2800()) { struct pci_dev *dev; pci_common_init(&ixdp2800_pci); if (ixdp2x00_master_npu()) { dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN); pci_remove_bus_device(dev); ixdp2800_master_enable_slave(); ixdp2800_master_wait_for_slave_bus_scan(); } else { dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN); pci_remove_bus_device(dev); } } return 0; }
static int via_get_revision(void) { u8 rev; struct pci_dev* dev; dev = pci_find_slot(0,0); if (dev == NULL) return 0; pci_read_config_byte(dev, 0xf6, &rev); return rev; }
/** * edd_get_pci_dev() - finds pci_dev that matches edev * @edev - edd_device * * Returns pci_dev if found, or NULL */ static struct pci_dev * edd_get_pci_dev(struct edd_device *edev) { struct edd_info *info = edd_dev_get_info(edev); if (edd_dev_is_type(edev, "PCI")) { return pci_find_slot(info->params.interface_path.pci.bus, PCI_DEVFN(info->params.interface_path.pci.slot, info->params.interface_path.pci. function)); } return NULL; }
int drm_irq_busid(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_irq_busid_t p; struct pci_dev *dev; if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p))) return -EFAULT; dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum)); if (dev) p.irq = dev->irq; else p.irq = 0; DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq); if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p))) return -EFAULT; return 0; }
void __init nautilus_init_pci(void) { struct pci_controller *hose = hose_head; struct pci_bus *bus; struct pci_dev *dev; unsigned long bus_align, bus_size, pci_mem; unsigned long memtop = max_low_pfn << PAGE_SHIFT; /* Scan our single hose. */ bus = pci_scan_bus(0, alpha_mv.pci_ops, hose); hose->bus = bus; hose->last_busno = bus->subordinate; bus->self = pci_find_slot(0, 0); bus->resource[1] = &irongate_mem; pbus_size_bridges(bus); /* IO port range. */ bus->resource[0]->start = 0; bus->resource[0]->end = 0xffff; /* Set up PCI memory range - limit is hardwired to 0xffffffff, base must be at aligned to 16Mb. */ bus_align = bus->resource[1]->start; bus_size = bus->resource[1]->end + 1 - bus_align; if (bus_align < 0x1000000UL) bus_align = 0x1000000UL; pci_mem = (0x100000000UL - bus_size) & -bus_align; bus->resource[1]->start = pci_mem; bus->resource[1]->end = 0xffffffffUL; if (request_resource(&iomem_resource, bus->resource[1]) < 0) printk(KERN_ERR "Failed to request MEM on hose 0\n"); if (pci_mem < memtop) memtop = pci_mem; if (memtop > alpha_mv.min_mem_address) { free_reserved_mem(__va(alpha_mv.min_mem_address), __va(memtop)); printk("nautilus_init_pci: %ldk freed\n", (memtop - alpha_mv.min_mem_address) >> 10); }
VOID *RTMPFindHostPCIDev( IN VOID *pPciDevSrc) { struct pci_dev *pci_dev = (struct pci_dev *)pPciDevSrc; struct pci_dev *parent_pci_dev; USHORT reg16; UCHAR reg8; UINT DevFn; PPCI_DEV pPci_dev; /* POS_COOKIE pObj; */ /* pObj = (POS_COOKIE) pAd->OS_Cookie; */ /* if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) */ /* return; */ DBGPRINT(RT_DEBUG_TRACE, ("%s.===>\n", __FUNCTION__)); parent_pci_dev = NULL; if (pci_dev->bus->parent) { for (DevFn = 0; DevFn < 255; DevFn++) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) pPci_dev = pci_get_slot(pci_dev->bus->parent, DevFn); #else pPci_dev = pci_find_slot(pci_dev->bus->parent->number, DevFn); #endif if (pPci_dev) { pci_read_config_word(pPci_dev, PCI_CLASS_DEVICE, ®16); reg16 = le2cpu16(reg16); pci_read_config_byte(pPci_dev, PCI_CB_CARD_BUS, ®8); if ((reg16 == PCI_CLASS_BRIDGE_PCI) && (reg8 == pci_dev->bus->number)) { return pPci_dev; } } } } return NULL; }
__initfunc(int safl_scan(void)) { if (pcibios_present()) { int index; /* * Search for an EBSA-285 board or an IOP board. Stop at * first one found. */ for (index = 0; index < 8; index++) { if (pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21554, index, &safl_pci_bus, &safl_pci_devfn) == PCIBIOS_SUCCESSFUL) { safl_devid = PCI_DEVICE_ID_DEC_21554; break; } if (pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, index, &safl_pci_bus, &safl_pci_devfn) == PCIBIOS_SUCCESSFUL) { safl_devid = PCI_DEVICE_ID_DEC_21285; break; } } if (index < 8) { #ifdef PCI_SUPPORT_VER2 safl_pdev = pci_find_slot(safl_pci_bus, safl_pci_devfn); #endif misc_register(&safl_dev); return 0; } } if (safl_debug) printk(KERN_INFO "Can't find device.\n"); return -ENODEV; }
static int oprompci2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data) { int err = -EINVAL; if (bufsize >= 2*sizeof(int)) { #ifdef CONFIG_PCI struct pci_dev *pdev; struct pcidev_cookie *pcp; pdev = pci_find_slot (((int *) op->oprom_array)[0], ((int *) op->oprom_array)[1]); pcp = pdev->sysdata; if (pcp != NULL) { dp = pcp->prom_node; data->current_node = dp; *((int *)op->oprom_array) = dp->node; op->oprom_size = sizeof(int); err = copyout(argp, op, bufsize + sizeof(int)); } #endif } return err; }
int awc4500_pci_probe(struct net_device *dev) { int cards_found = 0; static int pci_index; /* Static, for multiple probe calls. */ u8 pci_irq_line = 0; // int p; unsigned char awc_pci_dev, awc_pci_bus; if (!pci_present()) return -1; for (; pci_index < 0xff; pci_index++) { u16 vendor, device, pci_command, new_command; u32 pci_memaddr; u32 pci_ioaddr; u32 pci_cisaddr; struct pci_dev *pdev; if (pcibios_find_class (PCI_CLASS_NETWORK_OTHER << 8, reverse_probe ? 0xfe - pci_index : pci_index, &awc_pci_bus, &awc_pci_dev) != PCIBIOS_SUCCESSFUL) { if (reverse_probe) { continue; } else { break; } } pdev = pci_find_slot(awc_pci_bus, awc_pci_dev); if (!pdev) continue; if (pci_enable_device(pdev)) continue; vendor = pdev->vendor; device = pdev->device; pci_irq_line = pdev->irq; pci_memaddr = pci_resource_start (pdev, 0); pci_cisaddr = pci_resource_start (pdev, 1); pci_ioaddr = pci_resource_start (pdev, 2); // printk("\n pci capabilities %x and ptr %x \n",pci_caps,pci_caps_ptr); /* Remove I/O space marker in bit 0. */ if (vendor != PCI_VENDOR_ID_AIRONET) continue; if (device != PCI_DEVICE_AIRONET_4800_1 && device != PCI_DEVICE_AIRONET_4800 && device != PCI_DEVICE_AIRONET_4500 ) continue; // if (check_region(pci_ioaddr, AIRONET4X00_IO_SIZE) || // check_region(pci_cisaddr, AIRONET4X00_CIS_SIZE) || // check_region(pci_memaddr, AIRONET4X00_MEM_SIZE)) { // printk(KERN_ERR "aironet4X00 mem addrs not available for maping \n"); // continue; // } if (!request_region(pci_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr")) continue; // request_region(pci_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis"); // request_region(pci_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem"); mdelay(10); pci_read_config_word(pdev, PCI_COMMAND, &pci_command); new_command = pci_command | PCI_COMMAND_SERR; if (pci_command != new_command) pci_write_config_word(pdev, PCI_COMMAND, new_command); /* if (device == PCI_DEVICE_AIRONET_4800) pci_write_config_dword(pdev, 0x40, 0x00000000); udelay(1000); */ if (device == PCI_DEVICE_AIRONET_4800) pci_write_config_dword(pdev, 0x40, 0x40000000); if (awc_pci_init(dev, pdev, pci_ioaddr,pci_cisaddr,pci_memaddr,pci_irq_line)) { printk(KERN_ERR "awc4800 pci init failed \n"); break; } dev = 0; cards_found++; } return cards_found ? 0 : -ENODEV; }
int mac53c94_detect(Scsi_Host_Template *tp) { struct device_node *node; int nfscs; struct fsc_state *state, **prev_statep; struct Scsi_Host *host; void *dma_cmd_space; unsigned char *clkprop; int proplen; struct pci_dev *pdev; u8 pbus, devfn; nfscs = 0; prev_statep = &all_53c94s; for (node = find_devices("53c94"); node != 0; node = node->next) { if (node->n_addrs != 2 || node->n_intrs != 2) { printk(KERN_ERR "mac53c94: expected 2 addrs and intrs" " (got %d/%d) for node %s\n", node->n_addrs, node->n_intrs, node->full_name); continue; } pdev = NULL; if (node->parent != NULL && !pci_device_from_OF_node(node->parent, &pbus, &devfn)) pdev = pci_find_slot(pbus, devfn); if (pdev == NULL) { printk(KERN_ERR "mac53c94: can't find PCI device " "for %s\n", node->full_name); continue; } host = scsi_register(tp, sizeof(struct fsc_state)); if (host == NULL) break; host->unique_id = nfscs; state = (struct fsc_state *) host->hostdata; if (state == 0) { /* "can't happen" */ printk(KERN_ERR "mac53c94: no state for %s?!\n", node->full_name); scsi_unregister(host); break; } state->host = host; state->pdev = pdev; state->regs = (volatile struct mac53c94_regs *) ioremap(node->addrs[0].address, 0x1000); state->intr = node->intrs[0].line; state->dma = (volatile struct dbdma_regs *) ioremap(node->addrs[1].address, 0x1000); state->dmaintr = node->intrs[1].line; if (state->regs == NULL || state->dma == NULL) { printk(KERN_ERR "mac53c94: ioremap failed for %s\n", node->full_name); if (state->dma != NULL) iounmap(state->dma); if (state->regs != NULL) iounmap(state->regs); scsi_unregister(host); break; } clkprop = get_property(node, "clock-frequency", &proplen); if (clkprop == NULL || proplen != sizeof(int)) { printk(KERN_ERR "%s: can't get clock frequency, " "assuming 25MHz\n", node->full_name); state->clk_freq = 25000000; } else state->clk_freq = *(int *)clkprop; /* Space for dma command list: +1 for stop command, +1 to allow for aligning. */ dma_cmd_space = kmalloc((host->sg_tablesize + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL); if (dma_cmd_space == 0) { printk(KERN_ERR "mac53c94: couldn't allocate dma " "command space for %s\n", node->full_name); goto err_cleanup; } state->dma_cmds = (struct dbdma_cmd *) DBDMA_ALIGN(dma_cmd_space); memset(state->dma_cmds, 0, (host->sg_tablesize + 1) * sizeof(struct dbdma_cmd)); state->dma_cmd_space = dma_cmd_space; *prev_statep = state; prev_statep = &state->next; if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94", state)) { printk(KERN_ERR "mac53C94: can't get irq %d for %s\n", state->intr, node->full_name); err_cleanup: iounmap(state->dma); iounmap(state->regs); scsi_unregister(host); break; } mac53c94_init(state); ++nfscs; } return nfscs; }
static int __devinit hc_found_ohci (struct pci_dev *dev, int irq, void *mem_base, const struct pci_device_id *id) { ohci_t * ohci; char buf[8], *bufp = buf; int ret; #ifndef __sparc__ sprintf(buf, "%d", irq); #else bufp = __irq_itoa(irq); #endif printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n", (unsigned long) mem_base, bufp); printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name); ohci = hc_alloc_ohci (dev, mem_base); if (!ohci) { return -ENOMEM; } if ((ret = ohci_mem_init (ohci)) < 0) { hc_release_ohci (ohci); return ret; } ohci->flags = id->driver_data; /* Check for NSC87560. We have to look at the bridge (fn1) to identify the USB (fn2). This quirk might apply to more or even all NSC stuff I don't know.. */ if(dev->vendor == PCI_VENDOR_ID_NS) { struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1)); if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO) ohci->flags |= OHCI_QUIRK_SUCKYIO; } if (ohci->flags & OHCI_QUIRK_SUCKYIO) printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n"); if (ohci->flags & OHCI_QUIRK_AMD756) printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); if (hc_reset (ohci) < 0) { hc_release_ohci (ohci); return -ENODEV; } /* FIXME this is a second HC reset; why?? */ writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control); wait_ms (10); usb_register_bus (ohci->bus); if (request_irq (irq, hc_interrupt, SA_SHIRQ, ohci_pci_driver.name, ohci) != 0) { err ("request interrupt %s failed", bufp); hc_release_ohci (ohci); return -EBUSY; } ohci->irq = irq; if (hc_start (ohci) < 0) { err ("can't start usb-%s", dev->slot_name); hc_release_ohci (ohci); return -EBUSY; } #ifdef DEBUG ohci_dump (ohci, 1); #endif return 0; }
static int __devinit ohci_pci_start (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) { struct pci_dev *pdev = to_pci_dev(hcd->self.controller); /* AMD 756, for most chips (early revs), corrupts register * values on read ... so enable the vendor workaround. */ if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x740c) { ohci->flags = OHCI_QUIRK_AMD756; ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); // also somewhat erratum 10 (suspend/resume issues) } /* FIXME for some of the early AMD 760 southbridges, OHCI * won't work at all. blacklist them. */ /* Apple's OHCI driver has a lot of bizarre workarounds * for this chip. Evidently control and bulk lists * can get confused. (B&W G3 models, and ...) */ else if (pdev->vendor == PCI_VENDOR_ID_OPTI && pdev->device == 0xc861) { ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n"); } /* Check for NSC87560. We have to look at the bridge (fn1) to * identify the USB (fn2). This quirk might apply to more or * even all NSC stuff. */ else if (pdev->vendor == PCI_VENDOR_ID_NS) { struct pci_dev *b; b = pci_find_slot (pdev->bus->number, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO && b->vendor == PCI_VENDOR_ID_NS) { ohci->flags |= OHCI_QUIRK_SUPERIO; ohci_dbg (ohci, "Using NSC SuperIO setup\n"); } } /* Check for Compaq's ZFMicro chipset, which needs short * delays before control or bulk queues get re-activated * in finish_unlinks() */ else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ && pdev->device == 0xa0f8) { ohci->flags |= OHCI_QUIRK_ZFMICRO; ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n"); } } /* NOTE: there may have already been a first reset, to * keep bios/smm irqs from making trouble */ if ((ret = ohci_run (ohci)) < 0) { ohci_err (ohci, "can't start\n"); ohci_stop (hcd); return ret; } return 0; }
static int pcicommand(pcidata* x) { struct pci_dev* sh=(struct pci_dev*)x->starthandle; switch(x->command) { case CMD_FIND_SLOT: x->handle=(unsigned long)pci_find_slot(x->busnum, PCI_DEVFN(x->devnum,x->funnum)); return 0; case CMD_FIND_SUBSYS: x->handle=(unsigned long)pci_find_subsys(x->vendor, x->device, x->subsys_vendor, x->subsys_device, sh); return 0; case CMD_FIND_DEVICE: x->handle=(unsigned long)pci_find_device(x->vendor, x->device, sh); return 0; case CMD_FIND_CLASS: x->handle=(unsigned long)pci_find_class(x->class, sh); return 0; case CMD_FIND_CAPAB: x->cappos=pci_find_capability(sh, x->capability); return 0; case CMD_SET_POWER: x->oldpowerstate=pci_set_power_state(sh, x->powerstate); return 0; case CMD_ENABLE: x->result=pci_enable_device(sh); return 0; case CMD_DISABLE: pci_disable_device(sh); return 0; case CMD_RELEASE: release_device(sh,0); return 0; case CMD_REQUEST: { char* name; if (x->res_name) { int len; char c; int i; len=0; while (!COPY_FROM_USER(&c, x->res_name+len,1)) { if (!c) break; len++; } name=kmalloc(len+1,GFP_KERNEL); for (i=0;i<len;i++) { name[i]=0; COPY_FROM_USER(name+i, x->res_name+i,1); } name[i]=0; } else { name=kmalloc(22,GFP_KERNEL); strcpy(name,"amithlon pci system"); } x->result=pci_request_regions(sh,name); if (!x->result) { /* Successful */ pci_list* n=kmalloc(sizeof(pci_list),GFP_KERNEL); n->dev=sh; if (x->releasecode) { int size=find_code_size(x->releasecode); n->releasecode=kmalloc(size,GFP_KERNEL); COPY_FROM_USER(n->releasecode,x->releasecode,size); } else n->releasecode=NULL; n->name=name; n->next=devlist; n->prev_p=&devlist; if (devlist) devlist->prev_p=&(n->next); devlist=n; } else { kfree(name); } } return 0; case CMD_READBYTE: x->confdata=0; x->result=pci_read_config_byte(sh, x->offset, (u8*)&(x->confdata)); return 0; case CMD_READWORD: x->confdata=0; x->result=pci_read_config_word(sh, x->offset, (u16*)&(x->confdata)); return 0; case CMD_READLONG: x->confdata=0; x->result=pci_read_config_dword(sh, x->offset, (u32*)&(x->confdata)); return 0; case CMD_WRITEBYTE: x->result=pci_write_config_byte(sh, x->offset, (u8)(x->confdata)); return 0; case CMD_WRITEWORD: x->result=pci_write_config_word(sh, x->offset, (u16)(x->confdata)); return 0; case CMD_WRITELONG: x->result=pci_write_config_dword(sh, x->offset, (u32)(x->confdata)); return 0; case CMD_GETBASE: x->start=sh->resource[x->basenum].start; x->end=sh->resource[x->basenum].end; x->flags=sh->resource[x->basenum].flags; return 0; case CMD_GETINFO: x->irq=sh->irq; x->devnum=PCI_SLOT(sh->devfn); x->funnum=PCI_FUNC(sh->devfn); x->busnum=sh->bus->number; return 0; case CMD_GETNAME: { int len=0; do { if (COPY_TO_USER((void*)(x->res_name+len),(void*)(sh->name+len),1)) return -EFAULT; } while (sh->name[len++]); } return 0; default: return -EINVAL; } }
int acpi_pci_bind ( struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_pci_data *data = NULL; struct acpi_pci_data *pdata = NULL; char *pathname = NULL; struct acpi_buffer buffer = {0, NULL}; acpi_handle handle = NULL; ACPI_FUNCTION_TRACE("acpi_pci_bind"); if (!device || !device->parent) return_VALUE(-EINVAL); pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); if(!pathname) return_VALUE(-ENOMEM); memset(pathname, 0, ACPI_PATHNAME_MAX); buffer.length = ACPI_PATHNAME_MAX; buffer.pointer = pathname; data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); if (!data) { kfree (pathname); return_VALUE(-ENOMEM); } memset(data, 0, sizeof(struct acpi_pci_data)); acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", pathname)); /* * Segment & Bus * ------------- * These are obtained via the parent device's ACPI-PCI context. */ status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, (void**) &pdata); if (ACPI_FAILURE(status) || !pdata || !pdata->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid ACPI-PCI context for parent device %s\n", acpi_device_bid(device->parent))); result = -ENODEV; goto end; } data->id.segment = pdata->id.segment; data->id.bus = pdata->bus->number; /* * Device & Function * ----------------- * These are simply obtained from the device's _ADR method. Note * that a value of zero is valid. */ data->id.device = device->pnp.bus_address >> 16; data->id.function = device->pnp.bus_address & 0xFFFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); /* * TBD: Support slot devices (e.g. function=0xFFFF). */ /* * Locate PCI Device * ----------------- * Locate matching device in PCI namespace. If it doesn't exist * this typically means that the device isn't currently inserted * (e.g. docking station, port replicator, etc.). */ data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function)); if (!data->dev) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); result = -ENODEV; goto end; } if (!data->dev->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); result = -ENODEV; goto end; } /* * PCI Bridge? * ----------- * If so, set the 'bus' field and install the 'bind' function to * facilitate callbacks for all of its children. */ if (data->dev->subordinate) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %02x:%02x:%02x.%02x is a PCI bridge\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); data->bus = data->dev->subordinate; device->ops.bind = acpi_pci_bind; device->ops.unbind = acpi_pci_unbind; } /* * Attach ACPI-PCI Context * ----------------------- * Thus binding the ACPI and PCI devices. */ status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to attach ACPI-PCI context to device %s\n", acpi_device_bid(device))); result = -ENODEV; goto end; } /* * PCI Routing Table * ----------------- * Evaluate and parse _PRT, if exists. This code is independent of * PCI bridges (above) to allow parsing of _PRT objects within the * scope of non-bridge devices. Note that _PRTs within the scope of * a PCI bridge assume the bridge's subordinate bus number. * * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? */ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_SUCCESS(status)) { if (data->bus) /* PCI-PCI bridge */ acpi_pci_irq_add_prt(device->handle, data->id.segment, data->bus->number); else /* non-bridge PCI device */ acpi_pci_irq_add_prt(device->handle, data->id.segment, data->id.bus); } end: kfree(pathname); if (result) kfree(data); return_VALUE(result); }
static int __devinit agp_serverworks_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_bridge_data *bridge; struct pci_dev *bridge_dev; u32 temp, temp2; u8 cap_ptr = 0; /* Everything is on func 1 here so we are hardcoding function one */ bridge_dev = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); if (!bridge_dev) { printk(KERN_INFO PFX "Detected a Serverworks chipset " "but could not find the secondary device.\n"); return -ENODEV; } cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); switch (pdev->device) { case 0x0006: /* ServerWorks CNB20HE Fail silently.*/ printk (KERN_ERR PFX "Detected ServerWorks CNB20HE chipset: No AGP present.\n"); return -ENODEV; case PCI_DEVICE_ID_SERVERWORKS_HE: case PCI_DEVICE_ID_SERVERWORKS_LE: case 0x0007: break; default: if (cap_ptr) printk(KERN_ERR PFX "Unsupported Serverworks chipset " "(device id: %04x)\n", pdev->device); return -ENODEV; } serverworks_private.svrwrks_dev = bridge_dev; serverworks_private.gart_addr_ofs = 0x10; pci_read_config_dword(pdev, SVWRKS_APSIZE, &temp); if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2); if (temp2 != 0) { printk(KERN_INFO PFX "Detected 64 bit aperture address, " "but top bits are not zero. Disabling agp\n"); return -ENODEV; } serverworks_private.mm_addr_ofs = 0x18; } else serverworks_private.mm_addr_ofs = 0x14; pci_read_config_dword(pdev, serverworks_private.mm_addr_ofs, &temp); if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { pci_read_config_dword(pdev, serverworks_private.mm_addr_ofs + 4, &temp2); if (temp2 != 0) { printk(KERN_INFO PFX "Detected 64 bit MMIO address, " "but top bits are not zero. Disabling agp\n"); return -ENODEV; } } bridge = agp_alloc_bridge(); if (!bridge) return -ENOMEM; bridge->driver = &sworks_driver; bridge->dev_private_data = &serverworks_private, bridge->dev = pdev; pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); }
static int pci_etherdev_probe(struct device *dev, struct pci_id_info pci_tbl[]) { int cards_found = 0; int pci_index = 0; unsigned char pci_bus, pci_device_fn; if ( ! pcibios_present()) return -ENODEV; for (;pci_index < 0xff; pci_index++) { u16 vendor, device, pci_command, new_command; int chip_idx, irq; long pciaddr; long ioaddr; if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) break; pcibios_read_config_word(pci_bus, pci_device_fn, PCI_VENDOR_ID, &vendor); pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &device); for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) if (vendor == pci_tbl[chip_idx].vendor_id && (device & pci_tbl[chip_idx].device_id_mask) == pci_tbl[chip_idx].device_id) break; if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ continue; { #if defined(PCI_SUPPORT_VER2) struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); #ifdef VIA_USE_IO pciaddr = pdev->base_address[0]; #else pciaddr = pdev->base_address[1]; #endif irq = pdev->irq; #else u32 pci_memaddr; u8 pci_irq_line; pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq_line); #ifdef VIA_USE_IO pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_memaddr); pciaddr = pci_memaddr; #else pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_memaddr); pciaddr = pci_memaddr; #endif irq = pci_irq_line; #endif } if (debug > 2) printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n", pci_tbl[chip_idx].name, pciaddr, irq); if (pci_tbl[chip_idx].flags & PCI_USES_IO) { ioaddr = pciaddr & ~3; if (check_region(ioaddr, pci_tbl[chip_idx].io_size)) continue; } else if ((ioaddr = (long)ioremap(pciaddr & ~0xf, pci_tbl[chip_idx].io_size)) == 0) { printk(KERN_INFO "Failed to map PCI address %#lx.\n", pciaddr); continue; } pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_command); new_command = pci_command | (pci_tbl[chip_idx].flags & 7); if (pci_command != new_command) { printk(KERN_INFO " The PCI BIOS has not enabled the" " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", pci_bus, pci_device_fn, pci_command, new_command); pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, new_command); } dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr, irq, chip_idx, cards_found); if (dev && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) { u8 pci_latency; pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < min_pci_latency) { printk(KERN_INFO " PCI latency timer (CFLT) is " "unreasonably low at %d. Setting to %d clocks.\n", pci_latency, min_pci_latency); pcibios_write_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, min_pci_latency); } } dev = 0; cards_found++; } return cards_found ? 0 : -ENODEV; }
/* * SunOS and Solaris /dev/openprom ioctl calls. */ static int openprom_sunos_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg, int node) { DATA *data = (DATA *) file->private_data; char buffer[OPROMMAXPARAM+1], *buf; struct openpromio *opp; unsigned long flags; int bufsize, len, error = 0; extern char saved_command_line[]; static int cnt; if (cmd == OPROMSETOPT) bufsize = getstrings((void *)arg, &opp); else bufsize = copyin((void *)arg, &opp); if (bufsize < 0) return bufsize; switch (cmd) { case OPROMGETOPT: case OPROMGETPROP: save_and_cli(flags); len = prom_getproplen(node, opp->oprom_array); restore_flags(flags); if (len <= 0 || len > bufsize) { error = copyout((void *)arg, opp, sizeof(int)); break; } save_and_cli(flags); len = prom_getproperty(node, opp->oprom_array, buffer, bufsize); restore_flags(flags); memcpy(opp->oprom_array, buffer, len); opp->oprom_array[len] = '\0'; opp->oprom_size = len; error = copyout((void *)arg, opp, sizeof(int) + bufsize); break; case OPROMNXTOPT: case OPROMNXTPROP: save_and_cli(flags); buf = prom_nextprop(node, opp->oprom_array, buffer); restore_flags(flags); len = strlen(buf); if (len == 0 || len + 1 > bufsize) { error = copyout((void *)arg, opp, sizeof(int)); break; } memcpy(opp->oprom_array, buf, len); opp->oprom_array[len] = '\0'; opp->oprom_size = ++len; error = copyout((void *)arg, opp, sizeof(int) + bufsize); break; case OPROMSETOPT: case OPROMSETOPT2: buf = opp->oprom_array + strlen(opp->oprom_array) + 1; len = opp->oprom_array + bufsize - buf; save_and_cli(flags); error = prom_setprop(options_node, opp->oprom_array, buf, len); restore_flags(flags); if (error < 0) error = -EINVAL; break; case OPROMNEXT: case OPROMCHILD: case OPROMSETCUR: if (bufsize < sizeof(int)) { error = -EINVAL; break; } node = *((int *) opp->oprom_array); save_and_cli(flags); switch (cmd) { case OPROMNEXT: node = __prom_getsibling(node); break; case OPROMCHILD: node = __prom_getchild(node); break; case OPROMSETCUR: break; } restore_flags(flags); data->current_node = node; *((int *)opp->oprom_array) = node; opp->oprom_size = sizeof(int); error = copyout((void *)arg, opp, bufsize + sizeof(int)); break; case OPROMPCI2NODE: error = -EINVAL; if (bufsize >= 2*sizeof(int)) { #ifdef CONFIG_PCI struct pci_dev *pdev; struct pcidev_cookie *pcp; pdev = pci_find_slot (((int *) opp->oprom_array)[0], ((int *) opp->oprom_array)[1]); pcp = pdev->sysdata; if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) { node = pcp->prom_node; data->current_node = node; *((int *)opp->oprom_array) = node; opp->oprom_size = sizeof(int); error = copyout((void *)arg, opp, bufsize + sizeof(int)); } #endif } break; case OPROMPATH2NODE: save_and_cli(flags); node = prom_finddevice(opp->oprom_array); restore_flags(flags); data->current_node = node; *((int *)opp->oprom_array) = node; opp->oprom_size = sizeof(int); error = copyout((void *)arg, opp, bufsize + sizeof(int)); break; case OPROMGETBOOTARGS: buf = saved_command_line; len = strlen(buf); if (len > bufsize) { error = -EINVAL; break; } strcpy(opp->oprom_array, buf); opp->oprom_size = len; error = copyout((void *)arg, opp, bufsize + sizeof(int)); break; case OPROMU2P: case OPROMGETCONS: case OPROMGETFBNAME: if (cnt++ < 10) printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n"); error = -EINVAL; break; default: if (cnt++ < 10) printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg); error = -EINVAL; break; } kfree(opp); return error; }
int pciregions_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *data) { int i, pos=0; int bus, devfn, is_multi = 0; unsigned char headertype, pribus, secbus; u16 vendorid, deviceid = 0; /* to print information about several buses, keep an array of them */ #define MAXNBUS 8 int buses[MAXNBUS] = {0,}; int lastbus = 0; /* only one bus, by default, bus 0 */ int busindex = 0; /* this macro helps keeping the following lines short */ #define PRINTF(fmt, args...) sprintf(buf+len, fmt, ## args) len=0; /* Loop through the devices (code not printed in the book) */ if (!pci_present()) return sprintf(buf, "PCI not available in this computer\n"); bus = buses[busindex]; /* first bus (bus 0) */ for (devfn=0; pos < PAGE_SIZE; devfn++) { struct pci_dev *dev = NULL; /* * A clean implementation * would have a separate function to dump a single bus, but i * preferred to keep it in one function to include part of it * in the book (the printed code is automagically extracted from * this file). * * Instead, I use a dirty trick to fold two loops in one. */ if (devfn > 0xff) { /* end of this bus */ if (busindex == lastbus) break; /* loop over to the next bus */ bus = buses[++busindex]; devfn = 0; } /* * This code is derived from "drivers/pci/pci.c" in version * 2.0, although it has been modified to work with the 2.4 interface. * This means that the GPL applies to this source file * and credit is due to the original authors * (Drew Eckhardt, Frederic Potter, David Mosberger-Tang) */ if (PCI_FUNC(devfn) && !is_multi) /* not multi-function */ continue; dev = pci_find_slot(bus, devfn); if (!dev) { if (!PCI_FUNC(devfn)) is_multi = 0; /* no first implies no other */ continue; /* no such device */ } pci_read_config_byte(dev, PCI_HEADER_TYPE, &headertype); if (!PCI_FUNC(devfn)) /* first function */ is_multi = headertype & 0x80; headertype &= 0x7f; /* mask multi-function bit */ /* FIXME: should get rid of the PAGE_SIZE limit */ if (len > PAGE_SIZE / 2) { /* a big margin, just to be sure */ *eof = 1; return len; } vendorid = dev->vendor; deviceid = dev->device; len += PRINTF("Bus %i, device %2i, devfn %2i (id %04x-%04x," " headertype 0x%02x)\n", bus, devfn>>3, devfn & 7, vendorid, deviceid, headertype); if (headertype == PCI_HEADER_TYPE_BRIDGE) { /* This is a bridge, print what it does */ pci_read_config_byte(dev, PCI_PRIMARY_BUS, &pribus); pci_read_config_byte(dev, PCI_SECONDARY_BUS, &secbus); len += PRINTF("\tbridge connecting PCI bus %i to PCI bus %i\n", secbus, pribus); /* remember about this bus, to dump it later */ if (lastbus <= MAXNBUS-1) { lastbus++; buses[lastbus] = secbus; len += PRINTF("\t(bus %i is dumped below)\n", secbus); } else { len += PRINTF("\t(bus %i won't be dumped)\n", secbus); } pci_release_device(dev); /* 2.0 compatibility */ continue; } else if (headertype == PCI_HEADER_TYPE_CARDBUS) { /* This is a CardBus bridge, print what it does */ pci_read_config_byte(dev, PCI_CB_PRIMARY_BUS,&pribus); pci_read_config_byte(dev, PCI_CB_CARD_BUS,&secbus); len += PRINTF("\tbridge connecting CardBus %i to PCI bus %i\n", secbus, pribus); pci_release_device(dev); /* 2.0 compatibility */ continue; } else if (headertype != PCI_HEADER_TYPE_NORMAL) { len += PRINTF("\tunknown header type, skipping\n"); pci_release_device(dev); /* 2.0 compatibility */ continue; } /* Print the address regions of this device */ for (i=0; addresses[i]; i++) { u32 curr, mask, size; char *type; pci_read_config_dword(dev, addresses[i],&curr); cli(); pci_write_config_dword(dev, addresses[i],~0); pci_read_config_dword(dev, addresses[i],&mask); pci_write_config_dword(dev, addresses[i],curr); sti(); if (!mask) continue; /* there may be other regions */ /* * apply the I/O or memory mask to current position * note that I/O is limited to 0xffff, and 64-bit is not * supported by this simple imeplementation */ if (curr & PCI_BASE_ADDRESS_SPACE_IO) { curr &= PCI_BASE_ADDRESS_IO_MASK; } else { curr &= PCI_BASE_ADDRESS_MEM_MASK; } len += PRINTF("\tregion %i: mask 0x%08lx, now at 0x%08lx\n", i, (unsigned long)mask, (unsigned long)curr); /* extract the type, and the programmable bits */ if (mask & PCI_BASE_ADDRESS_SPACE_IO) { type = "I/O"; mask &= PCI_BASE_ADDRESS_IO_MASK; size = (~mask + 1) & 0xffff; /* Bleah */ } else { type = "mem"; mask &= PCI_BASE_ADDRESS_MEM_MASK; size = ~mask + 1; } len += PRINTF("\tregion %i: type %s, size %i (%i%s)\n", i, type, size, (size & 0xfffff) == 0 ? size >> 20 : (size & 0x3ff) == 0 ? size >> 10 : size, (size & 0xfffff) == 0 ? "MB" : (size & 0x3ff) == 0 ? "KB" : "B"); if (len > PAGE_SIZE / 2) { len += PRINTF("... more info skipped ...\n"); *eof = 1; return len; } } pci_release_device(dev); /* 2.0 compatibility */ } /* devfn */ *eof = 1; return len; }
/****************************************************************************** Module initialization functions ******************************************************************************/ dev_node_t *islpci_attach(dev_locator_t * loc) { u32 io; u16 dev_id; u8 bus, devfn, irq, latency_tmr; struct pci_dev *pci_device; struct net_device *nw_device; dev_node_t *node; islpci_private *private_config; int rvalue; int dma_mask = 0xffffffff; char firmware[256]; // perform some initial setting checks if (loc->bus != LOC_PCI) return NULL; bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_attach(bus %d, function %d)\n", bus, devfn); #endif // get some pci settings for verification pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); // check whether the latency timer is set correctly pcibios_read_config_byte(bus, devfn, PCI_LATENCY_TIMER, &latency_tmr); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG( SHOW_TRACING, "latency timer: %x\n", latency_tmr ); #endif if( latency_tmr < PCIDEVICE_LATENCY_TIMER_MIN ) { // set the latency timer pcibios_write_config_byte(bus, devfn, PCI_LATENCY_TIMER, PCIDEVICE_LATENCY_TIMER_VAL ); } if (io &= ~3, io == 0 || irq == 0) { DEBUG(SHOW_ERROR_MESSAGES, "The ISL38XX Ethernet interface was not " "assigned an %s.\n" KERN_ERR " It will not be activated.\n", io == 0 ? "I/O address" : "IRQ"); return NULL; } // get pci device information by loading the pci_dev structure if (pci_device = pci_find_slot(bus, devfn), pci_device == NULL) { // error reading the pci device structure DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not get PCI device " "information \n", DRIVER_NAME ); return NULL; } // determine what the supported DMA memory region is while( pci_set_dma_mask( pci_device, dma_mask ) != 0 ) { // range not supported, shift the mask and check again if( dma_mask >>= 1, dma_mask == 0 ) { // mask is zero, DMA memory not supported by PCI DEBUG(SHOW_ERROR_MESSAGES, "DMA Memory not supported\n" ); return NULL; } } #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "DMA Memory support mask is 0x%x \n", dma_mask ); #endif // setup the network device interface and its structure if (nw_device = islpci_probe(NULL, pci_device, (long) io, (int) irq), nw_device == NULL) { // error configuring the driver as a network device DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not configure " "network device \n", DRIVER_NAME ); return NULL; } #ifdef WDS_LINKS mgt_indication_handler ( DEV_NETWORK, nw_device->name, DOT11_OID_WDSLINKADD, islpci_wdslink_add_hndl ); mgt_indication_handler ( DEV_NETWORK, nw_device->name, DOT11_OID_WDSLINKREMOVE, islpci_wdslink_del_hndl ); #endif // save the interrupt request line and use the remapped device base address // as the device identification both for uniqueness and parameter passing // to the interrupt handler private_config = nw_device->priv; private_config->pci_irq = irq; private_config->pci_dev_id = dev_id; private_config->device_id = private_config->remapped_device_base; spin_lock_init( &private_config->slock ); // request for the interrupt before uploading the firmware if (rvalue = request_irq(irq, &islpci_interrupt, SA_INTERRUPT | SA_SHIRQ, DRIVER_NAME, private_config), rvalue != 0) { // error, could not hook the handler to the irq DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not install " "IRQ-handler \n", DRIVER_NAME ); return NULL; } // select the firmware file depending on the device id, take for default // the 3877 firmware file if( dev_id == PCIDEVICE_ISL3890 ) strcpy( firmware, ISL3890_IMAGE_FILE ); else strcpy( firmware, ISL3877_IMAGE_FILE ); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Device %x, firmware file: %s \n", dev_id, firmware ); #endif if (isl38xx_upload_firmware( firmware, private_config->remapped_device_base, private_config->device_host_address ) == -1) { // error uploading the firmware DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not upload the " "firmware \n", DRIVER_NAME ); return NULL; } // finally setup the node structure with the device information node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); strcpy(node->dev_name, nw_device->name); node->major = 0; node->minor = 0; node->next = NULL; MOD_INC_USE_COUNT; return node; }