Changeset 82167 in vbox for trunk/src/VBox/ExtPacks
- Timestamp:
- Nov 25, 2019 11:53:11 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 134977
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ExtPacks/BusMouseSample/DevBusMouse.cpp
r82155 r82167 35 35 #define LOG_GROUP LOG_GROUP_DEV_KBD 36 36 #include <VBox/vmm/pdmdev.h> 37 #ifndef IN_RING3 38 # include <VBox/vmm/pdmapi.h> 39 #endif 40 #include <VBox/AssertGuest.h> 37 41 #include <VBox/version.h> 38 42 #include <iprt/assert.h> … … 121 125 *********************************************************************************************************************************/ 122 126 /** 123 * The device state.127 * The shared Bus Mouse device state. 124 128 */ 125 129 typedef struct MouState … … 136 140 uint8_t irq; /**< The "jumpered" IRQ level. */ 137 141 int32_t irq_toggle_counter; 138 /** Mouse timer handle - HC. */139 PTMTIMERR3 MouseTimer;140 142 /** Timer period in milliseconds. */ 141 143 uint32_t cTimerPeriodMs; 144 /** Mouse timer handle. */ 145 TMTIMERHANDLE hMouseTimer; 142 146 /** @} */ 143 147 … … 145 149 * @{ */ 146 150 int32_t disable_counter; 147 uint8_t mouse_enabled;148 151 int32_t mouse_dx; /* current values, needed for 'poll' mode */ 149 152 int32_t mouse_dy; 153 uint8_t mouse_enabled; 150 154 uint8_t mouse_buttons; 151 155 uint8_t mouse_buttons_reported; 156 uint8_t bAlignment; 152 157 /** @} */ 153 158 154 /** Pointer to the device instance - RC. */ 155 PPDMDEVINSRC pDevInsRC; 156 /** Pointer to the device instance - R3 . */ 157 PPDMDEVINSR3 pDevInsR3; 158 /** Pointer to the device instance. */ 159 PPDMDEVINSR0 pDevInsR0; 159 /** The I/O ports registration. */ 160 IOMIOPORTHANDLE hIoPorts; 161 162 } MouState, BMSSTATE; 163 /** Pointer to the shared Bus Mouse device state. */ 164 typedef BMSSTATE *PBMSSTATE; 165 166 167 /** 168 * The ring-3 Bus Mouse device state. 169 */ 170 typedef struct BMSSTATER3 171 { 172 /** Pointer to the device instance. 173 * @note Only for getting our bearings in an interface method. */ 174 PPDMDEVINSR3 pDevIns; 160 175 161 176 /** … … 177 192 R3PTRTYPE(PPDMIMOUSECONNECTOR) pDrv; 178 193 } Mouse; 179 } MouState; 180 194 } BMSSTATER3; 195 /** Pointer to the ring-3 Bus Mouse device state. */ 196 typedef BMSSTATER3 *PBMSSTATER3; 181 197 182 198 … … 197 213 * necessary. 198 214 */ 199 static void bms _update_downstream_status(MouState *pThis)200 { 201 PPDMIMOUSECONNECTOR pDrv = pThis ->Mouse.pDrv;215 static void bmsR3UpdateDownstreamStatus(PBMSSTATE pThis, PBMSSTATER3 pThisCC) 216 { 217 PPDMIMOUSECONNECTOR pDrv = pThisCC->Mouse.pDrv; 202 218 bool fEnabled = !!pThis->mouse_enabled; 203 219 pDrv->pfnReportModes(pDrv, fEnabled, false, false); … … 205 221 206 222 /** 207 * Set the emulated hardware to a known initial state. 208 */ 209 static void bms_reset(MouState *pThis) 210 { 211 /* Clear the device setup. */ 212 pThis->port_a = pThis->port_b = 0; 213 pThis->port_c = BMS_CTL_INT_DIS; /* Interrupts disabled. */ 214 pThis->ctrl_port = 0x91; /* Default 8255A setup. */ 215 216 /* Clear motion/button state. */ 217 pThis->cnt_held = false; 218 pThis->mouse_dx = pThis->mouse_dy = 0; 219 pThis->mouse_buttons = 0; 220 pThis->mouse_buttons_reported = 0; 221 pThis->disable_counter = 0; 222 pThis->irq_toggle_counter = 1000; 223 224 if (pThis->mouse_enabled) 225 { 226 pThis->mouse_enabled = false; 227 bms_update_downstream_status(pThis); 228 } 229 } 230 231 /* Process a mouse event coming from the host. */ 232 static void bms_mouse_event(MouState *pThis, int dx, int dy, int dz, int dw, 233 int buttons_state) 223 * Process a mouse event coming from the host. 224 */ 225 static void bmsR3MouseEvent(PBMSSTATE pThis, int dx, int dy, int dz, int dw, int buttons_state) 234 226 { 235 227 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d, buttons_state=0x%x\n", … … 242 234 } 243 235 244 static DECLCALLBACK(void) bmsTimerCallback(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 245 { 246 RT_NOREF(pvUser); 247 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *); 236 /** 237 * @callback_method_impl{FNTMTIMERDEV} 238 */ 239 static DECLCALLBACK(void) bmsR3TimerCallback(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 240 { 241 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 242 PBMSSTATER3 pThisCC = PDMDEVINS_2_DATA(pDevIns, PBMSSTATER3); 248 243 uint8_t irq_bit; 244 RT_NOREF(pvUser, pTimer); 249 245 250 246 /* Toggle the IRQ line if interrupts are enabled. */ … … 254 250 { 255 251 if (!(pThis->port_c & BMS_CTL_INT_DIS)) 256 PDMDevHlpISASetIrq(p This->CTX_SUFF(pDevIns), pThis->irq, PDM_IRQ_LEVEL_LOW);252 PDMDevHlpISASetIrq(pDevIns, pThis->irq, PDM_IRQ_LEVEL_LOW); 257 253 pThis->port_c &= ~irq_bit; 258 254 } … … 261 257 pThis->port_c |= irq_bit; 262 258 if (!(pThis->port_c & BMS_CTL_INT_DIS)) 263 PDMDevHlpISASetIrq(p This->CTX_SUFF(pDevIns), pThis->irq, PDM_IRQ_LEVEL_HIGH);259 PDMDevHlpISASetIrq(pDevIns, pThis->irq, PDM_IRQ_LEVEL_HIGH); 264 260 } 265 261 … … 273 269 { 274 270 pThis->mouse_enabled = false; 275 bms _update_downstream_status(pThis);271 bmsR3UpdateDownstreamStatus(pThis, pThisCC); 276 272 } 277 273 } … … 282 278 { 283 279 pThis->mouse_enabled = true; 284 bms _update_downstream_status(pThis);280 bmsR3UpdateDownstreamStatus(pThis, pThisCC); 285 281 } 286 282 } 287 283 288 284 /* Re-arm the timer. */ 289 TMTimerSetMillies(pTimer, pThis->cTimerPeriodMs);285 PDMDevHlpTimerSetMillies(pDevIns, pThis->hMouseTimer, pThis->cTimerPeriodMs); 290 286 } 291 287 292 288 # endif /* IN_RING3 */ 293 289 294 static void bms _set_reported_buttons(MouState *pThis, unsigned fButtons, unsigned fButtonMask)290 static void bmsSetReportedButtons(PBMSSTATE pThis, unsigned fButtons, unsigned fButtonMask) 295 291 { 296 292 pThis->mouse_buttons_reported |= (fButtons & fButtonMask); … … 298 294 } 299 295 300 /* Update the internal state after a write to port C. */ 301 static void bms_update_ctrl(MouState *pThis) 296 /** 297 * Update the internal state after a write to port C. 298 */ 299 static void bmsUpdateCtrl(PPDMDEVINS pDevIns, PBMSSTATE pThis) 302 300 { 303 301 int32_t dx, dy; … … 315 313 pThis->mouse_dx -= dx; 316 314 pThis->mouse_dy -= dy; 317 bms _set_reported_buttons(pThis, pThis->mouse_buttons & 0x07, 0x07);315 bmsSetReportedButtons(pThis, pThis->mouse_buttons & 0x07, 0x07); 318 316 319 317 /* Force type conversion. */ … … 350 348 if (pThis->port_c & BMS_CTL_INT_DIS) 351 349 { 352 PDMDevHlpISASetIrq(pThis->CTX_SUFF(pDevIns), pThis->irq, PDM_IRQ_LEVEL_LOW); 353 pThis->port_c &= ~(BMS_IRQ_BIT(pThis->irq)); 354 } 355 } 356 357 static int bms_write_port(MouState *pThis, uint32_t offPort, uint32_t uValue) 358 { 359 int rc = VINF_SUCCESS; 360 361 LogRel3(("%s: write port %d: 0x%02x\n", __PRETTY_FUNCTION__, offPort, uValue)); 362 363 switch (offPort) 364 { 365 case BMS_PORT_SIG: 366 /* Update port B. */ 367 pThis->port_b = uValue; 368 break; 369 case BMS_PORT_DATA: 370 /* Do nothing, port A is not writable. */ 371 break; 372 case BMS_PORT_INIT: 373 pThis->ctrl_port = uValue; 374 break; 375 case BMS_PORT_CTRL: 376 /* Update the high nibble of port C. */ 377 pThis->port_c = (uValue & 0xF0) | (pThis->port_c & 0x0F); 378 bms_update_ctrl(pThis); 379 break; 380 default: 381 AssertMsgFailed(("invalid port %#x\n", offPort)); 382 break; 383 } 384 return rc; 385 } 386 387 static uint32_t bms_read_port(MouState *pThis, uint32_t offPort) 388 { 389 uint32_t uValue; 390 391 switch (offPort) 392 { 393 case BMS_PORT_DATA: 394 /* Read port A. */ 395 uValue = pThis->port_a; 396 break; 397 case BMS_PORT_SIG: 398 /* Read port B. */ 399 uValue = pThis->port_b; 400 break; 401 case BMS_PORT_CTRL: 402 /* Read port C. */ 403 uValue = pThis->port_c; 404 /* Some Microsoft driver code reads the control port 10,000 times when 405 * determining the IRQ level. This can occur faster than the IRQ line 406 * transitions and the detection fails. To work around this, we force 407 * the IRQ bit to toggle every once in a while. 408 */ 409 if (pThis->irq_toggle_counter) 410 pThis->irq_toggle_counter--; 411 else 412 { 413 pThis->irq_toggle_counter = 1000; 414 uValue ^= BMS_IRQ_BIT(pThis->irq); 415 } 416 break; 417 case BMS_PORT_INIT: 418 /* Read the 8255A control port. */ 419 uValue = pThis->ctrl_port; 420 break; 421 default: 422 AssertMsgFailed(("invalid port %#x\n", offPort)); 423 uValue = 0xff; 424 break; 425 } 426 LogRel3(("%s: read port %d: 0x%02x\n", __PRETTY_FUNCTION__, offPort, uValue)); 427 return uValue; 428 } 429 430 /** 431 * Port I/O Handler for port IN operations. 432 * 433 * @returns VBox status code. 434 * 435 * @param pDevIns The device instance. 436 * @param pvUser User argument - ignored. 437 * @param Port Port number used for the IN operation. 438 * @param pu32 Where to store the result. 439 * @param cb Number of bytes read. 440 */ 441 PDMBOTHCBDECL(int) mouIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 442 { 443 NOREF(pvUser); 350 PDMDevHlpISASetIrq(pDevIns, pThis->irq, PDM_IRQ_LEVEL_LOW); 351 pThis->port_c &= ~BMS_IRQ_BIT(pThis->irq); 352 } 353 } 354 355 /** 356 * @callback_method_impl{FNIOMIOPORTNEWIN} 357 */ 358 static DECLCALLBACK(VBOXSTRICTRC) bmsIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) 359 { 360 RT_NOREF(pvUser); 444 361 if (cb == 1) 445 362 { 446 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *); 447 *pu32 = bms_read_port(pThis, Port & 3); 448 Log2(("mouIOPortRead: Port=%#x cb=%d *pu32=%#x\n", Port, cb, *pu32)); 363 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 364 uint32_t uValue; 365 366 switch (offPort) 367 { 368 case BMS_PORT_DATA: 369 /* Read port A. */ 370 uValue = pThis->port_a; 371 break; 372 case BMS_PORT_SIG: 373 /* Read port B. */ 374 uValue = pThis->port_b; 375 break; 376 case BMS_PORT_CTRL: 377 /* Read port C. */ 378 uValue = pThis->port_c; 379 /* Some Microsoft driver code reads the control port 10,000 times when 380 * determining the IRQ level. This can occur faster than the IRQ line 381 * transitions and the detection fails. To work around this, we force 382 * the IRQ bit to toggle every once in a while. 383 */ 384 if (pThis->irq_toggle_counter) 385 pThis->irq_toggle_counter--; 386 else 387 { 388 pThis->irq_toggle_counter = 1000; 389 uValue ^= BMS_IRQ_BIT(pThis->irq); 390 } 391 break; 392 case BMS_PORT_INIT: 393 /* Read the 8255A control port. */ 394 uValue = pThis->ctrl_port; 395 break; 396 default: 397 ASSERT_GUEST_MSG_FAILED(("invalid port %#x\n", offPort)); 398 uValue = 0xff; 399 break; 400 } 401 402 *pu32 = uValue; 403 Log2(("mouIoPortRead: offPort=%#x+%x cb=%d *pu32=%#x\n", BMS_IO_BASE, offPort, cb, uValue)); 404 LogRel3(("mouIoPortRead: read port %u: %#04x\n", offPort, uValue)); 449 405 return VINF_SUCCESS; 450 406 } 451 A ssertMsgFailed(("Port=%#x cb=%d\n",Port, cb));407 ASSERT_GUEST_MSG_FAILED(("offPort=%#x cb=%d\n", offPort, cb)); 452 408 return VERR_IOM_IOPORT_UNUSED; 453 409 } 454 410 455 411 /** 456 * Port I/O Handler for port OUT operations. 457 * 458 * @returns VBox status code. 459 * 460 * @param pDevIns The device instance. 461 * @param pvUser User argument - ignored. 462 * @param Port Port number used for the IN operation. 463 * @param u32 The value to output. 464 * @param cb The value size in bytes. 465 */ 466 PDMBOTHCBDECL(int) mouIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 467 { 468 int rc = VINF_SUCCESS; 469 NOREF(pvUser); 412 * @callback_method_impl{FNIOMIOPORTNEWOUT} 413 */ 414 static DECLCALLBACK(VBOXSTRICTRC) bmsIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb) 415 { 416 RT_NOREF(pvUser); 470 417 if (cb == 1) 471 418 { 472 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *); 473 rc = bms_write_port(pThis, Port & 3, u32); 474 Log2(("mouIOPortWrite: Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 419 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 420 LogRel3(("mouIoPortWrite: write port %u: %#04x\n", offPort, u32)); 421 422 switch (offPort) 423 { 424 case BMS_PORT_SIG: 425 /* Update port B. */ 426 pThis->port_b = u32; 427 break; 428 case BMS_PORT_DATA: 429 /* Do nothing, port A is not writable. */ 430 break; 431 case BMS_PORT_INIT: 432 pThis->ctrl_port = u32; 433 break; 434 case BMS_PORT_CTRL: 435 /* Update the high nibble of port C. */ 436 pThis->port_c = (u32 & 0xF0) | (pThis->port_c & 0x0F); 437 bmsUpdateCtrl(pDevIns, pThis); 438 break; 439 default: 440 ASSERT_GUEST_MSG_FAILED(("invalid port %#x\n", offPort)); 441 break; 442 } 443 444 Log2(("mouIoPortWrite: offPort=%#x+%u cb=%d u32=%#x\n", BMS_IO_BASE+offPort, cb, u32)); 475 445 } 476 446 else 477 A ssertMsgFailed(("Port=%#x cb=%d\n",Port, cb));478 return rc;447 ASSERT_GUEST_MSG_FAILED(("offPort=%#x cb=%d\n", offPort, cb)); 448 return VINF_SUCCESS; 479 449 } 480 450 … … 482 452 483 453 /** 484 * Saves the state of the device. 485 * 486 * @returns VBox status code. 487 * @param pDevIns The device instance. 488 * @param pSSMHandle The handle to save the state to. 489 */ 490 static DECLCALLBACK(int) mouSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle) 491 { 492 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *); 454 * @callback_method_impl{FNSSMDEVSAVEEXEC} 455 */ 456 static DECLCALLBACK(int) bmsR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle) 457 { 458 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 459 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 493 460 494 461 /* 8255A state. */ 495 SSMR3PutU8(pSSMHandle, pThis->port_a);496 SSMR3PutU8(pSSMHandle, pThis->port_b);497 SSMR3PutU8(pSSMHandle, pThis->port_c);498 SSMR3PutU8(pSSMHandle, pThis->ctrl_port);462 pHlp->pfnSSMPutU8(pSSMHandle, pThis->port_a); 463 pHlp->pfnSSMPutU8(pSSMHandle, pThis->port_b); 464 pHlp->pfnSSMPutU8(pSSMHandle, pThis->port_c); 465 pHlp->pfnSSMPutU8(pSSMHandle, pThis->ctrl_port); 499 466 /* Other device state. */ 500 SSMR3PutU8(pSSMHandle, pThis->cnt_held);501 SSMR3PutU8(pSSMHandle, pThis->held_dx);502 SSMR3PutU8(pSSMHandle, pThis->held_dy);503 SSMR3PutU8(pSSMHandle, pThis->irq);504 SSMR3PutU32(pSSMHandle, pThis->cTimerPeriodMs);467 pHlp->pfnSSMPutU8(pSSMHandle, pThis->cnt_held); 468 pHlp->pfnSSMPutU8(pSSMHandle, pThis->held_dx); 469 pHlp->pfnSSMPutU8(pSSMHandle, pThis->held_dy); 470 pHlp->pfnSSMPutU8(pSSMHandle, pThis->irq); 471 pHlp->pfnSSMPutU32(pSSMHandle, pThis->cTimerPeriodMs); 505 472 /* Current mouse state deltas. */ 506 SSMR3PutS32(pSSMHandle, pThis->mouse_dx);507 SSMR3PutS32(pSSMHandle, pThis->mouse_dy);508 SSMR3PutU8(pSSMHandle, pThis->mouse_buttons_reported);473 pHlp->pfnSSMPutS32(pSSMHandle, pThis->mouse_dx); 474 pHlp->pfnSSMPutS32(pSSMHandle, pThis->mouse_dy); 475 pHlp->pfnSSMPutU8(pSSMHandle, pThis->mouse_buttons_reported); 509 476 /* Timer. */ 510 return TMR3TimerSave(pThis->MouseTimer, pSSMHandle); 511 } 512 513 /** 514 * Loads a saved device state. 515 * 516 * @returns VBox status code. 517 * @param pDevIns The device instance. 518 * @param pSSMHandle The handle to the saved state. 519 * @param uVersion The data unit version number. 520 * @param uPass The data pass. 521 */ 522 static DECLCALLBACK(int) mouLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t uVersion, uint32_t uPass) 523 { 524 int rc; 525 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *); 477 return PDMDevHlpTimerSave(pDevIns, pThis->hMouseTimer, pSSMHandle); 478 } 479 480 /** 481 * @callback_method_impl{FNSSMDEVLOADEXEC} 482 */ 483 static DECLCALLBACK(int) bmsR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t uVersion, uint32_t uPass) 484 { 485 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 486 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 526 487 527 488 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); … … 531 492 532 493 /* 8255A state. */ 533 SSMR3GetU8(pSSMHandle, &pThis->port_a);534 SSMR3GetU8(pSSMHandle, &pThis->port_b);535 SSMR3GetU8(pSSMHandle, &pThis->port_c);536 SSMR3GetU8(pSSMHandle, &pThis->ctrl_port);494 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->port_a); 495 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->port_b); 496 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->port_c); 497 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->ctrl_port); 537 498 /* Other device state. */ 538 SSMR3GetU8(pSSMHandle, &pThis->cnt_held);539 SSMR3GetU8(pSSMHandle, &pThis->held_dx);540 SSMR3GetU8(pSSMHandle, &pThis->held_dy);541 SSMR3GetU8(pSSMHandle, &pThis->irq);542 SSMR3GetU32(pSSMHandle, &pThis->cTimerPeriodMs);499 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->cnt_held); 500 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->held_dx); 501 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->held_dy); 502 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->irq); 503 pHlp->pfnSSMGetU32(pSSMHandle, &pThis->cTimerPeriodMs); 543 504 /* Current mouse state deltas. */ 544 SSMR3GetS32(pSSMHandle, &pThis->mouse_dx);545 SSMR3GetS32(pSSMHandle, &pThis->mouse_dy);546 SSMR3GetU8(pSSMHandle, &pThis->mouse_buttons_reported);505 pHlp->pfnSSMGetS32(pSSMHandle, &pThis->mouse_dx); 506 pHlp->pfnSSMGetS32(pSSMHandle, &pThis->mouse_dy); 507 pHlp->pfnSSMGetU8(pSSMHandle, &pThis->mouse_buttons_reported); 547 508 /* Timer. */ 548 rc = TMR3TimerLoad(pThis->MouseTimer, pSSMHandle); 549 return rc; 509 return PDMDevHlpTimerLoad(pDevIns, pThis->hMouseTimer, pSSMHandle); 550 510 } 551 511 … … 556 516 * @param pDevIns The device instance data. 557 517 */ 558 static DECLCALLBACK(void) mouReset(PPDMDEVINS pDevIns) 559 { 560 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *); 518 static DECLCALLBACK(void) bmsR3Reset(PPDMDEVINS pDevIns) 519 { 520 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 521 PBMSSTATER3 pThisCC = PDMDEVINS_2_DATA(pDevIns, PBMSSTATER3); 561 522 562 523 /* Reinitialize the timer. */ 563 524 pThis->cTimerPeriodMs = BMS_IRQ_PERIOD_MS / 2; 564 TMTimerSetMillies(pThis->MouseTimer, pThis->cTimerPeriodMs); 565 566 bms_reset(pThis); 525 PDMDevHlpTimerSetMillies(pDevIns, pThis->hMouseTimer, pThis->cTimerPeriodMs); 526 527 /* Clear the device setup. */ 528 pThis->port_a = pThis->port_b = 0; 529 pThis->port_c = BMS_CTL_INT_DIS; /* Interrupts disabled. */ 530 pThis->ctrl_port = 0x91; /* Default 8255A setup. */ 531 532 /* Clear motion/button state. */ 533 pThis->cnt_held = false; 534 pThis->mouse_dx = pThis->mouse_dy = 0; 535 pThis->mouse_buttons = 0; 536 pThis->mouse_buttons_reported = 0; 537 pThis->disable_counter = 0; 538 pThis->irq_toggle_counter = 1000; 539 540 if (pThis->mouse_enabled) 541 { 542 pThis->mouse_enabled = false; 543 bmsR3UpdateDownstreamStatus(pThis, pThisCC); 544 } 567 545 } 568 546 … … 573 551 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 574 552 */ 575 static DECLCALLBACK(void *) mouQueryMouseInterface(PPDMIBASE pInterface, const char *pszIID)576 { 577 MouState *pThis = RT_FROM_MEMBER(pInterface, MouState, Mouse.IBase);578 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis ->Mouse.IBase);579 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSEPORT, &pThis ->Mouse.IPort);553 static DECLCALLBACK(void *) bmsR3Base_QueryMouseInterface(PPDMIBASE pInterface, const char *pszIID) 554 { 555 PBMSSTATER3 pThisCC = RT_FROM_MEMBER(pInterface, BMSSTATER3, Mouse.IBase); 556 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->Mouse.IBase); 557 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSEPORT, &pThisCC->Mouse.IPort); 580 558 return NULL; 581 559 } … … 587 565 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEvent} 588 566 */ 589 static DECLCALLBACK(int) mouPutEvent(PPDMIMOUSEPORT pInterface, int32_t dx, 590 int32_t dy, int32_t dz, int32_t dw, 591 uint32_t fButtons) 592 { 593 MouState *pThis = RT_FROM_MEMBER(pInterface, MouState, Mouse.IPort); 594 int rc = PDMCritSectEnter(pThis->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSectRo), VERR_SEM_BUSY); 567 static DECLCALLBACK(int) bmsR3MousePort_PutEvent(PPDMIMOUSEPORT pInterface, int32_t dx, 568 int32_t dy, int32_t dz, int32_t dw, 569 uint32_t fButtons) 570 { 571 PBMSSTATER3 pThisCC = RT_FROM_MEMBER(pInterface, BMSSTATER3, Mouse.IPort); 572 PPDMDEVINS pDevIns = pThisCC->pDevIns; 573 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 574 int rc = PDMDevHlpCritSectEnter(pDevIns, pDevIns->CTX_SUFF(pCritSectRo), VERR_SEM_BUSY); 595 575 AssertReleaseRC(rc); 596 576 597 bms _mouse_event(pThis, dx, dy, dz, dw, fButtons);598 599 PDM CritSectLeave(pThis->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSectRo));577 bmsR3MouseEvent(pThis, dx, dy, dz, dw, fButtons); 578 579 PDMDevHlpCritSectLeave(pDevIns, pDevIns->CTX_SUFF(pCritSectRo)); 600 580 return VINF_SUCCESS; 601 581 } … … 604 584 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventAbs} 605 585 */ 606 static DECLCALLBACK(int) mouPutEventAbs(PPDMIMOUSEPORT pInterface, uint32_t x, uint32_t y,607 int32_t dz, int32_t dw, uint32_t fButtons)586 static DECLCALLBACK(int) bmsR3MousePort_PutEventAbs(PPDMIMOUSEPORT pInterface, uint32_t x, uint32_t y, 587 int32_t dz, int32_t dw, uint32_t fButtons) 608 588 { 609 589 RT_NOREF(pInterface, x, y, dz, dw, fButtons); … … 614 594 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMultiTouch} 615 595 */ 616 static DECLCALLBACK(int) mouPutEventMultiTouch(PPDMIMOUSEPORT pInterface, uint8_t cContacts,617 const uint64_t *pau64Contacts, uint32_t u32ScanTime)596 static DECLCALLBACK(int) bmsR3MousePort_PutEventMultiTouch(PPDMIMOUSEPORT pInterface, uint8_t cContacts, 597 const uint64_t *pau64Contacts, uint32_t u32ScanTime) 618 598 { 619 599 RT_NOREF(pInterface, cContacts, pau64Contacts, u32ScanTime); … … 625 605 626 606 /** 627 * Attach command. 628 * 629 * This is called to let the device attach to a driver for a specified LUN 630 * during runtime. This is not called during VM construction, the device 631 * constructor have to attach to all the available drivers. 632 * 633 * This is like plugging in the mouse after turning on the PC. 634 * 635 * @returns VBox status code. 636 * @param pDevIns The device instance. 637 * @param iLUN The logical unit which is being detached. 638 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 639 * @remark The controller doesn't support this action, this is just 640 * implemented to try out the driver<->device structure. 641 */ 642 static DECLCALLBACK(int) mouAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 643 { 607 * @interface_method_impl{PDMDEVREGR3,pfnAttach} 608 */ 609 static DECLCALLBACK(int) bmsR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 610 { 611 PBMSSTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PBMSSTATER3); 644 612 int rc; 645 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *);646 613 647 614 AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, … … 653 620 /* LUN #0: mouse */ 654 621 case 0: 655 rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pThis ->Mouse.IBase, &pThis->Mouse.pDrvBase, "Bus Mouse Port");622 rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pThisCC->Mouse.IBase, &pThisCC->Mouse.pDrvBase, "Bus Mouse Port"); 656 623 if (RT_SUCCESS(rc)) 657 624 { 658 pThis ->Mouse.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Mouse.pDrvBase, PDMIMOUSECONNECTOR);659 if (!pThis ->Mouse.pDrv)625 pThisCC->Mouse.pDrv = PDMIBASE_QUERY_INTERFACE(pThisCC->Mouse.pDrvBase, PDMIMOUSECONNECTOR); 626 if (!pThisCC->Mouse.pDrv) 660 627 { 661 628 AssertLogRelMsgFailed(("LUN #0 doesn't have a mouse interface! rc=%Rrc\n", rc)); … … 682 649 683 650 /** 684 * Detach notification. 685 * 686 * This is called when a driver is detaching itself from a LUN of the device. 687 * The device should adjust it's state to reflect this. 688 * 689 * This is like unplugging the network cable to use it for the laptop or 690 * something while the PC is still running. 691 * 692 * @param pDevIns The device instance. 693 * @param iLUN The logical unit which is being detached. 694 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 695 * @remark The controller doesn't support this action, this is just 696 * implemented to try out the driver<->device structure. 697 */ 698 static DECLCALLBACK(void) mouDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 699 { 700 #if 0 651 * @interface_method_impl{PDMDEVREGR3,pfnDetach} 652 */ 653 static DECLCALLBACK(void) bmsR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 654 { 655 # if 0 701 656 /* 702 657 * Reset the interfaces and update the controller state. 703 658 */ 704 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *);659 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 705 660 switch (iLUN) 706 661 { … … 715 670 break; 716 671 } 717 # else672 # else 718 673 RT_NOREF(pDevIns, iLUN, fFlags); 719 #endif 720 } 721 722 723 /** 724 * @copydoc FNPDMDEVRELOCATE 725 */ 726 static DECLCALLBACK(void) mouRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 727 { 728 RT_NOREF(offDelta); 729 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *); 730 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 674 # endif 731 675 } 732 676 … … 735 679 * @interface_method_impl{PDMDEVREG,pfnConstruct} 736 680 */ 737 static DECLCALLBACK(int) mouConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) 738 { 681 static DECLCALLBACK(int) bmsR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) 682 { 683 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 684 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 685 PBMSSTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PBMSSTATER3); 686 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 687 int rc; 739 688 RT_NOREF(iInstance); 740 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 741 MouState *pThis = PDMDEVINS_2_DATA(pDevIns, MouState *); 742 int rc; 743 bool fGCEnabled; 744 bool fR0Enabled; 745 uint8_t irq_lvl; 689 746 690 Assert(iInstance == 0); 747 748 691 749 692 /* 750 693 * Validate and read the configuration. 751 694 */ 752 if (!CFGMR3AreValuesValid(pCfg, "IRQ\0GCEnabled\0R0Enabled\0")) 753 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES; 754 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true); 755 if (RT_FAILURE(rc)) 756 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to query \"GCEnabled\" from the config")); 757 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true); 758 if (RT_FAILURE(rc)) 759 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to query \"R0Enabled\" from the config")); 760 rc = CFGMR3QueryU8Def(pCfg, "IRQ", &irq_lvl, BMS_DEFAULT_IRQ); 695 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IRQ", ""); 696 697 rc = pHlp->pfnCFGMQueryU8Def(pCfg, "IRQ", &pThis->irq, BMS_DEFAULT_IRQ); 761 698 if (RT_FAILURE(rc)) 762 699 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to query \"IRQ\" from the config")); 763 if ( (irq_lvl < 2) || (irq_lvl > 5))700 if (pThis->irq < 2 || pThis->irq > 5) 764 701 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Invalid \"IRQ\" config setting")); 765 702 766 pThis->irq = irq_lvl; 767 /// @todo remove after properly enabling RC/GC support 768 fGCEnabled = fR0Enabled = false; 769 Log(("busmouse: IRQ=%d fGCEnabled=%RTbool fR0Enabled=%RTbool\n", irq_lvl, fGCEnabled, fR0Enabled)); 703 Log(("busmouse: IRQ=%u fRCEnabled=%RTbool fR0Enabled=%RTbool\n", pThis->irq, pDevIns->fRCEnabled, pDevIns->fR0Enabled)); 770 704 771 705 /* 772 706 * Initialize the interfaces. 773 707 */ 774 pThis->pDevInsR3 = pDevIns; 775 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 776 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 777 pThis->Mouse.IBase.pfnQueryInterface = mouQueryMouseInterface; 778 pThis->Mouse.IPort.pfnPutEvent = mouPutEvent; 779 pThis->Mouse.IPort.pfnPutEventAbs = mouPutEventAbs; 780 pThis->Mouse.IPort.pfnPutEventMultiTouch = mouPutEventMultiTouch; 708 pThisCC->pDevIns = pDevIns; 709 pThisCC->Mouse.IBase.pfnQueryInterface = bmsR3Base_QueryMouseInterface; 710 pThisCC->Mouse.IPort.pfnPutEvent = bmsR3MousePort_PutEvent; 711 pThisCC->Mouse.IPort.pfnPutEventAbs = bmsR3MousePort_PutEventAbs; 712 pThisCC->Mouse.IPort.pfnPutEventMultiTouch = bmsR3MousePort_PutEventMultiTouch; 781 713 782 714 /* 783 715 * Create the interrupt timer. 784 716 */ 785 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, bmsTimerCallback, 786 pThis, TMTIMER_FLAGS_DEFAULT_CRIT_SECT, 787 "Bus Mouse Timer", &pThis->MouseTimer); 788 if (RT_FAILURE(rc)) 789 return rc; 717 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL, bmsR3TimerCallback, pThis, 718 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "Bus Mouse Timer", &pThis->hMouseTimer); 719 AssertRCReturn(rc, rc); 790 720 791 721 /* 792 * Register I/O ports , saved state, and mouse event handlers.722 * Register I/O ports. 793 723 */ 794 rc = PDMDevHlpIOPortRegister(pDevIns, BMS_IO_BASE, BMS_IO_SIZE, NULL, mouIOPortWrite, mouIOPortRead, NULL, NULL, "Bus Mouse"); 795 if (RT_FAILURE(rc)) 796 return rc; 797 if (fGCEnabled) 798 { 799 rc = PDMDevHlpIOPortRegisterRC(pDevIns, BMS_IO_BASE, BMS_IO_SIZE, 0, "mouIOPortWrite", "mouIOPortRead", NULL, NULL, "Bus Mouse"); 800 if (RT_FAILURE(rc)) 801 return rc; 802 } 803 if (fR0Enabled) 804 { 805 rc = PDMDevHlpIOPortRegisterR0(pDevIns, BMS_IO_BASE, BMS_IO_SIZE, 0, "mouIOPortWrite", "mouIOPortRead", NULL, NULL, "Bus Mouse"); 806 if (RT_FAILURE(rc)) 807 return rc; 808 } 809 rc = PDMDevHlpSSMRegister(pDevIns, BMS_SAVED_STATE_VERSION, sizeof(*pThis), mouSaveExec, mouLoadExec); 810 if (RT_FAILURE(rc)) 811 return rc; 724 static const IOMIOPORTDESC s_aDescs[] = 725 { 726 { "DATA", "DATA", NULL, NULL }, 727 { "SIG", "SIG", NULL, NULL }, 728 { "CTRL", "CTRL", NULL, NULL }, 729 { "INIT", "INIT", NULL, NULL }, 730 { NULL, NULL, NULL, NULL } 731 }; 732 rc = PDMDevHlpIoPortCreateAndMap(pDevIns, BMS_IO_BASE, BMS_IO_SIZE, bmsIoPortWrite, bmsIoPortRead, 733 "Bus Mouse", s_aDescs, &pThis->hIoPorts); 734 AssertRCReturn(rc, rc); 735 736 /* 737 * Register saved state. 738 */ 739 rc = PDMDevHlpSSMRegister(pDevIns, BMS_SAVED_STATE_VERSION, sizeof(*pThis), bmsR3SaveExec, bmsR3LoadExec); 740 AssertRCReturn(rc, rc); 812 741 813 742 /* 814 743 * Attach to the mouse driver. 815 744 */ 816 rc = mouAttach(pDevIns, 0, PDM_TACH_FLAGS_NOT_HOT_PLUG); 817 if (RT_FAILURE(rc)) 818 return rc; 745 rc = bmsR3Attach(pDevIns, 0, PDM_TACH_FLAGS_NOT_HOT_PLUG); 746 AssertRCReturn(rc, rc); 819 747 820 748 /* 821 749 * Initialize the device state. 822 750 */ 823 mouReset(pDevIns);751 bmsR3Reset(pDevIns); 824 752 825 753 return VINF_SUCCESS; 826 754 } 827 755 828 # endif /* IN_RING3 */ 756 # else /* !IN_RING3 */ 757 758 /** 759 * @callback_method_impl{PDMDEVREGR0,pfnConstruct} 760 */ 761 static DECLCALLBACK(int) bmsRZConstruct(PPDMDEVINS pDevIns) 762 { 763 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 764 PBMSSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PBMSSTATE); 765 766 int rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPorts, bmsIoPortWrite, bmsIoPortRead, NULL /*pvUser*/); 767 AssertRCReturn(rc, rc); 768 769 return VINF_SUCCESS; 770 } 771 772 # endif /* !IN_RING3 */ 829 773 830 774 … … 832 776 * The device registration structure. 833 777 */ 834 const PDMDEVREG g_DeviceBusMouse =778 static const PDMDEVREG g_DeviceBusMouse = 835 779 { 836 780 /* .u32Version = */ PDM_DEVREG_VERSION, 837 781 /* .uReserved0 = */ 0, 838 782 /* .szName = */ "busmouse", 839 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ,783 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS /** @todo | PDM_DEVREG_FLAGS_RZ */ | PDM_DEVREG_FLAGS_NEW_STYLE, 840 784 /* .fClass = */ PDM_DEVREG_CLASS_INPUT, 841 785 /* .cMaxInstances = */ 1, 842 786 /* .uSharedVersion = */ 42, 843 /* .cbInstanceShared = */ sizeof( MouState),844 /* .cbInstanceCC = */ 0,787 /* .cbInstanceShared = */ sizeof(BMSSTATE), 788 /* .cbInstanceCC = */ CTX_EXPR(sizeof(BMSSTATER3), 0, 0), 845 789 /* .cbInstanceRC = */ 0, 846 790 /* .cMaxPciDevices = */ 0, … … 850 794 /* .pszRCMod = */ "VBoxDDRC.rc", 851 795 /* .pszR0Mod = */ "VBoxDDR0.r0", 852 /* .pfnConstruct = */ mouConstruct,796 /* .pfnConstruct = */ bmsR3Construct, 853 797 /* .pfnDestruct = */ NULL, 854 /* .pfnRelocate = */ mouRelocate,798 /* .pfnRelocate = */ NULL, 855 799 /* .pfnMemSetup = */ NULL, 856 800 /* .pfnPowerOn = */ NULL, 857 /* .pfnReset = */ mouReset,801 /* .pfnReset = */ bmsR3Reset, 858 802 /* .pfnSuspend = */ NULL, 859 803 /* .pfnResume = */ NULL, 860 /* .pfnAttach = */ mouAttach,861 /* .pfnDetach = */ mouDetach,804 /* .pfnAttach = */ bmsR3Attach, 805 /* .pfnDetach = */ bmsR3Detach, 862 806 /* .pfnQueryInterface = */ NULL, 863 807 /* .pfnInitComplete = */ NULL, … … 902 846 }; 903 847 904 #if defined(VBOX_IN_EXTPACK_R3) && defined(IN_RING3) 848 # ifdef VBOX_IN_EXTPACK_R3 849 905 850 /** 906 851 * @callback_method_impl{FNPDMVBOXDEVICESREGISTER} … … 917 862 return pCallbacks->pfnRegister(pCallbacks, &g_DeviceBusMouse); 918 863 } 919 #endif 864 865 # else /* !VBOX_IN_EXTPACK_R3 */ 866 867 /** Pointer to the ring-0 device registrations for the Bus Mouse. */ 868 static PCPDMDEVREGR0 g_apDevRegs[] = 869 { 870 &g_DeviceBusMouse, 871 }; 872 873 /** Module device registration record for the Bus Mouse. */ 874 static PDMDEVMODREGR0 g_ModDevReg = 875 { 876 /* .u32Version = */ PDM_DEVMODREGR0_VERSION, 877 /* .cDevRegs = */ RT_ELEMENTS(g_apDevRegs), 878 /* .papDevRegs = */ &g_apDevRegs[0], 879 /* .hMod = */ NULL, 880 /* .ListEntry = */ { NULL, NULL }, 881 }; 882 883 DECLEXPORT(int) ModuleInit(void *hMod) 884 { 885 LogFlow(("VBoxBusMouseRZ/ModuleInit: %p\n", hMod)); 886 return PDMR0DeviceRegisterModule(hMod, &g_ModDevReg); 887 } 888 889 DECLEXPORT(void) ModuleTerm(void *hMod) 890 { 891 LogFlow(("VBoxBusMouseRZ/ModuleTerm: %p\n", hMod)); 892 PDMR0DeviceDeregisterModule(hMod, &g_ModDevReg); 893 } 894 895 # endif /* !VBOX_IN_EXTPACK_R3 */ 920 896 921 897 #endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
Note:
See TracChangeset
for help on using the changeset viewer.