📄 mptctl.c
字号:
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) { mpt_findImVolumes(ioc); pIoc2 = ioc->spi_data.pIocPg2; for ( id = 0; id <= max_id; ) { if ( pIoc2 && pIoc2->NumActiveVolumes ) { if ( id == pIoc2->RaidVolume[0].VolumeID ) { if (maxWordsLeft <= 0) { printk(KERN_ERR "mptctl_gettargetinfo - " "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices); goto data_space_full; } if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 ) devType = 0x80; else devType = 0xC0; bus_id = pIoc2->RaidVolume[0].VolumeBus; numDevices++; *pdata = ( (devType << 24) | (bus_id << 8) | id ); dctlprintk((KERN_ERR "mptctl_gettargetinfo - " "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); pdata++; --maxWordsLeft; goto next_id; } else { pIoc3 = ioc->spi_data.pIocPg3; for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) goto next_id; } } } if ( (vdev = hd->Targets[id]) ) { for (jj = 0; jj <= MPT_LAST_LUN; jj++) { lun_index = (jj >> 5); indexed_lun = (jj % 32); lun = (1 << indexed_lun); if (vdev->luns[lun_index] & lun) { if (maxWordsLeft <= 0) { printk(KERN_ERR "mptctl_gettargetinfo - " "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices); goto data_space_full; } bus_id = vdev->bus_id; numDevices++; *pdata = ( (jj << 16) | (bus_id << 8) | id ); dctlprintk((KERN_ERR "mptctl_gettargetinfo - " "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); pdata++; --maxWordsLeft; } } }next_id: id++; } } }data_space_full: karg.numDevices = numDevices; /* Copy part of the data from kernel memory to user memory */ if (copy_to_user((char __user *)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__, uarg); kfree(pmem); return -EFAULT; } /* Copy the remaining data from kernel memory to user memory */ if (copy_to_user(uarg->targetInfo, pmem, numBytes)) { printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", __FILE__, __LINE__, 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 __user *uarg = (void __user *) 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__, 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->pcidev->device;#endif strncpy (karg.name, ioc->name, MPT_MAX_NAME); karg.name[MPT_MAX_NAME-1]='\0'; strncpy (karg.product, ioc->prod_name, MPT_PRODUCT_LENGTH); karg.product[MPT_PRODUCT_LENGTH-1]='\0'; /* Copy the data from kernel memory to user memory */ if (copy_to_user((char __user *)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__, 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 __user *uarg = (void __user *) 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__, 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 __user *)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__, uarg); return -EFAULT; } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmptctl_eventenable (unsigned long arg){ struct mpt_ioctl_eventenable __user *uarg = (void __user *) 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__, 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 __user *uarg = (void __user *) 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__, 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(uarg->eventData, ioc->events, numBytes)) { printk(KERN_ERR "%s@%d::mptctl_eventreport - " "Unable to write out mpt_ioctl_eventreport struct @ %p\n", __FILE__, __LINE__, ioc->events); return -EFAULT; } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmptctl_replace_fw (unsigned long arg){ struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg; struct mpt_ioctl_replace_fw karg; MPT_ADAPTER *ioc; int iocnum; int newFwSize; 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__, 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 caching FW, Free the old FW image */ if (ioc->cached_fw == NULL) return 0; mpt_free_fw_memory(ioc); /* Allocate memory for the new FW image */ newFwSize = karg.newImageSize; if (newFwSize & 0x01) newFwSize += 1; if (newFwSize & 0x02) newFwSize += 2; mpt_alloc_fw_memory(ioc, newFwSize); if (ioc->cached_fw == NULL) return -ENOMEM; /* Copy the data from user memory to kernel space */ if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) { printk(KERN_ERR "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw image " "@ %p\n", __FILE__, __LINE__, uarg); mpt_free_fw_memory(ioc); return -EFAULT; } /* Update IOCFactsReply */ 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 __user *uarg = (void __user *) 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__, 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, &uarg->MF); 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, void __user *mfPtr){ MPT_ADAPTER *ioc; MPT_FRAME_HDR *mf = NULL; MPIHeader_t *hdr; char *psge; struct buflist bufIn; /* data In buffer */ struct buflist bufOut; /* data Out buffer */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -