Changeset 50831 in vbox for trunk/src/VBox/Devices/Graphics
- Timestamp:
- Mar 20, 2014 5:40:50 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
r50812 r50831 22 22 #include <iprt/asm.h> 23 23 #include <iprt/list.h> 24 #include <iprt/param.h> 24 25 25 26 #include "DevVGA.h" … … 1157 1158 } 1158 1159 1159 1160 /* 1161 * @returns 1162 * 1160 /** 1161 * @param fIn - whether this is a page in or out op. 1162 * the direction is VRA#M - related, so fIn == true - transfer to VRAM); false - transfer from VRAM 1163 1163 */ 1164 static int vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd) 1164 static int vboxVDMACrCmdVbvaProcessPagingEl(PPDMDEVINS pDevIns, const VBOXCMDVBVA_SYSMEMEL *pMemEl, uint8_t *pu8Vram, uint8_t *pu8VramMax, uint8_t **ppu8VramNext, bool fIn) 1165 { 1166 uint32_t u32Cpages = pMemEl->cPagesAfterFirst + 1; 1167 RTGCPHYS phPage = (pMemEl->iPage1 | (pMemEl->iPage2 << 20)); 1168 PGMPAGEMAPLOCK Lock; 1169 uint32_t cbCopy = u32Cpages * PAGE_SIZE; 1170 uint8_t* pu8VramNext = pu8Vram + cbCopy; 1171 1172 if (pu8VramNext <= pu8Vram && pu8VramNext > pu8VramMax) 1173 { 1174 WARN(("invalid copy size")); 1175 return VERR_INVALID_PARAMETER; 1176 } 1177 1178 int rc; 1179 if (fIn) 1180 { 1181 for (uint32_t i = 0; i < u32Cpages; ++i) 1182 { 1183 const void * pvPage; 1184 rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvPage, &Lock); 1185 if (!RT_SUCCESS(rc)) 1186 { 1187 WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d", rc)); 1188 return rc; 1189 } 1190 1191 memcpy(pu8Vram, pvPage, PAGE_SIZE); 1192 1193 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock); 1194 1195 pu8Vram += PAGE_SIZE; 1196 } 1197 } 1198 else 1199 { 1200 for (uint32_t i = 0; i < u32Cpages; ++i) 1201 { 1202 void * pvPage; 1203 rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, phPage, 0, &pvPage, &Lock); 1204 if (!RT_SUCCESS(rc)) 1205 { 1206 WARN(("PDMDevHlpPhysGCPhys2CCPtr failed %d", rc)); 1207 return rc; 1208 } 1209 1210 memcpy(pvPage, pu8Vram, PAGE_SIZE); 1211 1212 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock); 1213 1214 pu8Vram += PAGE_SIZE; 1215 } 1216 } 1217 1218 if (ppu8VramNext) 1219 *ppu8VramNext = pu8VramNext; 1220 1221 return VINF_SUCCESS; 1222 } 1223 1224 static int vboxVDMACrCmdVbvaProcessPagingEls(PPDMDEVINS pDevIns, const VBOXCMDVBVA_SYSMEMEL *pMemEl, uint32_t cMemEls, uint8_t *pu8Vram, uint8_t *pu8VramMax, uint8_t **ppu8VramNext, bool fIn) 1225 { 1226 uint8_t *pu8VramNext = pu8Vram; 1227 for (uint32_t i = 0; i < cMemEls; ++i, ++pMemEl) 1228 { 1229 int rc = vboxVDMACrCmdVbvaProcessPagingEl(pDevIns, pMemEl, pu8Vram, pu8VramMax, &pu8VramNext, fIn); 1230 if (!RT_SUCCESS(rc)) 1231 { 1232 WARN(("vboxVDMACrCmdVbvaProcessPagingEl failed %d", rc)); 1233 return rc; 1234 } 1235 } 1236 1237 if (ppu8VramNext) 1238 *ppu8VramNext = pu8VramNext; 1239 1240 return VINF_SUCCESS; 1241 } 1242 1243 static int8_t vboxVDMACrCmdVbvaPagingDataInit(PVGASTATE pVGAState, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd, 1244 const VBOXCMDVBVA_SYSMEMEL **ppSysMem, uint32_t *pcSysMem, 1245 uint8_t **ppu8Vram, uint8_t **ppu8VramMax, bool *pfIn) 1246 { 1247 if (cbCmd < sizeof (VBOXCMDVBVA_PAGING_TRANSFER)) 1248 { 1249 WARN(("cmd too small")); 1250 return -1; 1251 } 1252 1253 uint32_t cSysMem = cbCmd - RT_OFFSETOF(VBOXCMDVBVA_PAGING_TRANSFER, aSysMem); 1254 if (cSysMem % sizeof (VBOXCMDVBVA_SYSMEMEL)) 1255 { 1256 WARN(("invalid cmd size")); 1257 return -1; 1258 } 1259 cSysMem /= sizeof (VBOXCMDVBVA_SYSMEMEL); 1260 1261 VBOXCMDVBVA_PAGING_TRANSFER *pTransfer = (VBOXCMDVBVA_PAGING_TRANSFER*)pCmd; 1262 VBOXCMDVBVAOFFSET offVRAM = pTransfer->Alloc.u.offVRAM; 1263 if (offVRAM & PAGE_OFFSET_MASK) 1264 { 1265 WARN(("offVRAM address is not on page boundary\n")); 1266 return -1; 1267 } 1268 const VBOXCMDVBVA_SYSMEMEL *pSysMem = pTransfer->aSysMem; 1269 1270 uint8_t * pu8VramBase = pVGAState->vram_ptrR3; 1271 uint8_t *pu8VramMax = pu8VramBase + pVGAState->vram_size; 1272 if (pTransfer->Alloc.u.offVRAM >= pVGAState->vram_size) 1273 { 1274 WARN(("invalid vram offset")); 1275 return -1; 1276 } 1277 1278 uint8_t *pu8Vram = pu8VramBase + pTransfer->Alloc.u.offVRAM; 1279 bool fIn = (pTransfer->Hdr.u8Flags & VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN); 1280 1281 *ppSysMem = pSysMem; 1282 *pcSysMem = cSysMem; 1283 *ppu8Vram = pu8Vram; 1284 *ppu8VramMax = pu8VramMax; 1285 *pfIn = fIn; 1286 return 0; 1287 } 1288 1289 static int8_t vboxVDMACrCmdVbvaProcessCmdData(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd) 1290 { 1291 switch (pCmd->u8OpCode) 1292 { 1293 case VBOXCMDVBVA_OPTYPE_NOPCMD: 1294 return 0; 1295 case VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER: 1296 { 1297 PVGASTATE pVGAState = pVdma->pVGAState; 1298 const VBOXCMDVBVA_SYSMEMEL *pSysMem; 1299 uint32_t cSysMem; 1300 uint8_t *pu8Vram; 1301 uint8_t *pu8VramMax; 1302 bool fIn; 1303 int8_t i8Result = vboxVDMACrCmdVbvaPagingDataInit(pVGAState, pCmd, cbCmd, 1304 &pSysMem, &cSysMem, 1305 &pu8Vram, &pu8VramMax, &fIn); 1306 if (i8Result < 0) 1307 { 1308 WARN(("vboxVDMACrCmdVbvaPagingDataInit failed %d", i8Result)); 1309 return i8Result; 1310 } 1311 1312 PPDMDEVINS pDevIns = pVGAState->pDevInsR3; 1313 int rc = vboxVDMACrCmdVbvaProcessPagingEls(pDevIns, pSysMem, cSysMem, pu8Vram, pu8VramMax, &pu8Vram, fIn); 1314 if (!RT_SUCCESS(rc)) 1315 { 1316 WARN(("vboxVDMACrCmdVbvaProcessPagingEls failed %d", rc)); 1317 return -1; 1318 } 1319 1320 return 0; 1321 } 1322 case VBOXCMDVBVA_OPTYPE_PAGING_FILL: 1323 WARN(("VBOXCMDVBVA_OPTYPE_PAGING_FILL not implemented")); 1324 return -1; 1325 default: 1326 return pVdma->CrSrvInfo.pfnCmd(pVdma->CrSrvInfo.hSvr, pCmd, cbCmd); 1327 } 1328 } 1329 1330 #if 0 1331 typedef struct VBOXCMDVBVA_PAGING_TRANSFER 1332 { 1333 VBOXCMDVBVA_HDR Hdr; 1334 /* for now can only contain offVRAM. 1335 * paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */ 1336 VBOXCMDVBVA_ALLOCINFO Alloc; 1337 uint32_t u32Reserved; 1338 VBOXCMDVBVA_SYSMEMEL aSysMem[1]; 1339 } VBOXCMDVBVA_PAGING_TRANSFER; 1340 #endif 1341 1342 AssertCompile(sizeof (VBOXCMDVBVA_HDR) == 8); 1343 AssertCompile(sizeof (VBOXCMDVBVA_ALLOCINFO) == 4); 1344 AssertCompile(sizeof (VBOXCMDVBVA_SYSMEMEL) == 8); 1345 AssertCompile(!(PAGE_SIZE % sizeof (VBOXCMDVBVA_SYSMEMEL))); 1346 AssertCompile(!(sizeof (VBOXCMDVBVA_PAGING_TRANSFER) % 8)); 1347 1348 #define VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE (PAGE_SIZE / sizeof (VBOXCMDVBVA_SYSMEMEL)) 1349 1350 static int8_t vboxVDMACrCmdVbvaProcess(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd) 1351 { 1352 switch (pCmd->u8OpCode) 1353 { 1354 case VBOXCMDVBVA_OPTYPE_SYSMEMCMD: 1355 { 1356 VBOXCMDVBVA_SYSMEMCMD *pSysmemCmd = (VBOXCMDVBVA_SYSMEMCMD*)pCmd; 1357 const VBOXCMDVBVA_HDR *pRealCmd; 1358 uint32_t cbRealCmd = pCmd->u8Flags; 1359 cbRealCmd |= (pCmd->u.u8PrimaryID << 8); 1360 if (cbRealCmd < sizeof (VBOXCMDVBVA_HDR)) 1361 { 1362 WARN(("invalid sysmem cmd size")); 1363 return -1; 1364 } 1365 1366 RTGCPHYS phPage = pSysmemCmd->phSysMem; 1367 if (phPage & PAGE_OFFSET_MASK) 1368 { 1369 WARN(("cmd address is not on page boundary\n")); 1370 return -1; 1371 } 1372 1373 PGMPAGEMAPLOCK Lock; 1374 PVGASTATE pVGAState = pVdma->pVGAState; 1375 PPDMDEVINS pDevIns = pVGAState->pDevInsR3; 1376 const void * pvCmd; 1377 int rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvCmd, &Lock); 1378 if (!RT_SUCCESS(rc)) 1379 { 1380 WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc)); 1381 return -1; 1382 } 1383 1384 pRealCmd = (const VBOXCMDVBVA_HDR *)pvCmd; 1385 1386 if (cbRealCmd <= PAGE_SIZE) 1387 { 1388 uint8_t i8Result = vboxVDMACrCmdVbvaProcessCmdData(pVdma, pRealCmd, cbRealCmd); 1389 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock); 1390 return i8Result; 1391 } 1392 1393 int8_t i8Result = 0; 1394 1395 switch (pRealCmd->u8OpCode) 1396 { 1397 case VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER: 1398 { 1399 const VBOXCMDVBVA_SYSMEMEL *pSysMem; 1400 uint32_t cSysMem; 1401 uint8_t *pu8Vram; 1402 uint8_t *pu8VramMax; 1403 bool fIn; 1404 i8Result = vboxVDMACrCmdVbvaPagingDataInit(pVGAState, pCmd, cbCmd, 1405 &pSysMem, &cSysMem, 1406 &pu8Vram, &pu8VramMax, &fIn); 1407 if (i8Result < 0) 1408 { 1409 WARN(("vboxVDMACrCmdVbvaPagingDataInit failed %d", i8Result)); 1410 return i8Result; 1411 } 1412 1413 uint32_t cCurSysMem = PAGE_SIZE - RT_OFFSETOF(VBOXCMDVBVA_PAGING_TRANSFER, aSysMem); 1414 cCurSysMem /= sizeof (VBOXCMDVBVA_SYSMEMEL); 1415 Assert(cCurSysMem < cSysMem); 1416 1417 do 1418 { 1419 rc = vboxVDMACrCmdVbvaProcessPagingEls(pDevIns, pSysMem, cCurSysMem, pu8Vram, pu8VramMax, &pu8Vram, fIn); 1420 if (!RT_SUCCESS(rc)) 1421 { 1422 WARN(("vboxVDMACrCmdVbvaProcessPagingEls failed %d", rc)); 1423 i8Result = -1; 1424 break; 1425 } 1426 1427 Assert(cSysMem >= cCurSysMem); 1428 cSysMem -= cCurSysMem; 1429 1430 if (!cSysMem) 1431 break; 1432 1433 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock); 1434 1435 phPage += PAGE_SIZE; 1436 1437 rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvCmd, &Lock); 1438 if (!RT_SUCCESS(rc)) 1439 { 1440 WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc)); 1441 return -1; 1442 } 1443 1444 if (cSysMem > VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE) 1445 cCurSysMem = VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE; 1446 else 1447 cCurSysMem = cSysMem; 1448 } while (1); 1449 break; 1450 } 1451 default: 1452 WARN(("command can not be splitted")); 1453 i8Result = -1; 1454 break; 1455 } 1456 1457 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock); 1458 return i8Result; 1459 } 1460 default: 1461 return vboxVDMACrCmdVbvaProcessCmdData(pVdma, pCmd, cbCmd); 1462 } 1463 } 1464 1465 static void vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd) 1165 1466 { 1166 1467 if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP) 1167 return VINF_EOF; 1468 return; 1469 1470 if (cbCmd < sizeof (VBOXCMDVBVA_HDR)) 1471 { 1472 WARN(("invalid command size")); 1473 return; 1474 } 1168 1475 1169 1476 PVBOXCMDVBVA_HDR pCmd = (PVBOXCMDVBVA_HDR)pu8Cmd; … … 1173 1480 { 1174 1481 Assert(pCmd->u8State == VBOXCMDVBVA_STATE_CANCELLED); 1175 return VINF_EOF; 1176 } 1177 1178 /* come commands can be handled right away? */ 1179 switch (pCmd->u8OpCode) 1180 { 1181 case VBOXCMDVBVA_OPTYPE_NOPCMD: 1182 pCmd->u.i8Result = 0; 1183 return VINF_EOF; 1184 default: 1185 return VINF_SUCCESS; 1186 } 1187 } 1188 1189 static DECLCALLBACK(int) vboxVDMACrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo) 1190 { 1191 return VINF_SUCCESS; 1192 } 1193 1194 static DECLCALLBACK(void) vboxVDMACrCmdDisable(HVBOXCRCMDSVR hSvr) 1195 { 1196 } 1197 1198 static DECLCALLBACK(int) vboxVDMACrCmdCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd) 1199 { 1200 return VERR_NOT_SUPPORTED; 1201 } 1202 1203 static DECLCALLBACK(int) vboxVDMACrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) 1204 { 1205 switch (pCmd->u8OpCode) 1206 { 1207 #if 0 1208 case VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID: 1209 { 1210 crVBoxServerCrCmdBltProcess(pCmd, cbCmd); 1211 break; 1212 } 1213 #endif 1214 default: 1215 WARN(("unsupported command\n")); 1216 pCmd->u.i8Result = -1; 1217 } 1218 return VINF_SUCCESS; 1482 return; 1483 } 1484 1485 pCmd->u.i8Result = vboxVDMACrCmdVbvaProcess(pVdma, pCmd, cbCmd); 1219 1486 } 1220 1487
Note:
See TracChangeset
for help on using the changeset viewer.