📄 mptbase.c
字号:
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_pci_scan - Scan PCI devices for MPT adapters. * * Returns count of MPT adapters found, keying off of PCI vendor and * device_id's. */int __initmpt_pci_scan(void){ struct pci_dev *pdev; struct pci_dev *pdev2; int found = 0; int count = 0; int r; dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n")); /* * NOTE: The 929 (I believe) will appear as 2 separate PCI devices, * one for each channel. */ pci_for_each_dev(pdev) { pdev2 = NULL; if (pdev->vendor != 0x1000) continue; if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) &&#if 0 /* FIXME! C103x family */ (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) && (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) && (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1035) &&#endif 1) { dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device)); continue; } /* GRRRRR * 929 dual function devices may be presented in Func 1,0 order, * but we'd really really rather have them in Func 0,1 order. * Do some kind of look ahead here... */ if (pdev->devfn & 1) { pdev2 = pci_peek_next_dev(pdev); if (pdev2 && (pdev2->vendor == 0x1000) && (PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) && (pdev2->device == MPI_MANUFACTPAGE_DEVICEID_FC929) && (pdev2->bus->number == pdev->bus->number) && !(pdev2->devfn & 1)) { dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n", pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device)); found++; if ((r = mpt_adapter_install(pdev2)) == 0) count++; } else { pdev2 = NULL; } } dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n", pdev->bus->number, pdev->devfn, pdev->class, pdev->device)); found++; if ((r = mpt_adapter_install(pdev)) == 0) count++; if (pdev2) pdev = pdev2; } printk(KERN_INFO MYNAM ": %d MPT adapter%s found, %d installed.\n", found, (found==1) ? "" : "s", count); if (!found || !count) { fusion_exit(); return -ENODEV; }#ifdef CONFIG_PROC_FS if (procmpt_create() != 0) printk(KERN_WARNING MYNAM ": WARNING! - %s creation failed!\n", MPT_PROCFS_MPTBASEDIR);#endif return count;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_verify_adapter - Given a unique IOC identifier, set pointer to * the associated MPT adapter structure. * @iocid: IOC unique identifier (integer) * @iocpp: Pointer to pointer to IOC adapter * * Returns iocid and sets iocpp. */intmpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp){ MPT_ADAPTER *p; *iocpp = NULL; if (iocid >= MPT_MAX_ADAPTERS) return -1; p = mpt_adapters[iocid]; if (p == NULL) return -1; *iocpp = p; return iocid;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_adapter_install - Install a PCI intelligent MPT adapter. * @pdev: Pointer to pci_dev structure * * This routine performs all the steps necessary to bring the IOC of * a MPT adapter to a OPERATIONAL state. This includes registering * memory regions, registering the interrupt, and allocating request * and reply memory pools. * * This routine also pre-fetches the LAN MAC address of a Fibre Channel * MPT adapter. * * Returns 0 for success, non-zero for failure. * * TODO: Add support for polled controllers */static int __initmpt_adapter_install(struct pci_dev *pdev){ MPT_ADAPTER *ioc; char *myname; u8 *mem; unsigned long mem_phys; unsigned long port; u32 msize; u32 psize; int i; int r = -ENODEV; int len; ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_KERNEL); if (ioc == NULL) { printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; } memset(ioc, 0, sizeof(*ioc)); ioc->req_sz = MPT_REQ_SIZE; /* avoid div by zero! */ ioc->alloc_total = sizeof(MPT_ADAPTER); ioc->pcidev = pdev; /* Find lookup slot. */ for (i=0; i < MPT_MAX_ADAPTERS; i++) { if (mpt_adapters[i] == NULL) { ioc->id = i; /* Assign adapter unique id (lookup) */ break; } } if (i == MPT_MAX_ADAPTERS) { printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", i); kfree(ioc); return -ENFILE; } mem_phys = msize = 0; port = psize = 0; for (i=0; i < DEVICE_COUNT_RESOURCE; i++) { if (pdev->PCI_BASEADDR_FLAGS(i) & PCI_BASE_ADDRESS_SPACE_IO) { /* Get I/O space! */ port = pdev->PCI_BASEADDR_START(i); psize = PCI_BASEADDR_SIZE(pdev,i); } else { /* Get memmap */ mem_phys = pdev->PCI_BASEADDR_START(i); msize = PCI_BASEADDR_SIZE(pdev,i); break; } } ioc->mem_size = msize; if (i == DEVICE_COUNT_RESOURCE) { printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n"); kfree(ioc); return -EINVAL; } dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize)); dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize)); dprintk((KERN_INFO MYNAM ": Using %s register access method\n", PortIo ? "PortIo" : "MemMap")); mem = NULL; if (! PortIo) { /* Get logical ptr for PciMem0 space */ /*mem = ioremap(mem_phys, msize);*/ mem = ioremap(mem_phys, 0x100); if (mem == NULL) { printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n"); kfree(ioc); return -EINVAL; } ioc->memmap = mem; } dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys)); if (PortIo) { u8 *pmem = (u8*)port; ioc->mem_phys = port; ioc->chip = (SYSIF_REGS*)pmem; } else { ioc->mem_phys = mem_phys; ioc->chip = (SYSIF_REGS*)mem; } ioc->chip_type = FCUNK; if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { ioc->chip_type = FC909; ioc->prod_name = "LSIFC909"; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { ioc->chip_type = FC929; ioc->prod_name = "LSIFC929"; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) { ioc->chip_type = FC919; ioc->prod_name = "LSIFC919"; }#if 0 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_53C1030) { ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; }#endif myname = "iocN"; len = strlen(myname); memcpy(ioc->name, myname, len+1); ioc->name[len-1] = '0' + ioc->id; Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); spin_lock_init(&ioc->FreeQlock); /* Disable all! */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); ioc->pci_irq = -1; if (pdev->irq) { r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); if (r < 0) { printk(KERN_ERR MYNAM ": %s: ERROR - Unable to allocate interrupt %d!\n", ioc->name, pdev->irq); iounmap(mem); kfree(ioc); return -EBUSY; } ioc->pci_irq = pdev->irq; pci_set_master(pdev); /* ?? */ dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); } /* tack onto tail of our MPT adapter list */ Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER); /* Set lookup ptr. */ mpt_adapters[ioc->id] = ioc; /* NEW! 20010220 -sralston * Check for "929 bound ports" to reduce redundant resets. */ if (ioc->chip_type == FC929) mpt_detect_929_bound_ports(ioc, pdev); if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) { printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); } return r;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_do_ioc_recovery - Initialize or recover MPT adapter. * @ioc: Pointer to MPT adapter structure * @reason: Event word / reason * * This routine performs all the steps necessary to bring the IOC * to a OPERATIONAL state. * * This routine also pre-fetches the LAN MAC address of a Fibre Channel * MPT adapter. * * Returns 0 for success. */static intmpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason){ int hard_reset_done = 0; int alt_ioc_ready = 0; int hard; int r; int i; int handlers; printk(KERN_INFO MYNAM ": Initiating %s %s\n", ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); /* Disable reply interrupts */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; /* NOTE: Access to IOC's request FreeQ is now blocked! */// FIXME? Cleanup all IOC requests here! (or below?)// But watch out for event associated request? hard = HardReset; if (ioc->alt_ioc && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) hard = 0; if ((hard_reset_done = MakeIocReady(ioc, hard)) < 0) { printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", ioc->name); return -1; }// NEW!#if 0 // Kiss-of-death!?! if (ioc->alt_ioc) {// Grrr... Hold off any alt-IOC interrupts (and events) while// handshaking to <this> IOC, needed because? /* Disable alt-IOC's reply interrupts for a bit ... */ alt_ioc_intmask = CHIPREG_READ32(&ioc->alt_ioc->chip->IntMask); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); ioc->alt_ioc->active = 0; /* NOTE: Access to alt-IOC's request FreeQ is now blocked! */ }#endif if (hard_reset_done && ioc->alt_ioc) { if ((r = MakeIocReady(ioc->alt_ioc, 0)) == 0) alt_ioc_ready = 1; else printk(KERN_WARNING MYNAM ": alt-%s: (%d) Not ready WARNING!\n", ioc->alt_ioc->name, r); } if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { /* Get IOC facts! */ if ((r = GetIocFacts(ioc)) != 0) return -2; MptDisplayIocCapabilities(ioc); } /* * Call each currently registered protocol IOC reset handler * with pre-reset indication. * NOTE: If we're doing _IOC_BRINGUP, there can be no * MptResetHandlers[] registered yet. */ if (hard_reset_done) { r = handlers = 0; for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) { if (MptResetHandlers[i]) { dprintk((KERN_INFO MYNAM ": %s: Calling IOC pre_reset handler #%d\n", ioc->name, i)); r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_PRE_RESET); handlers++; if (alt_ioc_ready) { dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC pre_reset handler #%d\n", ioc->alt_ioc->name, i)); r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_PRE_RESET); handlers++; } } } /* FIXME? Examine results here? */ } // May need to check/upload firmware & data here! if ((r = SendIocInit(ioc)) != 0) return -3;// NEW! if (alt_ioc_ready) { if ((r = SendIocInit(ioc->alt_ioc)) != 0) { alt_ioc_ready = 0; printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n", ioc->alt_ioc->name, r); } } /* * Call each currently registered protocol IOC reset handler * with post-reset indication. * NOTE: If we're doing _IOC_BRINGUP, there can be no * MptResetHandlers[] registered yet. */ if (hard_reset_done) { r = handlers = 0; for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) { if (MptResetHandlers[i]) { dprintk((KERN_INFO MYNAM ": %s: Calling IOC post_reset handler #%d\n", ioc->name, i)); r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_POST_RESET); handlers++; if (alt_ioc_ready) { dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC post_reset handler #%d\n", ioc->alt_ioc->name, i)); r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; } } } /* FIXME? Examine results here? */ } /* * Prime reply & request queues! * (mucho alloc's) */ if ((r = PrimeIocFifos(ioc)) != 0) return -4;// NEW! if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) { printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", ioc->alt_ioc->name, r); }// FIXME! Cleanup all IOC (and alt-IOC?) requests here!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -