/***************************************************************************** Function name : orc_ReturnNumberOfAdapters Description : This function will scan PCI bus to get all Orchid card Input : None. Output : None. Return : SUCCESSFUL - Successful scan ohterwise - No drives founded *****************************************************************************/ int orc_ReturnNumberOfAdapters(void) { unsigned int i, iAdapters; iAdapters = 0; /* * PCI-bus probe. */ if (pcibios_present()) { struct { unsigned short vendor_id; unsigned short device_id; } const inia100_pci_devices[] = { {ORC_VENDOR_ID, I920_DEVICE_ID}, {ORC_VENDOR_ID, ORC_DEVICE_ID} }; unsigned int dRegValue; unsigned short command; WORD wBIOS, wBASE; BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum; #ifdef MMAPIO unsigned long page_offset, base; #endif #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) struct pci_dev *pdev = NULL; #else int index; unsigned char pci_bus, pci_devfn; #endif bPCIBusNum = 0; bPCIDeviceNum = 0; init_inia100Adapter_table(); for (i = 0; i < NUMBER(inia100_pci_devices); i++) { #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) pdev = NULL; while ((pdev = pci_find_device(inia100_pci_devices[i].vendor_id, inia100_pci_devices[i].device_id, pdev))) #else index = 0; while (!(pcibios_find_device(inia100_pci_devices[i].vendor_id, inia100_pci_devices[i].device_id, index++, &pci_bus, &pci_devfn))) #endif { if (iAdapters >= MAX_SUPPORTED_ADAPTERS) break; /* Never greater than maximum */ if (i == 0) { /* printk("inia100: The RAID controller is not supported by\n"); printk("inia100: this driver, we are ignoring it.\n"); */ } else { /* * Read sundry information from PCI BIOS. */ #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) bPCIBusNum = pdev->bus->number; bPCIDeviceNum = pdev->devfn; dRegValue = pdev->base_address[0]; if (dRegValue == -1) { /* Check return code */ printk("\n\rinia100: orchid read configuration error.\n"); return (0); /* Read configuration space error */ } /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ wBASE = (WORD) dRegValue; /* Now read the interrupt line */ dRegValue = pdev->irq; bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ pci_read_config_word(pdev, PCI_COMMAND, &command); pci_write_config_word(pdev, PCI_COMMAND, command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); #else bPCIBusNum = pci_bus; bPCIDeviceNum = pci_devfn; pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0, &dRegValue); if (dRegValue == -1) { /* Check return code */ printk("\n\rinia100: Orchid read configuration error.\n"); return (0); /* Read configuration space error */ } /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ wBASE = (WORD) dRegValue; /* Now read the interrupt line */ pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, &dRegValue); bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command); pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); #endif wBASE &= PCI_BASE_ADDRESS_IO_MASK; wBIOS = ORC_RDWORD(wBASE, 0x50); #ifdef MMAPIO base = wBASE & PAGE_MASK; page_offset = wBASE - base; /* * replace the next line with this one if you are using 2.1.x: * temp_p->maddr = ioremap(base, page_offset + 256); */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0) wBASE = ioremap(base, page_offset + 256); #else wBASE = (WORD) vremap(base, page_offset + 256); #endif if (wBASE) { wBASE += page_offset; } #endif if (Addinia100_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum, bPCIDeviceNum) == SUCCESSFUL) iAdapters++; } } /* while(pdev=....) */ } /* for PCI_DEVICES */ } /* PCI BIOS present */ return (iAdapters); }
static int __devinit inia100_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { struct Scsi_Host *shost; ORC_HCS *pHCB; unsigned long port, bios; int error = -ENODEV; u32 sz; unsigned long dBiosAdr; char *pbBiosAdr; if (pci_enable_device(pdev)) goto out; if (pci_set_dma_mask(pdev, 0xffffffffULL)) { printk(KERN_WARNING "Unable to set 32bit DMA " "on inia100 adapter, ignoring.\n"); goto out_disable_device; } pci_set_master(pdev); port = pci_resource_start(pdev, 0); if (!request_region(port, 256, "inia100")) { printk(KERN_WARNING "inia100: io port 0x%lx, is busy.\n", port); goto out_disable_device; } /* <02> read from base address + 0x50 offset to get the bios balue. */ bios = ORC_RDWORD(port, 0x50); shost = scsi_host_alloc(&inia100_template, sizeof(ORC_HCS)); if (!shost) goto out_release_region; pHCB = (ORC_HCS *)shost->hostdata; pHCB->pdev = pdev; pHCB->HCS_Base = port; pHCB->HCS_BIOS = bios; pHCB->pSRB_head = NULL; /* Initial SRB save queue */ pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */ pHCB->BitAllocFlagLock = SPIN_LOCK_UNLOCKED; /* Get total memory needed for SCB */ sz = ORC_MAXQUEUE * sizeof(ORC_SCB); pHCB->HCS_virScbArray = pci_alloc_consistent(pdev, sz, &pHCB->HCS_physScbArray); if (!pHCB->HCS_virScbArray) { printk("inia100: SCB memory allocation error\n"); goto out_host_put; } memset(pHCB->HCS_virScbArray, 0, sz); /* Get total memory needed for ESCB */ sz = ORC_MAXQUEUE * sizeof(ESCB); pHCB->HCS_virEscbArray = pci_alloc_consistent(pdev, sz, &pHCB->HCS_physEscbArray); if (!pHCB->HCS_virEscbArray) { printk("inia100: ESCB memory allocation error\n"); goto out_free_scb_array; } memset(pHCB->HCS_virEscbArray, 0, sz); dBiosAdr = pHCB->HCS_BIOS; dBiosAdr = (dBiosAdr << 4); pbBiosAdr = phys_to_virt(dBiosAdr); if (init_orchid(pHCB)) { /* Initialize orchid chip */ printk("inia100: initial orchid fail!!\n"); goto out_free_escb_array; } shost->io_port = pHCB->HCS_Base; shost->n_io_port = 0xff; shost->can_queue = ORC_MAXQUEUE; shost->unique_id = shost->io_port; shost->max_id = pHCB->HCS_MaxTar; shost->max_lun = 16; shost->irq = pHCB->HCS_Intr = pdev->irq; shost->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */ shost->sg_tablesize = TOTAL_SG_ENTRY; /* Initial orc chip */ error = request_irq(pdev->irq, inia100_intr, SA_SHIRQ, "inia100", shost); if (error < 0) { printk(KERN_WARNING "inia100: unable to get irq %d\n", pdev->irq); goto out_free_escb_array; } pci_set_drvdata(pdev, shost); error = scsi_add_host(shost, &pdev->dev); if (error) goto out_free_irq; scsi_scan_host(shost); return 0; out_free_irq: free_irq(shost->irq, shost); out_free_escb_array: pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB), pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray); out_free_scb_array: pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB), pHCB->HCS_virScbArray, pHCB->HCS_physScbArray); out_host_put: scsi_host_put(shost); out_release_region: release_region(port, 256); out_disable_device: pci_disable_device(pdev); out: return error; }