Changeset 46265 in vbox for trunk/src/VBox/Devices
- Timestamp:
- May 25, 2013 5:51:06 PM (12 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
r46253 r46265 22 22 #include <VBox/vmm/pdmdev.h> 23 23 #include <VBox/vmm/pdmqueue.h> 24 #include <VBox/vmm/pdmthread.h> 24 25 #include <VBox/vmm/pdmcritsect.h> 25 26 #include <VBox/scsi.h> 27 #include <VBox/sup.h> 26 28 #include <iprt/assert.h> 27 29 #include <iprt/asm.h> … … 331 333 /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when 332 334 * a port is entering the idle state. */ 333 bool volatile fSignalIdle;335 bool volatile fSignalIdle; 334 336 /** Flag whether we have tasks which need to be processed again- */ 335 bool volatile fRedo; 337 bool volatile fRedo; 338 /** Flag whether the worker thread is sleeping. */ 339 volatile bool fWrkThreadSleeping; 336 340 /** Alignment padding. */ 337 bool afPadding2[HC_ARCH_BITS == 32 ? 2 : 6];341 bool afPadding2[HC_ARCH_BITS == 32 ? 1 : 5]; 338 342 /** List of tasks which can be redone. */ 339 343 R3PTRTYPE(volatile PLSILOGICREQ) pTasksRedoHead; … … 354 358 uint8_t u8Padding[2 * sizeof(RTUINTPTR)]; 355 359 }; 360 361 /** The support driver session handle. */ 362 R3R0PTRTYPE(PSUPDRVSESSION) pSupDrvSession; 363 /** Worker thread. */ 364 R3PTRTYPE(PPDMTHREAD) pThreadWrk; 365 /** The event semaphore the processing thread waits on. */ 366 SUPSEMEVENT hEvtProcess; 367 356 368 } LSILOGISCSI; 357 369 /** Pointer to the device instance data of the LsiLogic emulation. */ … … 1274 1286 if (!ASMAtomicXchgBool(&pThis->fNotificationSend, true)) 1275 1287 { 1288 #ifdef IN_RC 1276 1289 PPDMQUEUEITEMCORE pNotificationItem = PDMQueueAlloc(pThis->CTX_SUFF(pNotificationQueue)); 1277 1290 AssertPtr(pNotificationItem); 1278 1291 1279 1292 PDMQueueInsert(pThis->CTX_SUFF(pNotificationQueue), pNotificationItem); 1293 #else 1294 LogFlowFunc(("Signal event semaphore\n")); 1295 int rc = SUPSemEventSignal(pThis->pSupDrvSession, pThis->hEvtProcess); 1296 AssertRC(rc); 1297 #endif 1280 1298 } 1281 1299 break; … … 3693 3711 LogFlowFunc(("pDevIns=%#p pItem=%#p\n", pDevIns, pItem)); 3694 3712 3695 /* Reset notification event. */ 3696 ASMAtomicXchgBool(&pThis->fNotificationSend, false); 3697 3698 /* Only process request which arrived before we received the notification. */ 3699 uint32_t uRequestQueueNextEntryWrite = ASMAtomicReadU32(&pThis->uRequestQueueNextEntryFreeWrite); 3700 3701 /* Go through the messages now and process them. */ 3702 while ( RT_LIKELY(pThis->enmState == LSILOGICSTATE_OPERATIONAL) 3703 && (pThis->uRequestQueueNextAddressRead != uRequestQueueNextEntryWrite)) 3704 { 3705 uint32_t u32RequestMessageFrameDesc = pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextAddressRead]; 3706 RTGCPHYS GCPhysMessageFrameAddr = LSILOGIC_RTGCPHYS_FROM_U32(pThis->u32HostMFAHighAddr, 3707 (u32RequestMessageFrameDesc & ~0x07)); 3708 3709 PLSILOGICREQ pLsiReq; 3710 3711 /* Get new task state. */ 3712 rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq); 3713 AssertRC(rc); 3714 3715 pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr; 3716 3717 /* Read the message header from the guest first. */ 3718 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, sizeof(MptMessageHdr)); 3719 3720 /* Determine the size of the request. */ 3721 uint32_t cbRequest = 0; 3722 3723 switch (pLsiReq->GuestRequest.Header.u8Function) 3724 { 3725 case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST: 3726 cbRequest = sizeof(MptSCSIIORequest); 3727 break; 3728 case MPT_MESSAGE_HDR_FUNCTION_SCSI_TASK_MGMT: 3729 cbRequest = sizeof(MptSCSITaskManagementRequest); 3730 break; 3731 case MPT_MESSAGE_HDR_FUNCTION_IOC_INIT: 3732 cbRequest = sizeof(MptIOCInitRequest); 3733 break; 3734 case MPT_MESSAGE_HDR_FUNCTION_IOC_FACTS: 3735 cbRequest = sizeof(MptIOCFactsRequest); 3736 break; 3737 case MPT_MESSAGE_HDR_FUNCTION_CONFIG: 3738 cbRequest = sizeof(MptConfigurationRequest); 3739 break; 3740 case MPT_MESSAGE_HDR_FUNCTION_PORT_FACTS: 3741 cbRequest = sizeof(MptPortFactsRequest); 3742 break; 3743 case MPT_MESSAGE_HDR_FUNCTION_PORT_ENABLE: 3744 cbRequest = sizeof(MptPortEnableRequest); 3745 break; 3746 case MPT_MESSAGE_HDR_FUNCTION_EVENT_NOTIFICATION: 3747 cbRequest = sizeof(MptEventNotificationRequest); 3748 break; 3749 case MPT_MESSAGE_HDR_FUNCTION_EVENT_ACK: 3750 AssertMsgFailed(("todo\n")); 3751 //cbRequest = sizeof(MptEventAckRequest); 3752 break; 3753 case MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD: 3754 cbRequest = sizeof(MptFWDownloadRequest); 3755 break; 3756 case MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD: 3757 cbRequest = sizeof(MptFWUploadRequest); 3758 break; 3759 default: 3760 AssertMsgFailed(("Unknown function issued %u\n", pLsiReq->GuestRequest.Header.u8Function)); 3761 lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INVALID_FUNCTION); 3762 } 3763 3764 if (cbRequest != 0) 3765 { 3766 /* Read the complete message frame from guest memory now. */ 3767 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, cbRequest); 3768 3769 /* Handle SCSI I/O requests now. */ 3770 if (pLsiReq->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST) 3771 { 3772 rc = lsilogicR3ProcessSCSIIORequest(pThis, pLsiReq); 3773 AssertRC(rc); 3774 } 3775 else 3776 { 3777 MptReplyUnion Reply; 3778 rc = lsilogicR3ProcessMessageRequest(pThis, &pLsiReq->GuestRequest.Header, &Reply); 3779 AssertRC(rc); 3780 RTMemCacheFree(pThis->hTaskCache, pLsiReq); 3781 } 3782 3783 pThis->uRequestQueueNextAddressRead++; 3784 pThis->uRequestQueueNextAddressRead %= pThis->cRequestQueueEntries; 3785 } 3786 } 3713 rc = SUPSemEventSignal(pThis->pSupDrvSession, pThis->hEvtProcess); 3714 AssertRC(rc); 3787 3715 3788 3716 return true; … … 4223 4151 pThis->pRequestQueueBaseR3 = NULL; 4224 4152 } 4153 4154 4155 /* The worker thread. */ 4156 static DECLCALLBACK(int) lsilogicR3Worker(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 4157 { 4158 PLSILOGICSCSI pThis = (PLSILOGICSCSI)pThread->pvUser; 4159 int rc = VINF_SUCCESS; 4160 4161 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 4162 return VINF_SUCCESS; 4163 4164 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 4165 { 4166 bool fNotificationSend; 4167 4168 ASMAtomicWriteBool(&pThis->fWrkThreadSleeping, true); 4169 fNotificationSend = ASMAtomicXchgBool(&pThis->fNotificationSend, false); 4170 if (!fNotificationSend) 4171 { 4172 Assert(ASMAtomicReadBool(&pThis->fWrkThreadSleeping)); 4173 rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pThis->hEvtProcess, RT_INDEFINITE_WAIT); 4174 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc); 4175 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING)) 4176 break; 4177 LogFlowFunc(("Woken up with rc=%Rrc\n", rc)); 4178 fNotificationSend = ASMAtomicXchgBool(&pThis->fNotificationSend, false); 4179 } 4180 4181 ASMAtomicWriteBool(&pThis->fWrkThreadSleeping, false); 4182 4183 /* Only process request which arrived before we received the notification. */ 4184 uint32_t uRequestQueueNextEntryWrite = ASMAtomicReadU32(&pThis->uRequestQueueNextEntryFreeWrite); 4185 4186 /* Go through the messages now and process them. */ 4187 while ( RT_LIKELY(pThis->enmState == LSILOGICSTATE_OPERATIONAL) 4188 && (pThis->uRequestQueueNextAddressRead != uRequestQueueNextEntryWrite)) 4189 { 4190 uint32_t u32RequestMessageFrameDesc = pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextAddressRead]; 4191 RTGCPHYS GCPhysMessageFrameAddr = LSILOGIC_RTGCPHYS_FROM_U32(pThis->u32HostMFAHighAddr, 4192 (u32RequestMessageFrameDesc & ~0x07)); 4193 4194 PLSILOGICREQ pLsiReq; 4195 4196 /* Get new task state. */ 4197 rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq); 4198 AssertRC(rc); 4199 4200 pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr; 4201 4202 /* Read the message header from the guest first. */ 4203 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, sizeof(MptMessageHdr)); 4204 4205 /* Determine the size of the request. */ 4206 uint32_t cbRequest = 0; 4207 4208 switch (pLsiReq->GuestRequest.Header.u8Function) 4209 { 4210 case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST: 4211 cbRequest = sizeof(MptSCSIIORequest); 4212 break; 4213 case MPT_MESSAGE_HDR_FUNCTION_SCSI_TASK_MGMT: 4214 cbRequest = sizeof(MptSCSITaskManagementRequest); 4215 break; 4216 case MPT_MESSAGE_HDR_FUNCTION_IOC_INIT: 4217 cbRequest = sizeof(MptIOCInitRequest); 4218 break; 4219 case MPT_MESSAGE_HDR_FUNCTION_IOC_FACTS: 4220 cbRequest = sizeof(MptIOCFactsRequest); 4221 break; 4222 case MPT_MESSAGE_HDR_FUNCTION_CONFIG: 4223 cbRequest = sizeof(MptConfigurationRequest); 4224 break; 4225 case MPT_MESSAGE_HDR_FUNCTION_PORT_FACTS: 4226 cbRequest = sizeof(MptPortFactsRequest); 4227 break; 4228 case MPT_MESSAGE_HDR_FUNCTION_PORT_ENABLE: 4229 cbRequest = sizeof(MptPortEnableRequest); 4230 break; 4231 case MPT_MESSAGE_HDR_FUNCTION_EVENT_NOTIFICATION: 4232 cbRequest = sizeof(MptEventNotificationRequest); 4233 break; 4234 case MPT_MESSAGE_HDR_FUNCTION_EVENT_ACK: 4235 AssertMsgFailed(("todo\n")); 4236 //cbRequest = sizeof(MptEventAckRequest); 4237 break; 4238 case MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD: 4239 cbRequest = sizeof(MptFWDownloadRequest); 4240 break; 4241 case MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD: 4242 cbRequest = sizeof(MptFWUploadRequest); 4243 break; 4244 default: 4245 AssertMsgFailed(("Unknown function issued %u\n", pLsiReq->GuestRequest.Header.u8Function)); 4246 lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INVALID_FUNCTION); 4247 } 4248 4249 if (cbRequest != 0) 4250 { 4251 /* Read the complete message frame from guest memory now. */ 4252 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, cbRequest); 4253 4254 /* Handle SCSI I/O requests now. */ 4255 if (pLsiReq->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST) 4256 { 4257 rc = lsilogicR3ProcessSCSIIORequest(pThis, pLsiReq); 4258 AssertRC(rc); 4259 } 4260 else 4261 { 4262 MptReplyUnion Reply; 4263 rc = lsilogicR3ProcessMessageRequest(pThis, &pLsiReq->GuestRequest.Header, &Reply); 4264 AssertRC(rc); 4265 RTMemCacheFree(pThis->hTaskCache, pLsiReq); 4266 } 4267 4268 pThis->uRequestQueueNextAddressRead++; 4269 pThis->uRequestQueueNextAddressRead %= pThis->cRequestQueueEntries; 4270 } 4271 } /* While request frames available. */ 4272 } /* While running */ 4273 4274 return VINF_SUCCESS; 4275 } 4276 4277 4278 /** 4279 * Unblock the worker thread so it can respond to a state change. 4280 * 4281 * @returns VBox status code. 4282 * @param pDevIns The pcnet device instance. 4283 * @param pThread The send thread. 4284 */ 4285 static DECLCALLBACK(int) lsilogicR3WorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 4286 { 4287 PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI); 4288 return SUPSemEventSignal(pThis->pSupDrvSession, pThis->hEvtProcess); 4289 } 4290 4225 4291 4226 4292 /** … … 5160 5226 } 5161 5227 5228 if (pThis->hEvtProcess != NIL_SUPSEMEVENT) 5229 { 5230 SUPSemEventClose(pThis->pSupDrvSession, pThis->hEvtProcess); 5231 pThis->hEvtProcess = NIL_SUPSEMEVENT; 5232 } 5233 5162 5234 lsilogicR3ConfigurationPagesFree(pThis); 5163 5235 lsilogicR3MemRegionsFree(pThis); … … 5178 5250 * Initialize enought of the state to make the destructure not trip up. 5179 5251 */ 5180 pThis->hTaskCache = NIL_RTMEMCACHE; 5252 pThis->hTaskCache = NIL_RTMEMCACHE; 5253 pThis->hEvtProcess = NIL_SUPSEMEVENT; 5181 5254 RTListInit(&pThis->ListMemRegns); 5182 5255 … … 5296 5369 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 5297 5370 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 5371 pThis->pSupDrvSession = PDMDevHlpGetSupDrvSession(pDevIns); 5298 5372 pThis->IBase.pfnQueryInterface = lsilogicR3StatusQueryInterface; 5299 5373 pThis->ILeds.pfnQueryStatusLed = lsilogicR3StatusQueryStatusLed; … … 5395 5469 else 5396 5470 AssertMsgFailed(("Invalid controller type: %d\n", pThis->enmCtrlType)); 5471 5472 /* 5473 * Create event semaphore and worker thread. 5474 */ 5475 rc = PDMDevHlpThreadCreate(pDevIns, &pThis->pThreadWrk, pThis, lsilogicR3Worker, 5476 lsilogicR3WorkerWakeUp, 0, RTTHREADTYPE_IO, szDevTag); 5477 if (RT_FAILURE(rc)) 5478 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 5479 N_("LsiLogic: Failed to create worker thread %s"), szDevTag); 5480 5481 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->hEvtProcess); 5482 if (RT_FAILURE(rc)) 5483 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 5484 N_("LsiLogic: Failed to create SUP event semaphore")); 5397 5485 5398 5486 /* -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r46253 r46265 1616 1616 GEN_CHECK_OFF(LSILOGICSCSI, fSignalIdle); 1617 1617 GEN_CHECK_OFF(LSILOGICSCSI, fRedo); 1618 GEN_CHECK_OFF(LSILOGICSCSI, fWrkThreadSleeping); 1618 1619 GEN_CHECK_OFF(LSILOGICSCSI, pTasksRedoHead); 1619 1620 GEN_CHECK_OFF(LSILOGICSCSI, u32DiagMemAddr); 1620 1621 GEN_CHECK_OFF(LSILOGICSCSI, cbMemRegns); 1621 1622 GEN_CHECK_OFF(LSILOGICSCSI, ListMemRegns); 1623 GEN_CHECK_OFF(LSILOGICSCSI, pSupDrvSession); 1624 GEN_CHECK_OFF(LSILOGICSCSI, pThreadWrk); 1625 GEN_CHECK_OFF(LSILOGICSCSI, hEvtProcess); 1622 1626 #endif /* VBOX_WITH_LSILOGIC */ 1623 1627
Note:
See TracChangeset
for help on using the changeset viewer.