📄 ide-pci.c
字号:
*/ if (bootable) { for (h = 0; h < MAX_HWIFS; ++h) { hwif = &ide_hwifs[h]; if (hwif->chipset == ide_unknown) return hwif; /* pick an unused entry */ } } else { for (h = 2; h < MAX_HWIFS; ++h) { hwif = ide_hwifs + h; if (hwif->chipset == ide_unknown) return hwif; /* pick an unused entry */ } } for (h = 0; h < 2; ++h) { hwif = ide_hwifs + h; if (hwif->chipset == ide_unknown) return hwif; /* pick an unused entry */ } printk("%s: too many IDE interfaces, no room in table\n", name); return NULL;}__initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)){ byte reg, progif = 0; /* * Place both IDE interfaces into PCI "native" mode: */ if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { if ((progif & 0xa) != 0xa) { printk("%s: device not capable of full native PCI mode\n", name); return 1; } printk("%s: placing both ports into native PCI mode\n", name); (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif); return 1; } } /* * Setup base registers for IDE command/control spaces for each interface: */ for (reg = 0; reg < 4; reg++) if (!dev->base_address[reg]) { printk("%s: Missing I/O address #%d, please report to <mj@ucw.cz>\n", name, reg); return 1; } return 0;}/* * ide_setup_pci_device() looks at the primary/secondary interfaces * on a PCI IDE device and, if they are enabled, prepares the IDE driver * for use with them. This generic code works for most PCI chipsets. * * One thing that is not standardized is the location of the * primary/secondary interface "enable/disable" bits. For chipsets that * we "know" about, this information is in the ide_pci_device_t struct; * for all other chipsets, we just assume both interfaces are enabled. */__initfunc(static void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d)){ unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0; unsigned short pcicmd = 0, tried_config = 0; byte tmp = 0; ide_hwif_t *hwif, *mate = NULL;#ifdef CONFIG_IDEDMA_AUTO autodma = 1;#endifcheck_if_enabled: if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { printk("%s: error accessing PCI regs\n", d->name); return; } if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ /* * PnP BIOS was *supposed* to have set this device up for us, * but we can do it ourselves, so long as the BIOS has assigned an IRQ * (or possibly the device is using a "legacy header" for IRQs). * Maybe the user deliberately *disabled* the device, * but we'll eventually ignore it again if no drives respond. */ if (tried_config++ || ide_setup_pci_baseregs(dev, d->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { printk("%s: device disabled (BIOS)\n", d->name); return; } autodma = 0; /* default DMA off if we had to configure it here */ goto check_if_enabled; } if (tried_config) printk("%s: device enabled (Linux)\n", d->name); /* * Can we trust the reported IRQ? */ pciirq = dev->irq; if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { printk("%s: not 100%% native mode: will probe irqs later\n", d->name); pciirq = ide_special_settings(dev, d->name); } else if (tried_config) { printk("%s: will probe irqs later\n", d->name); pciirq = 0; } else if (!pciirq) { printk("%s: bad irq (%d): will probe later\n", d->name, pciirq); pciirq = 0; } else {#ifdef __sparc__ printk("%s: 100%% native mode on irq %s\n", d->name, __irq_itoa(pciirq));#else printk("%s: 100%% native mode on irq %d\n", d->name, pciirq);#endif } /* * Set up the IDE ports */ for (port = 0; port <= 1; ++port) { unsigned long base = 0, ctl = 0; ide_pci_enablebit_t *e = &(d->enablebits[port]); if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) continue; /* port not enabled */ if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { ctl = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK; base = dev->base_address[2*port] & ~7; } if ((ctl && !base) || (base && !ctl)) { printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port); continue; } if (!ctl) ctl = port ? 0x374 : 0x3f4; /* use default value */ if (!base) base = port ? 0x170 : 0x1f0; /* use default value */ if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL) continue; /* no room in ide_hwifs[] */ if (hwif->io_ports[IDE_DATA_OFFSET] != base) { ide_init_hwif_ports(hwif->io_ports, base, NULL); hwif->io_ports[IDE_CONTROL_OFFSET] = ctl + 2; hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; } hwif->chipset = ide_pci; hwif->pci_dev = dev; hwif->pci_devid = d->devid; hwif->channel = port; if (!hwif->irq) hwif->irq = pciirq; if (mate) { hwif->mate = mate; mate->mate = hwif; if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) { hwif->serialized = 1; mate->serialized = 1; } } if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) || IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF)) hwif->irq = hwif->channel ? 15 : 14;#ifdef CONFIG_BLK_DEV_IDEDMA if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513)) autodma = 0; if (autodma) hwif->autodma = 1; if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT343) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name); if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { /* * Set up BM-DMA capability (PnP BIOS should have done this) */ hwif->autodma = 0; /* default DMA off if we had to configure it here */ (void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER); if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { printk("%s: %s error updating PCICMD\n", hwif->name, d->name); dma_base = 0; } } if (dma_base) ide_setup_dma(hwif, dma_base, 8); else printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name); }#endif /* CONFIG_BLK_DEV_IDEDMA */ if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */ d->init_hwif(hwif); mate = hwif; at_least_one_hwif_enabled = 1; } if (!at_least_one_hwif_enabled) printk("%s: neither IDE port enabled (BIOS)\n", d->name);}/* * ide_scan_pcibus() gets invoked at boot time from ide.c. * It finds all PCI IDE controllers and calls ide_setup_pci_device for them. */__initfunc(void ide_scan_pcibus (void)){ struct pci_dev *dev; ide_pci_devid_t devid; ide_pci_device_t *d; if (!pci_present()) return; for(dev = pci_devices; dev; dev=dev->next) { devid.vid = dev->vendor; devid.did = dev->device; for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); if (d->init_hwif == IDE_IGNORE) printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name); else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1)) continue; /* OPTI Viper-M uses same devid for functions 0 and 1 */ else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n", d->name, dev->bus->number, dev->devfn, devid.vid, devid.did); else printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); ide_setup_pci_device(dev, d); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -