static int __init dino_probe()

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;
}