示例#1
0
/*****************************************************************************
 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);
}
示例#2
0
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;
}