Example #1
0
/*****************************************************************************
 Function name  : inia100_detect
 Description    : 
 Input          : pHCB  -       Pointer to host adapter structure
 Output         : None.
 Return         : pSRB  -       Pointer to SCSI request block.
*****************************************************************************/
int inia100_detect(Scsi_Host_Template * tpnt)
{
	ORC_HCS *pHCB;
	struct Scsi_Host *hreg;
	U32 sz;
	U32 i;			/* 01/14/98                     */
	int ok = 0, iAdapters;
	ULONG dBiosAdr;
	BYTE *pbBiosAdr;

#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
	tpnt->proc_dir = &proc_scsi_inia100;
#endif
	if (setup_called) {
		/* Setup by inia100_setup          */
		printk("inia100: processing commandline: ");
	}
	/* Get total number of adapters in the motherboard */
	iAdapters = orc_ReturnNumberOfAdapters();

	/* printk("inia100: Total Initio Adapters = %d\n", iAdapters); */
	if (iAdapters == 0)	/* If no orc founded, return */
		return (0);

	orc_num_ch = (iAdapters > orc_num_ch) ? orc_num_ch : iAdapters;
	orc_num_scb = ORC_MAXQUEUE;

	/* clear the memory needed for HCS */
	i = orc_num_ch * sizeof(ORC_HCS);
	memset((unsigned char *) &orc_hcs[0], 0, i);	/* Initialize orc_hcs 0   */

#if 0
	printk("orc_num_scb= %x orc_num_ch= %x hcsize= %x scbsize= %x escbsize= %x\n",
	       orc_num_scb, orc_num_ch, sizeof(ORC_HCS), sizeof(ORC_SCB), sizeof(ESCB));
#endif

	for (i = 0, pHCB = &orc_hcs[0];		/* Get pointer for control block */
	     i < orc_num_ch;
	     i++, pHCB++) {

		pHCB->pSRB_head = NULL;		/* Initial SRB save queue       */
		pHCB->pSRB_tail = NULL;		/* Initial SRB save queue       */
#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
		pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */
#endif
		/* Get total memory needed for SCB */
		sz = orc_num_scb * sizeof(ORC_SCB);
		if ((pHCB->HCS_virScbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) {
			printk("inia100: SCB memory allocation error\n");
			return (0);
		}
		memset((unsigned char *) pHCB->HCS_virScbArray, 0, sz);
		pHCB->HCS_physScbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virScbArray);

		/* Get total memory needed for ESCB */
		sz = orc_num_scb * sizeof(ESCB);
		if ((pHCB->HCS_virEscbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) {
			printk("inia100: ESCB memory allocation error\n");
			return (0);
		}
		memset((unsigned char *) pHCB->HCS_virEscbArray, 0, sz);
		pHCB->HCS_physEscbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virEscbArray);

		request_region(pHCB->HCS_Base, 0x100, "inia100");	/* Register */
		get_orcPCIConfig(pHCB, i);

		dBiosAdr = pHCB->HCS_BIOS;
		dBiosAdr = (dBiosAdr << 4);

#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
		pbBiosAdr = phys_to_virt(dBiosAdr);
#endif

		if (init_orchid(pHCB)) {	/* Initial orchid chip    */
			printk("inia100: initial orchid fail!!\n");
			return (0);
		}
		hreg = scsi_register(tpnt, sizeof(ORC_HCS));
		if (hreg == NULL) {
			printk("Invalid scsi_register pointer.\n");
		}
		hreg->io_port = pHCB->HCS_Base;
		hreg->n_io_port = 0xff;
		hreg->can_queue = orc_num_scb;	/* 03/05/98                   */

#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
		hreg->unique_id = pHCB->HCS_Base;
		hreg->max_id = pHCB->HCS_MaxTar;
#endif

		hreg->max_lun = 32;	/* 10/21/97                     */
/*
   hreg->max_lun = 8;
   hreg->max_channel = 1;
 */
		hreg->irq = pHCB->HCS_Intr;
		hreg->this_id = pHCB->HCS_SCSI_ID;	/* Assign HCS index           */
		hreg->base = (UCHAR *) pHCB;

#if 1
		hreg->sg_tablesize = TOTAL_SG_ENTRY;	/* Maximun support is 32 */
#else
		hreg->sg_tablesize = SG_NONE;	/* No SG                        */
#endif

		/* Initial orc chip           */
		switch (i) {
#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
		case 0:
			ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
			break;
		case 1:
			ok = request_irq(pHCB->HCS_Intr, inia100_intr1, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
			break;
		case 2:
			ok = request_irq(pHCB->HCS_Intr, inia100_intr2, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
			break;
		case 3:
			ok = request_irq(pHCB->HCS_Intr, inia100_intr3, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
			break;
		case 4:
			ok = request_irq(pHCB->HCS_Intr, inia100_intr4, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
			break;
		case 5:
			ok = request_irq(pHCB->HCS_Intr, inia100_intr5, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
			break;
		case 6:
			ok = request_irq(pHCB->HCS_Intr, inia100_intr6, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
			break;
		case 7:
			ok = request_irq(pHCB->HCS_Intr, inia100_intr7, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
			break;
		default:
			inia100_panic("inia100: Too many host adapters\n");
			break;
		}

		if (ok < 0) {
			if (ok == -EINVAL) {
				printk("inia100: bad IRQ %d.\n", pHCB->HCS_Intr);
				printk("         Contact author.\n");
			} else {
				if (ok == -EBUSY)
					printk("inia100: IRQ %d already in use. Configure another.\n", pHCB->HCS_Intr);
				else {
					printk("\ninia100: Unexpected error code on requesting IRQ %d.\n",
					       pHCB->HCS_Intr);
					printk("         Contact author.\n");
				}
			}
			inia100_panic("inia100: driver needs an IRQ.\n");
		}
#endif
	}

	tpnt->this_id = -1;
	tpnt->can_queue = 1;
	return 1;
}
Example #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;
}