📄 mptctl.c
字号:
pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + (req_idx * MPT_SENSE_BUFFER_ALLOC)); if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) { if (hd->Targets) pTarget = hd->Targets[target]; } if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; /* Have the IOCTL driver set the direction based * on the dataOutSize (ordering issue with Sparc). */ if (karg.dataOutSize > 0) { scsidir = MPI_SCSIIO_CONTROL_WRITE; dataSize = karg.dataOutSize; } else { scsidir = MPI_SCSIIO_CONTROL_READ; dataSize = karg.dataInSize; } pScsiReq->Control = cpu_to_le32(scsidir | qtag); pScsiReq->DataLength = cpu_to_le32(dataSize); ioc->ioctl->reset = MPTCTL_RESET_OK; ioc->ioctl->target = target; } else { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } break; case MPI_FUNCTION_RAID_ACTION: /* Just add a SGE */ break; case MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: if (ioc->sh) { SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; int qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; int scsidir = MPI_SCSIIO_CONTROL_READ; int dataSize; pScsiReq->MsgFlags = mpt_msg_flags(); /* verify that app has not requested * more sense data than driver * can provide, if so, reset this parameter * set the sense buffer pointer low address * update the control field to specify Q type */ if (karg.maxSenseBytes > MPT_SENSE_BUFFER_SIZE) pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; else pScsiReq->SenseBufferLength = karg.maxSenseBytes; pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + (req_idx * MPT_SENSE_BUFFER_ALLOC)); /* All commands to physical devices are tagged */ /* Have the IOCTL driver set the direction based * on the dataOutSize (ordering issue with Sparc). */ if (karg.dataOutSize > 0) { scsidir = MPI_SCSIIO_CONTROL_WRITE; dataSize = karg.dataOutSize; } else { scsidir = MPI_SCSIIO_CONTROL_READ; dataSize = karg.dataInSize; } pScsiReq->Control = cpu_to_le32(scsidir | qtag); pScsiReq->DataLength = cpu_to_le32(dataSize); ioc->ioctl->reset = MPTCTL_RESET_OK; ioc->ioctl->target = pScsiReq->TargetID; } else { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } break; case MPI_FUNCTION_SCSI_TASK_MGMT: { MPT_SCSI_HOST *hd = NULL; if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver not loaded or SCSI host not found. \n", __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } else if (mptctl_set_tm_flags(hd) != 0) { rc = -EPERM; goto done_free_mem; } } break; case MPI_FUNCTION_IOC_INIT: { IOCInit_t *pInit = (IOCInit_t *) mf; u32 high_addr, sense_high; /* Verify that all entries in the IOC INIT match * existing setup (and in LE format). */ if (sizeof(dma_addr_t) == sizeof(u64)) { high_addr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32)); sense_high= cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32)); } else { high_addr = 0; sense_high= 0; } if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) || (pInit->MaxBuses != ioc->facts.MaxBuses) || (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) || (pInit->HostMfaHighAddr != high_addr) || (pInit->SenseBufferHighAddr != sense_high)) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n", __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } } break; default: /* * MPI_FUNCTION_PORT_ENABLE * MPI_FUNCTION_TARGET_CMD_BUFFER_POST * MPI_FUNCTION_TARGET_ASSIST * MPI_FUNCTION_TARGET_STATUS_SEND * MPI_FUNCTION_TARGET_MODE_ABORT * MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET * MPI_FUNCTION_IO_UNIT_RESET * MPI_FUNCTION_HANDSHAKE * MPI_FUNCTION_REPLY_FRAME_REMOVAL * MPI_FUNCTION_EVENT_NOTIFICATION * (driver handles event notification) * MPI_FUNCTION_EVENT_ACK */ /* What to do with these??? CHECK ME!!! MPI_FUNCTION_FC_LINK_SRVC_BUF_POST MPI_FUNCTION_FC_LINK_SRVC_RSP MPI_FUNCTION_FC_ABORT MPI_FUNCTION_LAN_SEND MPI_FUNCTION_LAN_RECEIVE MPI_FUNCTION_LAN_RESET */ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Illegal request (function 0x%x) \n", __FILE__, __LINE__, hdr->Function); rc = -EFAULT; goto done_free_mem; } /* Add the SGL ( at most one data in SGE and one data out SGE ) * In the case of two SGE's - the data out (write) will always * preceede the data in (read) SGE. psgList is used to free the * allocated memory. */ psge = (char *) (((int *) mf) + karg.dataSgeOffset); flagsLength = 0; /* bufIn and bufOut are used for user to kernel space transfers */ bufIn.kptr = bufOut.kptr = NULL; bufIn.len = bufOut.len = 0; if (karg.dataOutSize > 0) sgSize ++; if (karg.dataInSize > 0) sgSize ++; if (sgSize > 0) { /* Set up the dataOut memory allocation */ if (karg.dataOutSize > 0) { if (karg.dataInSize > 0) { flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | MPI_SGE_FLAGS_DIRECTION | mpt_addr_size() ) << MPI_SGE_FLAGS_SHIFT; } else { flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; } flagsLength |= karg.dataOutSize; bufOut.len = karg.dataOutSize; bufOut.kptr = pci_alloc_consistent( ioc->pcidev, bufOut.len, &dma_addr_out); if (bufOut.kptr == NULL) { rc = -ENOMEM; goto done_free_mem; } else { /* Set up this SGE. * Copy to MF and to sglbuf */ mpt_add_sge(psge, flagsLength, dma_addr_out); psge += (sizeof(u32) + sizeof(dma_addr_t)); /* Copy user data to kernel space. */ if (copy_from_user(bufOut.kptr, karg.dataOutBufPtr, bufOut.len)) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - Unable " "to read user data " "struct @ %p\n", __FILE__, __LINE__,karg.dataOutBufPtr); rc = -EFAULT; goto done_free_mem; } } } if (karg.dataInSize > 0) { flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; flagsLength |= karg.dataInSize; bufIn.len = karg.dataInSize; bufIn.kptr = pci_alloc_consistent(ioc->pcidev, bufIn.len, &dma_addr_in); if (bufIn.kptr == NULL) { rc = -ENOMEM; goto done_free_mem; } else { /* Set up this SGE * Copy to MF and to sglbuf */ mpt_add_sge(psge, flagsLength, dma_addr_in); } } } else { /* Add a NULL SGE */ mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); } ioc->ioctl->wait_done = 0; if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf); if (mpt_send_handshake_request(mptctl_id, ioc, sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP) != 0) { dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" " (ioc %p, mf %p) \n", ioc->name, ioc, mf)); mptctl_free_tm_flags(ioc); rc = -ENODATA; goto done_free_mem; } } else mpt_put_msg_frame(mptctl_id, ioc, mf); /* Now wait for the command to complete */ timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; timeout = wait_event_interruptible_timeout(mptctl_wait, ioc->ioctl->wait_done == 1, HZ*timeout); if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) { /* Now we need to reset the board */ if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) mptctl_free_tm_flags(ioc); mptctl_timeout_expired(ioc->ioctl); rc = -ENODATA; goto done_free_mem; } mf = NULL; /* If a valid reply frame, copy to the user. * Offset 2: reply length in U32's */ if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { if (karg.maxReplyBytes < ioc->reply_sz) { sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]); } else { sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]); } if (sz > 0) { if (copy_to_user(karg.replyFrameBufPtr, &ioc->ioctl->ReplyFrame, sz)){ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write out reply frame %p\n", __FILE__, __LINE__, karg.replyFrameBufPtr); rc = -ENODATA; goto done_free_mem; } } } /* If valid sense data, copy to user. */ if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) { sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); if (sz > 0) { if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write sense data to user %p\n", __FILE__, __LINE__, karg.senseDataPtr); rc = -ENODATA; goto done_free_mem; } } } /* If the overall status is _GOOD and data in, copy data * to user. */ if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) && (karg.dataInSize > 0) && (bufIn.kptr)) { if (copy_to_user(karg.dataInBufPtr, bufIn.kptr, karg.dataInSize)) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write data to user %p\n", __FILE__, __LINE__, karg.dataInBufPtr); rc = -ENODATA; } }done_free_mem: ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | MPT_IOCTL_STATUS_RF_VALID ); /* Free the allocated memory. */ if (bufOut.kptr != NULL) { pci_free_consistent(ioc->pcidev, bufOut.len, (void *) bufOut.kptr, dma_addr_out); } if (bufIn.kptr != NULL) { pci_free_consistent(ioc->pcidev, bufIn.len, (void *) bufIn.kptr, dma_addr_in); } /* mf is null if command issued successfully * otherwise, failure occured after mf acquired. */ if (mf) mpt_free_msg_frame(ioc, mf); return rc;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* Prototype Routine for the HP HOST INFO command. * * Outputs: None. * Return: 0 if successful * -EFAULT if data unavailable * -EBUSY if previous command timout and IOC reset is not complete. * -ENODEV if no such device/adapter * -ETIME if timer expires * -ENOMEM if memory allocation error */static intmptctl_hp_hostinfo(unsigned long arg, unsigned int data_size){ hp_host_info_t __user *uarg = (void __user *) arg; MPT_ADAPTER *ioc; struct pci_dev *pdev; char *pbuf; dma_addr_t buf_dma; hp_host_info_t karg; CONFIGPARMS cfg; ConfigPageHeader_t hdr; int iocnum; int rc, cim_rev; dctlprintk((": mptctl_hp_hostinfo called.\n")); /* Reset long to int. Should affect IA64 and SPARC only */ if (data_size == sizeof(hp_host_info_t)) cim_rev = 1; else if (data_size == sizeof(hp_host_info_rev0_t)) cim_rev = 0; /* obsolete */ else return -EFAULT; if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) { printk(KERN_ERR "%s@%d::mptctl_hp_host_info - " "Unable to read in hp_host_info 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_hp_hostinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } /* Fill in the data and return the structure to the calling * program */ pdev = (struct pci_dev *) ioc->pcidev; karg.vendor = pdev->vendor; karg.device = pdev->device; karg.subsystem_id = pdev->subsystem_device; karg.subsystem_vendor = pdev->subsystem_vendor; karg.devfn = pdev->devfn; karg.bus = pdev->bus->number; /* Save the SCSI host no. if * SCSI driver loaded */ if (ioc->sh != NULL) karg.host_no = ioc->sh->host_no; else karg.host_no = -1; /* Reformat the fw_version into a string */ karg.fw_version[0] = ioc->facts.FWVersion.Struct.Major >= 10 ? ((ioc->facts.FWVersion.Struct.Major / 10) + '0') : '0'; karg.fw_version[1] = (ioc->facts.FWVersion.Struct.Major % 10 ) + '0'; karg.fw_version[2] = '.'; karg.fw_version[3] = ioc->facts.FWVersion.Struct.Minor >= 10 ? ((ioc->facts.FWVersion.Struct.Minor / 10) + '0') : '0'; karg.fw_version[4] = (ioc->facts.FWVersion.Struct.Minor % 10 ) + '0'; karg.fw_version[5] = '.'; karg.fw_version[6] = ioc->facts.FWVersion.Struct.Unit >= 10 ? ((ioc->facts.FWVersion.Struct.Unit / 10) + '0') : '0'; karg.fw_version[7] = (ioc->facts.FWVersion.Struct.Unit % 10 ) + '0'; karg.fw_version[8] = '.'; karg.fw_version[9] = ioc->facts.FWVersion.Stru
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -