in dino.c [909:1033]
static int __init dino_probe(struct parisc_device *dev)
{
struct dino_device *dino_dev; // Dino specific control struct
const char *version = "unknown";
char *name;
int is_cujo = 0;
LIST_HEAD(resources);
struct pci_bus *bus;
unsigned long hpa = dev->hpa.start;
int max;
name = "Dino";
if (is_card_dino(&dev->id)) {
version = "3.x (card mode)";
} else {
if (!is_cujo(&dev->id)) {
if (dev->id.hversion_rev < 4) {
version = dino_vers[dev->id.hversion_rev];
}
} else {
name = "Cujo";
is_cujo = 1;
if (dev->id.hversion_rev < 2) {
version = cujo_vers[dev->id.hversion_rev];
}
}
}
printk("%s version %s found at 0x%lx\n", name, version, hpa);
if (!request_mem_region(hpa, PAGE_SIZE, name)) {
printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%lx)!\n",
hpa);
return 1;
}
/* Check for bugs */
if (is_cujo && dev->id.hversion_rev == 1) {
#ifdef CONFIG_IOMMU_CCIO
printk(KERN_WARNING "Enabling Cujo 2.0 bug workaround\n");
if (hpa == (unsigned long)CUJO_RAVEN_ADDR) {
ccio_cujo20_fixup(dev, CUJO_RAVEN_BADPAGE);
} else if (hpa == (unsigned long)CUJO_FIREHAWK_ADDR) {
ccio_cujo20_fixup(dev, CUJO_FIREHAWK_BADPAGE);
} else {
printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", hpa);
}
#endif
} else if (!is_cujo && !is_card_dino(&dev->id) &&
dev->id.hversion_rev < 3) {
printk(KERN_WARNING
"The GSCtoPCI (Dino hrev %d) bus converter found may exhibit\n"
"data corruption. See Service Note Numbers: A4190A-01, A4191A-01.\n"
"Systems shipped after Aug 20, 1997 will not exhibit this problem.\n"
"Models affected: C180, C160, C160L, B160L, and B132L workstations.\n\n",
dev->id.hversion_rev);
/* REVISIT: why are C200/C240 listed in the README table but not
** "Models affected"? Could be an omission in the original literature.
*/
}
dino_dev = kzalloc(sizeof(struct dino_device), GFP_KERNEL);
if (!dino_dev) {
printk("dino_init_chip - couldn't alloc dino_device\n");
return 1;
}
dino_dev->hba.dev = dev;
dino_dev->hba.base_addr = ioremap(hpa, 4096);
dino_dev->hba.lmmio_space_offset = PCI_F_EXTEND;
spin_lock_init(&dino_dev->dinosaur_pen);
dino_dev->hba.iommu = ccio_get_iommu(dev);
if (is_card_dino(&dev->id)) {
dino_card_init(dino_dev);
} else {
dino_bridge_init(dino_dev, name);
}
if (dino_common_init(dev, dino_dev, name))
return 1;
dev->dev.platform_data = dino_dev;
pci_add_resource_offset(&resources, &dino_dev->hba.io_space,
HBA_PORT_BASE(dino_dev->hba.hba_num));
if (dino_dev->hba.lmmio_space.flags)
pci_add_resource_offset(&resources, &dino_dev->hba.lmmio_space,
dino_dev->hba.lmmio_space_offset);
if (dino_dev->hba.elmmio_space.flags)
pci_add_resource_offset(&resources, &dino_dev->hba.elmmio_space,
dino_dev->hba.lmmio_space_offset);
if (dino_dev->hba.gmmio_space.flags)
pci_add_resource(&resources, &dino_dev->hba.gmmio_space);
dino_dev->hba.bus_num.start = dino_current_bus;
dino_dev->hba.bus_num.end = 255;
dino_dev->hba.bus_num.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &dino_dev->hba.bus_num);
/*
** It's not used to avoid chicken/egg problems
** with configuration accessor functions.
*/
dino_dev->hba.hba_bus = bus = pci_create_root_bus(&dev->dev,
dino_current_bus, &dino_cfg_ops, NULL, &resources);
if (!bus) {
printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n",
dev_name(&dev->dev), dino_current_bus);
pci_free_resource_list(&resources);
/* increment the bus number in case of duplicates */
dino_current_bus++;
return 0;
}
max = pci_scan_child_bus(bus);
pci_bus_update_busn_res_end(bus, max);
/* This code *depends* on scanning being single threaded
* if it isn't, this global bus number count will fail
*/
dino_current_bus = max + 1;
pci_bus_assign_resources(bus);
pci_bus_add_devices(bus);
return 0;
}