📄 mptbase.c
字号:
printk("\n"); }#endif mf_dma_addr = iocp->req_frames_low_dma + req_offset; CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr); } else { printk (KERN_ERR "mpt_put_msg_frame: Invalid iocid=%d\n", iocid); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_free_msg_frame - Place MPT request frame back on FreeQ. * @handle: Handle of registered MPT protocol driver * @iocid: IOC unique identifier (integer) * @mf: Pointer to MPT request frame * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */voidmpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf){ MPT_ADAPTER *iocp; unsigned long flags; iocp = mpt_adapters[iocid]; if (iocp != NULL) { /* Put Request back on FreeQ! */ spin_lock_irqsave(&iocp->FreeQlock, flags); Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);#ifdef MFCNT iocp->mfcnt--;#endif spin_unlock_irqrestore(&iocp->FreeQlock, flags); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_add_sge - Place a simple SGE at address pAddr. * @pAddr: virtual address for SGE * @flagslength: SGE flags and data transfer length * @dma_addr: Physical address * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */voidmpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr){ if (sizeof(dma_addr_t) == sizeof(u64)) { SGESimple64_t *pSge = (SGESimple64_t *) pAddr; u32 tmp = dma_addr & 0xFFFFFFFF; pSge->FlagsLength = cpu_to_le32(flagslength); pSge->Address.Low = cpu_to_le32(tmp); tmp = (u32) ((u64)dma_addr >> 32); pSge->Address.High = cpu_to_le32(tmp); } else { SGESimple32_t *pSge = (SGESimple32_t *) pAddr; pSge->FlagsLength = cpu_to_le32(flagslength); pSge->Address = cpu_to_le32(dma_addr); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_add_chain - Place a chain SGE at address pAddr. * @pAddr: virtual address for SGE * @next: nextChainOffset value (u32's) * @length: length of next SGL segment * @dma_addr: Physical address * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */voidmpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr){ if (sizeof(dma_addr_t) == sizeof(u64)) { SGEChain64_t *pChain = (SGEChain64_t *) pAddr; u32 tmp = dma_addr & 0xFFFFFFFF; pChain->Length = cpu_to_le16(length); pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); pChain->NextChainOffset = next; pChain->Address.Low = cpu_to_le32(tmp); tmp = (u32) ((u64)dma_addr >> 32); pChain->Address.High = cpu_to_le32(tmp); } else { SGEChain32_t *pChain = (SGEChain32_t *) pAddr; pChain->Length = cpu_to_le16(length); pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); pChain->NextChainOffset = next; pChain->Address = cpu_to_le32(dma_addr); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_send_handshake_request - Send MPT request via doorbell * handshake method. * @handle: Handle of registered MPT protocol driver * @iocid: IOC unique identifier (integer) * @reqBytes: Size of the request in bytes * @req: Pointer to MPT request frame * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. * * This routine is used exclusively to send MptScsiTaskMgmt * requests since they are required to be sent via doorbell handshake. * * NOTE: It is the callers responsibility to byte-swap fields in the * request which are greater than 1 byte in size. * * Returns 0 for success, non-zero for failure. */intmpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag){ MPT_ADAPTER *iocp; int r = 0; iocp = mpt_adapters[iocid]; if (iocp != NULL) { u8 *req_as_bytes; int ii; /* State is known to be good upon entering * this function so issue the bus reset * request. */ /* * Emulate what mpt_put_msg_frame() does /wrt to sanity * setting cb_idx/req_idx. But ONLY if this request * is in proper (pre-alloc'd) request buffer range... */ ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req); if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) { MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; } /* Make sure there are no doorbells */ CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); CHIPREG_WRITE32(&iocp->chip->Doorbell, ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) | ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT))); /* Wait for IOC doorbell int */ if ((ii = WaitForDoorbellInt(iocp, 5, sleepFlag)) < 0) { return ii; } /* Read doorbell and check for active bit */ if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) return -5; dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", iocp->name, ii)); CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) { return -2; } /* Send request via doorbell handshake */ req_as_bytes = (u8 *) req; for (ii = 0; ii < reqBytes/4; ii++) { u32 word; word = ((req_as_bytes[(ii*4) + 0] << 0) | (req_as_bytes[(ii*4) + 1] << 8) | (req_as_bytes[(ii*4) + 2] << 16) | (req_as_bytes[(ii*4) + 3] << 24)); CHIPREG_WRITE32(&iocp->chip->Doorbell, word); if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) { r = -3; break; } } if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0) r = 0; else r = -4; /* Make sure there are no doorbells */ CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); } return r;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_adapter_find_first - Find first MPT adapter pointer. * * Returns first MPT adapter pointer or %NULL if no MPT adapters * are present. */MPT_ADAPTER *mpt_adapter_find_first(void){ MPT_ADAPTER *this; if (! Q_IS_EMPTY(&MptAdapters)) this = MptAdapters.head; else this = NULL; return this;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_adapter_find_next - Find next MPT adapter pointer. * @prev: Pointer to previous MPT adapter * * Returns next MPT adapter pointer or %NULL if there are no more. */MPT_ADAPTER *mpt_adapter_find_next(MPT_ADAPTER *prev){ MPT_ADAPTER *next; if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head)) next = prev->forw; else next = NULL; return next;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_pci_scan - Scan PCI devices for MPT adapters. * * Returns count of MPT adapters found, keying off of PCI vendor and * device_id's. */static 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, 929X, 1030 and 1035 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) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929X) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919X) && (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) && (pdev->device != MPI_MANUFACTPAGE_DEVID_1030_53C1035) && 1) { dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device)); continue; } /* GRRRRR * dual function devices (929, 929X, 1030, 1035) 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 == pdev->device) && (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 (void) procmpt_create();#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; u8 *mem; unsigned long mem_phys; unsigned long port; u32 msize; u32 psize; int ii; int r = -ENODEV; u64 mask = 0xffffffffffffffffULL; u8 revision; u8 pcixcmd; if (pci_enable_device(pdev)) return r; /* For some kernels, broken kernel limits memory allocation for target mode * driver. Shirron. Fixed in 2.4.20-8 * if ((sizeof(dma_addr_t) == sizeof(u64)) && (!pci_set_dma_mask(pdev, mask))) { */ if ((!pci_set_dma_mask(pdev, mask))) { dprintk((KERN_INFO MYNAM ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); } else { if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) { printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); return r; } } ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); if (ioc == NULL) { printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; } memset(ioc, 0, sizeof(MPT_ADAPTER)); ioc->alloc_total = sizeof(MPT_ADAPTER); ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ ioc->reply_sz = MPT_REPLY_FRAME_SIZE; ioc->pcidev = pdev; ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); /* Initialize the event logging. */ ioc->eventTypes = 0; /* None */ ioc->eventContext = 0; ioc->eventLogSize = 0; ioc->events = NULL;#ifdef MFCNT ioc->mfcnt = 0;#endif ioc->cached_fw = NULL; /* Initilize SCSI Config Data structure */ memset(&ioc->spi_data, 0, sizeof(ScsiCfgData)); /* Initialize the running configQ head. */ Q_INIT(&ioc->configQ, Q_ITEM); /* Find lookup slot. */ for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) { if (mpt_adapters[ii] == NULL) { ioc->id = ii; /* Assign adapter unique id (lookup) */ break; } } if (ii == MPT_MAX_ADAPTERS) { printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii); kfree(ioc); return -ENFILE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -