📄 mptbase.c
字号:
if (pdev->PCI_BASEADDR_FLAGS(ii) & PCI_BASE_ADDRESS_SPACE_IO) { /* Get I/O space! */ port = pdev->PCI_BASEADDR_START(ii); psize = PCI_BASEADDR_SIZE(pdev,ii); } else { /* Get memmap */ mem_phys = pdev->PCI_BASEADDR_START(ii); msize = PCI_BASEADDR_SIZE(pdev,ii); break; } } ioc->mem_size = msize; if (ii == 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)); dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n", &ioc->facts, &ioc->pfacts[0])); 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; } /* Save Port IO values incase we need to do downloadboot */ { u8 *pmem = (u8*)port; ioc->pio_mem_phys = port; ioc->pio_chip = (SYSIF_REGS*)pmem; } 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"; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) { ioc->chip_type = FC929X; ioc->prod_name = "LSIFC929X"; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) { ioc->chip_type = FC919X; ioc->prod_name = "LSIFC919X"; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; { /* 1030 Chip Fix. Disable Split transactions * for PCIX. Set bits 4 - 6 to zero. */ u16 pcixcmd = 0; pci_read_config_word(pdev, 0x6a, &pcixcmd); pcixcmd &= 0xFF8F; pci_write_config_word(pdev, 0x6a, pcixcmd); } } sprintf(ioc->name, "ioc%d", 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) {#ifndef __sparc__ printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", ioc->name, pdev->irq);#else printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", ioc->name, __irq_itoa(pdev->irq));#endif iounmap(mem); kfree(ioc); return -EBUSY; } ioc->pci_irq = pdev->irq; pci_set_master(pdev); /* ?? */#ifndef __sparc__ dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));#else dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));#endif } /* 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 "bound ports" (929, 929X, 1030) to reduce redundant resets. */ if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) || (ioc->chip_type == FC929X)) mpt_detect_bound_ports(ioc, pdev); if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 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 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. * * 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 * -1 if failed to get board READY * -2 if READY but IOCFacts Failed * -3 if READY but PrimeIOCFifos Failed * -4 if READY but IOCInit Failed */static intmpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag){ int hard_reset_done = 0; int alt_ioc_ready = 0; int hard; int r; int ii; 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! */ if (ioc->alt_ioc) { /* Disable alt-IOC's reply interrupts for a bit ... */ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); ioc->alt_ioc->active = 0; /* NOTE: Access to alt-IOC's request FreeQ is now blocked! */ } hard = 1; if (reason == MPT_HOSTEVENT_IOC_BRINGUP) hard = 0; if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) { printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", ioc->name); return -1; } /* hard_reset_done = 0 if a soft reset was performed * and 1 if a hard reset was performed. */ if (hard_reset_done && ioc->alt_ioc) { if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) alt_ioc_ready = 1; else printk(KERN_WARNING MYNAM ": alt-%s: (%d) Not ready WARNING!\n", ioc->alt_ioc->name, r); } /* Get IOC facts! */ if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) return -2; if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); } if (alt_ioc_ready) { if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) return -2; if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc->alt_ioc); } } /* * Prime reply & request queues! * (mucho alloc's) Must be done prior to * init as upper addresses are needed for init. */ if ((r = PrimeIocFifos(ioc)) != 0) return -3; // May need to check/upload firmware & data here! if ((r = SendIocInit(ioc, sleepFlag)) != 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); alt_ioc_ready = 0; } if (alt_ioc_ready) { if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { alt_ioc_ready = 0; printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n", ioc->alt_ioc->name, r); } } if (reason == MPT_HOSTEVENT_IOC_BRINGUP){ if (ioc->upload_fw) { ddlprintk((MYIOC_s_INFO_FMT "firmware upload required!\n", ioc->name)); r = mpt_do_upload(ioc, sleepFlag); if (r != 0) printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); /* Handle the alt IOC too */ if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){ r = mpt_do_upload(ioc->alt_ioc, sleepFlag); if (r != 0) printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); } } } /* Enable! (reply interrupt) */ CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); ioc->active = 1; if (ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt) */ dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ioc->alt_ioc->name)); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); ioc->alt_ioc->active = 1; } /* NEW! 20010120 -sralston * Enable MPT base driver management of EventNotification * and EventAck handling. */ if (!ioc->facts.EventState) (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */ if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */ /* (Bugzilla:fibrebugs, #513) * Bug fix (part 2)! 20010905 -sralston * Add additional "reason" check before call to GetLanConfigPages * (combined with GetIoUnitPage2 call). This prevents a somewhat * recursive scenario; GetLanConfigPages times out, timer expired * routine calls HardResetHandler, which calls into here again, * and we try GetLanConfigPages again... */ if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { if ((int)ioc->chip_type <= (int)FC929) { /* * Pre-fetch FC port WWN and stuff... * (FCPortPage0_t stuff) */ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { (void) GetFcPortPage0(ioc, ii); } if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && (ioc->lan_cnfg_page0.Header.PageLength == 0)) { /* * Pre-fetch the ports LAN MAC address! * (LANPage1_t stuff) */ (void) GetLanConfigPages(ioc);#ifdef MPT_DEBUG { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] )); }#endif } } else { /* Get NVRAM and adapter maximums from SPP 0 and 2 */ mpt_GetScsiPortSettings(ioc, 0); /* Get version and length of SDP 1 */ mpt_readScsiDevicePageHeaders(ioc, 0); /* Find IM volumes */ if (ioc->facts.MsgVersion >= 0x0102) mpt_findImVolumes(ioc); } GetIoUnitPage2(ioc); } /* * 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 (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if (MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", ioc->name, ii)); r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); handlers++; if (alt_ioc_ready) { dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; } } } /* FIXME? Examine results here? */ } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_detect_bound_ports - Search for PCI bus/dev_function * which matches PCI bus/dev_function (+/-1) for newly discovered 929, * 929X or 1030. * @ioc: Pointer to MPT adapter structure * @pdev: Pointer to (struct pci_dev) structure * * If match on PCI dev_function +/-1 is found, bind the two MPT adapters * using alt_ioc pointer fields in their %MPT_ADAPTER structures. */static voidmpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev){ MPT_ADAPTER *ioc_srch = mpt_adapter_find_first(); unsigned int match_lo, match_hi; match_lo = pdev->devfn-1; match_hi = pdev->devfn+1; dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n", ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi)); while (ioc_srch != NULL) { struct pci_dev *_pcidev = ioc_srch->pcidev; if ((_pcidev->device == pdev->device) && (_pcidev->bus->number == pdev->bus->number) && (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) { /* Paranoia checks */ if (ioc->alt_ioc != NULL) { printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", ioc->name, ioc->alt_ioc->name); break; } else if (ioc_srch->alt_ioc != NULL) { printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", ioc_srch->name, ioc_srch->alt_ioc->name); break; } dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n", ioc->name, ioc_srch->name)); ioc_srch->alt_ioc = ioc; ioc->alt_ioc = ioc_srch; break; } ioc_srch = mpt_adapter_find_next(ioc_srch); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_adapter_disable - Disable misbehaving MPT adapter. * @this: Pointer to MPT adapter structure * @free: Free up alloc'd reply, request, etc. */static voidmpt_adapter_disable(MPT_ADAPTER *this, int freeup){ if (this != NULL) { int sz; u32 state; /* Disable the FW */ state = mpt_GetIocState(this, 1); if (state == MPI_IOC_STATE_OPERATIONAL) { if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP) != 0) (void) KickStart(this, 1, NO_SLEEP); } if (this->cached_fw != NULL) { ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n")); if ((state = mpt_downloadboot(this, NO_SLEEP)) < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -