📄 mptctl.c
字号:
if (maxWordsLeft <= 0) { printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", __FILE__, __LINE__); return -ENOMEM; } /* Fill in the data and return the structure to the calling * program */ /* struct mpt_ioctl_targetinfo does not contain sufficient space * for the target structures so when the IOCTL is called, there is * not sufficient stack space for the structure. Allocate memory, * populate the memory, copy back to the user, then free memory. * targetInfo format: * bits 31-24: reserved * 23-16: LUN * 15- 8: Bus Number * 7- 0: Target ID */ pmem = kmalloc(numBytes, GFP_KERNEL); if (pmem == NULL) { printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", __FILE__, __LINE__); return -ENOMEM; } memset(pmem, 0, numBytes); pdata = (int *) pmem; /* Get number of devices */ if ( (sh = ioc->sh) != NULL) { max_id = sh->max_id - 1; hd = (MPT_SCSI_HOST *) sh->hostdata; /* Check all of the target structures. * Save the Id and increment the counter, * if ptr non-null. * sh->max_id = maximum target ID + 1 */ if (hd && hd->Targets) { ii = 0; while (ii <= max_id) { if (hd->Targets[ii]) { for (jj = 0; jj <= MPT_LAST_LUN; jj++) { lun = (1 << jj); if (hd->Targets[ii]->luns & lun) { numDevices++; *pdata = (jj << 16) | ii; --maxWordsLeft; pdata++; if (maxWordsLeft <= 0) { break; } } } } ii++; } } } karg.numDevices = numDevices; /* Copy part of the data from kernel memory to user memory */ if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_targetinfo))) { printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); kfree(pmem); return -EFAULT; } /* Copy the remaining data from kernel memory to user memory */ if (copy_to_user((char *) uarg->targetInfo, pmem, numBytes)) { printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", __FILE__, __LINE__, (void*)pdata); kfree(pmem); return -EFAULT; } kfree(pmem); return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* MPT IOCTL Test function. * * Outputs: None. * Return: 0 if successful * -EFAULT if data unavailable * -ENODEV if no such device/adapter */static intmptctl_readtest (unsigned long arg){ struct mpt_ioctl_test *uarg = (struct mpt_ioctl_test *) arg; struct mpt_ioctl_test karg; MPT_ADAPTER *ioc; int iocnum; dctlprintk(("mptctl_readtest called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) { printk(KERN_ERR "%s@%d::mptctl_readtest - " "Unable to read in mpt_ioctl_test struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } /* Fill in the data and return the structure to the calling * program */#ifdef MFCNT karg.chip_type = ioc->mfcnt;#else karg.chip_type = ioc->chip_type;#endif strncpy (karg.name, ioc->name, MPT_MAX_NAME); strncpy (karg.product, ioc->prod_name, MPT_PRODUCT_LENGTH); /* Copy the data from kernel memory to user memory */ if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_test))) { printk(KERN_ERR "%s@%d::mptctl_readtest - " "Unable to write out mpt_ioctl_test struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptctl_eventquery - Query the host adapter for the event types * that are being logged. * @arg: User space argument * * Outputs: None. * Return: 0 if successful * -EFAULT if data unavailable * -ENODEV if no such device/adapter */static intmptctl_eventquery (unsigned long arg){ struct mpt_ioctl_eventquery *uarg = (struct mpt_ioctl_eventquery *) arg; struct mpt_ioctl_eventquery karg; MPT_ADAPTER *ioc; int iocnum; dctlprintk(("mptctl_eventquery called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) { printk(KERN_ERR "%s@%d::mptctl_eventquery - " "Unable to read in mpt_ioctl_eventquery struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } karg.eventEntries = ioc->eventLogSize; karg.eventTypes = ioc->eventTypes; /* Copy the data from kernel memory to user memory */ if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) { printk(KERN_ERR "%s@%d::mptctl_eventquery - " "Unable to write out mpt_ioctl_eventquery struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmptctl_eventenable (unsigned long arg){ struct mpt_ioctl_eventenable *uarg = (struct mpt_ioctl_eventenable *) arg; struct mpt_ioctl_eventenable karg; MPT_ADAPTER *ioc; int iocnum; dctlprintk(("mptctl_eventenable called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) { printk(KERN_ERR "%s@%d::mptctl_eventenable - " "Unable to read in mpt_ioctl_eventenable struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } if (ioc->events == NULL) { /* Have not yet allocated memory - do so now. */ int sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); ioc->events = kmalloc(sz, GFP_KERNEL); if (ioc->events == NULL) { printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; } memset(ioc->events, 0, sz); ioc->alloc_total += sz; ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE; ioc->eventContext = 0; } /* Update the IOC event logging flag. */ ioc->eventTypes = karg.eventTypes; return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmptctl_eventreport (unsigned long arg){ struct mpt_ioctl_eventreport *uarg = (struct mpt_ioctl_eventreport *) arg; struct mpt_ioctl_eventreport karg; MPT_ADAPTER *ioc; int iocnum; int numBytes, maxEvents, max; dctlprintk(("mptctl_eventreport called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) { printk(KERN_ERR "%s@%d::mptctl_eventreport - " "Unable to read in mpt_ioctl_eventreport struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } numBytes = karg.hdr.maxDataSize - sizeof(mpt_ioctl_header); maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS); max = ioc->eventLogSize < maxEvents ? ioc->eventLogSize : maxEvents; /* If fewer than 1 event is requested, there must have * been some type of error. */ if ((max < 1) || !ioc->events) return -ENODATA; /* Copy the data from kernel memory to user memory */ numBytes = max * sizeof(MPT_IOCTL_EVENTS); if (copy_to_user((char *) uarg->eventData, ioc->events, numBytes)) { printk(KERN_ERR "%s@%d::mptctl_eventreport - " "Unable to write out mpt_ioctl_eventreport struct @ %p\n", __FILE__, __LINE__, (void*)ioc->events); return -EFAULT; } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmptctl_replace_fw (unsigned long arg){ struct mpt_ioctl_replace_fw *uarg = (struct mpt_ioctl_replace_fw *) arg; struct mpt_ioctl_replace_fw karg; MPT_ADAPTER *ioc; fw_image_t **fwmem = NULL; int iocnum; int newFwSize; int num_frags, alloc_sz; int ii; u32 offset; dctlprintk(("mptctl_replace_fw called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) { printk(KERN_ERR "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } /* If not caching FW, return 0 */ if ((ioc->cached_fw == NULL) && (ioc->alt_ioc) && (ioc->alt_ioc->cached_fw == NULL)) return 0; /* Allocate memory for the new FW image */ newFwSize = karg.newImageSize; fwmem = mpt_alloc_fw_memory(ioc, newFwSize, &num_frags, &alloc_sz); if (fwmem == NULL) return -ENOMEM; offset = 0; for (ii = 0; ii < num_frags; ii++) { /* Copy the data from user memory to kernel space */ if (copy_from_user(fwmem[ii]->fw, uarg->newImage + offset, fwmem[ii]->size)) { printk(KERN_ERR "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw image @ %p\n", __FILE__, __LINE__, (void*)uarg); mpt_free_fw_memory(ioc, fwmem); return -EFAULT; } offset += fwmem[ii]->size; } /* Free the old FW image */ if (ioc->cached_fw) { mpt_free_fw_memory(ioc, 0); ioc->cached_fw = fwmem; ioc->alloc_total += alloc_sz; } else if ((ioc->alt_ioc) && (ioc->alt_ioc->cached_fw)) { mpt_free_fw_memory(ioc->alt_ioc, 0); ioc->alt_ioc->cached_fw = fwmem; ioc->alt_ioc->alloc_total += alloc_sz; } /* Update IOCFactsReply */ ioc->facts.FWImageSize = newFwSize; if (ioc->alt_ioc) ioc->alt_ioc->facts.FWImageSize = newFwSize; return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* MPT IOCTL MPTCOMMAND function. * Cast the arg into the mpt_ioctl_mpt_command structure. * * Outputs: None. * Return: 0 if successful * -EBUSY if previous command timout and IOC reset is not complete. * -EFAULT if data unavailable * -ENODEV if no such device/adapter * -ETIME if timer expires * -ENOMEM if memory allocation error */static intmptctl_mpt_command (unsigned long arg){ struct mpt_ioctl_command *uarg = (struct mpt_ioctl_command *) arg; struct mpt_ioctl_command karg; MPT_ADAPTER *ioc; int iocnum; int rc; dctlprintk(("mptctl_command called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) { printk(KERN_ERR "%s@%d::mptctl_mpt_command - " "Unable to read in mpt_ioctl_command struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } rc = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0); return rc;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* Worker routine for the IOCTL MPTCOMMAND and MPTCOMMAND32 (sparc) commands. * * Outputs: None. * Return: 0 if successful * -EBUSY if previous command timout and IOC reset is not complete. * -EFAULT if data unavailable * -ENODEV if no such device/adapter * -ETIME if timer expires * -ENOMEM if memory allocation error * -EPERM if SCSI I/O and target is untagged */static intmptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local){ MPT_ADAPTER *ioc; MPT_FRAME_HDR *mf = NULL; MPIHeader_t *hdr; char *psge; MptSge_t *this_sge = NULL; MptSge_t *sglbuf = NULL; struct buflist bufIn; /* data In buffer */ struct buflist bufOut; /* data Out buffer */ dma_addr_t sglbuf_dma; dma_addr_t dma_addr; int dir; /* PCI data direction */ int sgSize = 0; /* Num SG elements */ int this_alloc; int iocnum, flagsLength; int sz, rc = 0; int msgContext; int tm_flags_set = 0; u16 req_idx; dctlprintk(("mptctl_do_mpt_command called.\n")); if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } if (!ioc->ioctl) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "No memory available during driver init.\n", __FILE__, __LINE__); return -ENOMEM; } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -