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