32#include "dev/x86/i8042.hh" 33#include "mem/packet.hh" 34#include "mem/packet_access.hh" 35 36// The 8042 has a whopping 32 bytes of internal RAM. 37const uint8_t RamSize = 32; 38const uint8_t NumOutputBits = 14; 39const uint8_t X86ISA::PS2Keyboard::ID[] = {0xab, 0x83}; 40const uint8_t X86ISA::PS2Mouse::ID[] = {0x00}; 41const uint8_t CommandAck = 0xfa; 42const uint8_t CommandNack = 0xfe; 43const uint8_t BatSuccessful = 0xaa; 44 45void 46X86ISA::I8042::addressRanges(AddrRangeList &range_list) 47{ 48 range_list.clear(); 49 range_list.push_back(RangeSize(dataPort, 1)); 50 range_list.push_back(RangeSize(commandPort, 1)); 51} 52 53void 54X86ISA::I8042::writeData(uint8_t newData, bool mouse) 55{ 56 DPRINTF(I8042, "Set data %#02x.\n", newData); 57 dataReg = newData; 58 statusReg.outputFull = 1; 59 statusReg.mouseOutputFull = (mouse ? 1 : 0); 60 if (!mouse && commandByte.keyboardFullInt) { 61 DPRINTF(I8042, "Sending keyboard interrupt.\n"); 62 keyboardIntPin->raise(); 63 //This is a hack 64 keyboardIntPin->lower(); 65 } else if (mouse && commandByte.mouseFullInt) { 66 DPRINTF(I8042, "Sending mouse interrupt.\n"); 67 mouseIntPin->raise(); 68 //This is a hack 69 mouseIntPin->lower(); 70 } 71} 72 73void 74X86ISA::PS2Device::ack() 75{ 76 bufferData(&CommandAck, sizeof(CommandAck)); 77} 78 79void 80X86ISA::PS2Device::nack() 81{ 82 bufferData(&CommandNack, sizeof(CommandNack)); 83} 84 85void 86X86ISA::PS2Device::bufferData(const uint8_t *data, int size) 87{ 88 assert(data || size == 0); 89 while (size) { 90 outBuffer.push(*(data++)); 91 size--; 92 } 93} 94 95uint8_t 96X86ISA::I8042::readDataOut() 97{ 98 uint8_t data = dataReg; 99 statusReg.outputFull = 0; 100 statusReg.mouseOutputFull = 0; 101 if (keyboard.hasData()) { 102 writeData(keyboard.getData(), false); 103 } else if (mouse.hasData()) { 104 writeData(mouse.getData(), true); 105 } 106 return data; 107} 108 109bool 110X86ISA::PS2Keyboard::processData(uint8_t data) 111{ 112 if (lastCommand != NoCommand) { 113 switch (lastCommand) { 114 case LEDWrite: 115 DPRINTF(I8042, "Setting LEDs: " 116 "caps lock %s, num lock %s, scroll lock %s\n", 117 bits(data, 2) ? "on" : "off", 118 bits(data, 1) ? "on" : "off", 119 bits(data, 0) ? "on" : "off"); 120 ack(); 121 lastCommand = NoCommand; 122 break; 123 case TypematicInfo: 124 DPRINTF(I8042, "Setting typematic info to %#02x.\n", data); 125 ack(); 126 lastCommand = NoCommand; 127 break; 128 } 129 return hasData(); 130 } 131 switch (data) { 132 case LEDWrite: 133 DPRINTF(I8042, "Got LED write command.\n"); 134 ack(); 135 lastCommand = LEDWrite; 136 break; 137 case DiagnosticEcho: 138 panic("Keyboard diagnostic echo unimplemented.\n"); 139 case AlternateScanCodes: 140 panic("Accessing alternate scan codes unimplemented.\n"); 141 case ReadID: 142 DPRINTF(I8042, "Got keyboard read ID command.\n"); 143 ack(); 144 bufferData((uint8_t *)&ID, sizeof(ID)); 145 break; 146 case TypematicInfo: 147 DPRINTF(I8042, "Setting typematic info.\n"); 148 ack(); 149 lastCommand = TypematicInfo; 150 break; 151 case Enable: 152 DPRINTF(I8042, "Enabling the keyboard.\n"); 153 ack(); 154 break; 155 case Disable: 156 DPRINTF(I8042, "Disabling the keyboard.\n"); 157 ack(); 158 break; 159 case DefaultsAndDisable: 160 DPRINTF(I8042, "Disabling and resetting the keyboard.\n"); 161 ack(); 162 break; 163 case AllKeysToTypematic: 164 panic("Setting all keys to typemantic unimplemented.\n"); 165 case AllKeysToMakeRelease: 166 panic("Setting all keys to make/release unimplemented.\n"); 167 case AllKeysToMake: 168 panic("Setting all keys to make unimplemented.\n"); 169 case AllKeysToTypematicMakeRelease: 170 panic("Setting all keys to " 171 "typematic/make/release unimplemented.\n"); 172 case KeyToTypematic: 173 panic("Setting a key to typematic unimplemented.\n"); 174 case KeyToMakeRelease: 175 panic("Setting a key to make/release unimplemented.\n"); 176 case KeyToMakeOnly: 177 panic("Setting key to make only unimplemented.\n"); 178 case Resend: 179 panic("Keyboard resend unimplemented.\n"); 180 case Reset: 181 panic("Keyboard reset unimplemented.\n"); 182 default: 183 panic("Unknown keyboard command %#02x.\n", data); 184 } 185 return hasData(); 186} 187 188bool 189X86ISA::PS2Mouse::processData(uint8_t data) 190{ 191 if (lastCommand != NoCommand) { 192 switch(lastCommand) { 193 case SetResolution: 194 DPRINTF(I8042, "Mouse resolution set to %d.\n", data); 195 resolution = data; 196 ack(); 197 lastCommand = NoCommand; 198 break; 199 case SampleRate: 200 DPRINTF(I8042, "Mouse sample rate %d samples " 201 "per second.\n", data); 202 sampleRate = data; 203 ack(); 204 lastCommand = NoCommand; 205 break; 206 default: 207 panic("Not expecting data for a mouse command.\n"); 208 } 209 return hasData(); 210 } 211 switch (data) { 212 case Scale1to1: 213 DPRINTF(I8042, "Setting mouse scale to 1:1.\n"); 214 status.twoToOne = 0; 215 ack(); 216 break; 217 case Scale2to1: 218 DPRINTF(I8042, "Setting mouse scale to 2:1.\n"); 219 status.twoToOne = 1; 220 ack(); 221 break; 222 case SetResolution: 223 DPRINTF(I8042, "Setting mouse resolution.\n"); 224 lastCommand = SetResolution; 225 ack(); 226 break; 227 case GetStatus: 228 DPRINTF(I8042, "Getting mouse status.\n"); 229 ack(); 230 bufferData((uint8_t *)&(status), 1); 231 bufferData(&resolution, sizeof(resolution)); 232 bufferData(&sampleRate, sizeof(sampleRate)); 233 break; 234 case ReadData: 235 panic("Reading mouse data unimplemented.\n"); 236 case ResetWrapMode: 237 panic("Resetting mouse wrap mode unimplemented.\n"); 238 case WrapMode: 239 panic("Setting mouse wrap mode unimplemented.\n"); 240 case RemoteMode: 241 panic("Setting mouse remote mode unimplemented.\n"); 242 case ReadID: 243 DPRINTF(I8042, "Mouse ID requested.\n"); 244 ack(); 245 bufferData(ID, sizeof(ID)); 246 break; 247 case SampleRate: 248 DPRINTF(I8042, "Setting mouse sample rate.\n"); 249 lastCommand = SampleRate; 250 ack(); 251 break; 252 case DisableReporting: 253 DPRINTF(I8042, "Disabling data reporting.\n"); 254 status.enabled = 0; 255 ack(); 256 break; 257 case EnableReporting: 258 DPRINTF(I8042, "Enabling data reporting.\n"); 259 status.enabled = 1; 260 ack(); 261 break; 262 case DefaultsAndDisable: 263 DPRINTF(I8042, "Disabling and resetting mouse.\n"); 264 sampleRate = 100; 265 resolution = 4; 266 status.twoToOne = 0; 267 status.enabled = 0; 268 ack(); 269 break; 270 case Resend: 271 panic("Mouse resend unimplemented.\n"); 272 case Reset: 273 DPRINTF(I8042, "Resetting the mouse.\n"); 274 sampleRate = 100; 275 resolution = 4; 276 status.twoToOne = 0; 277 status.enabled = 0; 278 ack(); 279 bufferData(&BatSuccessful, sizeof(BatSuccessful)); 280 bufferData(ID, sizeof(ID)); 281 break; 282 default: 283 warn("Unknown mouse command %#02x.\n", data); 284 nack(); 285 break; 286 } 287 return hasData(); 288} 289 290 291Tick 292X86ISA::I8042::read(PacketPtr pkt) 293{ 294 assert(pkt->getSize() == 1); 295 Addr addr = pkt->getAddr(); 296 if (addr == dataPort) { 297 uint8_t data = readDataOut(); 298 //DPRINTF(I8042, "Read from data port got %#02x.\n", data); 299 pkt->set<uint8_t>(data); 300 } else if (addr == commandPort) { 301 //DPRINTF(I8042, "Read status as %#02x.\n", (uint8_t)statusReg); 302 pkt->set<uint8_t>((uint8_t)statusReg); 303 } else { 304 panic("Read from unrecognized port %#x.\n", addr); 305 } 306 pkt->makeAtomicResponse(); 307 return latency; 308} 309 310Tick 311X86ISA::I8042::write(PacketPtr pkt) 312{ 313 assert(pkt->getSize() == 1); 314 Addr addr = pkt->getAddr(); 315 uint8_t data = pkt->get<uint8_t>(); 316 if (addr == dataPort) { 317 statusReg.commandLast = 0; 318 switch (lastCommand) { 319 case NoCommand: 320 if (keyboard.processData(data)) { 321 writeData(keyboard.getData(), false); 322 } 323 break; 324 case WriteToMouse: 325 if (mouse.processData(data)) { 326 writeData(mouse.getData(), true); 327 } 328 break; 329 case WriteCommandByte: 330 commandByte = data; 331 DPRINTF(I8042, "Got data %#02x for \"Write " 332 "command byte\" command.\n", data); 333 statusReg.passedSelfTest = (uint8_t)commandByte.passedSelfTest; 334 break; 335 case WriteMouseOutputBuff: 336 DPRINTF(I8042, "Got data %#02x for \"Write " 337 "mouse output buffer\" command.\n", data); 338 writeData(data, true); 339 break; 340 default: 341 panic("Data written for unrecognized " 342 "command %#02x\n", lastCommand); 343 } 344 lastCommand = NoCommand; 345 } else if (addr == commandPort) { 346 DPRINTF(I8042, "Got command %#02x.\n", data); 347 statusReg.commandLast = 1; 348 // These purposefully leave off the first byte of the controller RAM 349 // so it can be handled specially. 350 if (data > ReadControllerRamBase && 351 data < ReadControllerRamBase + RamSize) { 352 panic("Attempted to use i8042 read controller RAM command to " 353 "get byte %d.\n", data - ReadControllerRamBase); 354 } else if (data > WriteControllerRamBase && 355 data < WriteControllerRamBase + RamSize) { 356 panic("Attempted to use i8042 read controller RAM command to " 357 "get byte %d.\n", data - ReadControllerRamBase); 358 } else if (data >= PulseOutputBitBase && 359 data < PulseOutputBitBase + NumOutputBits) { 360 panic("Attempted to use i8042 pulse output bit command to " 361 "to pulse bit %d.\n", data - PulseOutputBitBase); 362 } 363 switch (data) { 364 case GetCommandByte: 365 DPRINTF(I8042, "Getting command byte.\n"); 366 writeData(commandByte); 367 break; 368 case WriteCommandByte: 369 DPRINTF(I8042, "Setting command byte.\n"); 370 lastCommand = WriteCommandByte; 371 break; 372 case CheckForPassword: 373 panic("i8042 \"Check for password\" command not implemented.\n"); 374 case LoadPassword: 375 panic("i8042 \"Load password\" command not implemented.\n"); 376 case CheckPassword: 377 panic("i8042 \"Check password\" command not implemented.\n"); 378 case DisableMouse: 379 DPRINTF(I8042, "Disabling mouse at controller.\n"); 380 commandByte.disableMouse = 1; 381 break; 382 case EnableMouse: 383 DPRINTF(I8042, "Enabling mouse at controller.\n"); 384 commandByte.disableMouse = 0; 385 break; 386 case TestMouse: 387 panic("i8042 \"Test mouse\" command not implemented.\n"); 388 case SelfTest: 389 panic("i8042 \"Self test\" command not implemented.\n"); 390 case InterfaceTest: 391 panic("i8042 \"Interface test\" command not implemented.\n"); 392 case DiagnosticDump: 393 panic("i8042 \"Diagnostic dump\" command not implemented.\n"); 394 case DisableKeyboard: 395 DPRINTF(I8042, "Disabling keyboard at controller.\n"); 396 commandByte.disableKeyboard = 1; 397 break; 398 case EnableKeyboard: 399 DPRINTF(I8042, "Enabling keyboard at controller.\n"); 400 commandByte.disableKeyboard = 0; 401 break; 402 case ReadInputPort: 403 panic("i8042 \"Read input port\" command not implemented.\n"); 404 case ContinuousPollLow: 405 panic("i8042 \"Continuous poll low\" command not implemented.\n"); 406 case ContinuousPollHigh: 407 panic("i8042 \"Continuous poll high\" command not implemented.\n"); 408 case ReadOutputPort: 409 panic("i8042 \"Read output port\" command not implemented.\n"); 410 case WriteOutputPort: 411 panic("i8042 \"Write output port\" command not implemented.\n"); 412 case WriteKeyboardOutputBuff: 413 panic("i8042 \"Write keyboard output buffer\" " 414 "command not implemented.\n"); 415 case WriteMouseOutputBuff: 416 DPRINTF(I8042, "Got command to write to mouse output buffer.\n"); 417 lastCommand = WriteMouseOutputBuff; 418 break; 419 case WriteToMouse: 420 DPRINTF(I8042, "Expecting mouse command.\n"); 421 lastCommand = WriteToMouse; 422 break; 423 case DisableA20: 424 panic("i8042 \"Disable A20\" command not implemented.\n"); 425 case EnableA20: 426 panic("i8042 \"Enable A20\" command not implemented.\n"); 427 case ReadTestInputs: 428 panic("i8042 \"Read test inputs\" command not implemented.\n"); 429 case SystemReset: 430 panic("i8042 \"System reset\" command not implemented.\n"); 431 default: 432 panic("Write to unknown i8042 " 433 "(keyboard controller) command port.\n"); 434 } 435 } else { 436 panic("Write to unrecognized port %#x.\n", addr); 437 } 438 pkt->makeAtomicResponse(); 439 return latency; 440} 441 442void 443X86ISA::I8042::serialize(std::ostream &os) 444{ 445 uint8_t statusRegData = statusReg.__data; 446 uint8_t commandByteData = commandByte.__data; 447 448 SERIALIZE_SCALAR(dataPort); 449 SERIALIZE_SCALAR(commandPort); 450 SERIALIZE_SCALAR(statusRegData); 451 SERIALIZE_SCALAR(commandByteData); 452 SERIALIZE_SCALAR(dataReg); 453 SERIALIZE_SCALAR(lastCommand); 454 mouse.serialize("mouse", os); 455 keyboard.serialize("keyboard", os); 456} 457 458void 459X86ISA::I8042::unserialize(Checkpoint *cp, const std::string §ion) 460{ 461 uint8_t statusRegData; 462 uint8_t commandByteData; 463 464 UNSERIALIZE_SCALAR(dataPort); 465 UNSERIALIZE_SCALAR(commandPort); 466 UNSERIALIZE_SCALAR(statusRegData); 467 UNSERIALIZE_SCALAR(commandByteData); 468 UNSERIALIZE_SCALAR(dataReg); 469 UNSERIALIZE_SCALAR(lastCommand); 470 mouse.unserialize("mouse", cp, section); 471 keyboard.unserialize("keyboard", cp, section); 472 473 statusReg.__data = statusRegData; 474 commandByte.__data = commandByteData; 475} 476 477void 478X86ISA::PS2Keyboard::serialize(const std::string &base, std::ostream &os) 479{ 480 paramOut(os, base + ".lastCommand", lastCommand); 481 int bufferSize = outBuffer.size(); 482 paramOut(os, base + ".outBuffer.size", bufferSize); 483 uint8_t *buffer = new uint8_t[bufferSize]; 484 for (int i = 0; i < bufferSize; ++i) { 485 buffer[i] = outBuffer.front(); 486 outBuffer.pop(); 487 } 488 arrayParamOut(os, base + ".outBuffer.elts", buffer, 489 bufferSize*sizeof(uint8_t)); 490 delete buffer; 491} 492 493void 494X86ISA::PS2Keyboard::unserialize(const std::string &base, Checkpoint *cp, 495 const std::string §ion) 496{ 497 paramIn(cp, section, base + ".lastCommand", lastCommand); 498 int bufferSize; 499 paramIn(cp, section, base + ".outBuffer.size", bufferSize); 500 uint8_t *buffer = new uint8_t[bufferSize]; 501 arrayParamIn(cp, section, base + ".outBuffer.elts", buffer, 502 bufferSize*sizeof(uint8_t)); 503 for (int i = 0; i < bufferSize; ++i) { 504 outBuffer.push(buffer[i]); 505 } 506 delete buffer; 507} 508 509void 510X86ISA::PS2Mouse::serialize(const std::string &base, std::ostream &os) 511{ 512 uint8_t statusData = status.__data; 513 paramOut(os, base + ".lastCommand", lastCommand); 514 int bufferSize = outBuffer.size(); 515 paramOut(os, base + ".outBuffer.size", bufferSize); 516 uint8_t *buffer = new uint8_t[bufferSize]; 517 for (int i = 0; i < bufferSize; ++i) { 518 buffer[i] = outBuffer.front(); 519 outBuffer.pop(); 520 } 521 arrayParamOut(os, base + ".outBuffer.elts", buffer, 522 bufferSize*sizeof(uint8_t)); 523 delete buffer; 524 paramOut(os, base + ".status", statusData); 525 paramOut(os, base + ".resolution", resolution); 526 paramOut(os, base + ".sampleRate", sampleRate); 527} 528 529void 530X86ISA::PS2Mouse::unserialize(const std::string &base, Checkpoint *cp, 531 const std::string §ion) 532{ 533 uint8_t statusData; 534 paramIn(cp, section, base + ".lastCommand", lastCommand); 535 int bufferSize; 536 paramIn(cp, section, base + ".outBuffer.size", bufferSize); 537 uint8_t *buffer = new uint8_t[bufferSize]; 538 arrayParamIn(cp, section, base + ".outBuffer.elts", buffer, 539 bufferSize*sizeof(uint8_t)); 540 for (int i = 0; i < bufferSize; ++i) { 541 outBuffer.push(buffer[i]); 542 } 543 delete buffer; 544 paramIn(cp, section, base + ".status", statusData); 545 paramIn(cp, section, base + ".resolution", resolution); 546 paramIn(cp, section, base + ".sampleRate", sampleRate); 547 548 status.__data = statusData; 549} 550 551X86ISA::I8042 * 552I8042Params::create() 553{ 554 return new X86ISA::I8042(this); 555}
| 33#include "dev/x86/i8042.hh" 34#include "mem/packet.hh" 35#include "mem/packet_access.hh" 36 37// The 8042 has a whopping 32 bytes of internal RAM. 38const uint8_t RamSize = 32; 39const uint8_t NumOutputBits = 14; 40const uint8_t X86ISA::PS2Keyboard::ID[] = {0xab, 0x83}; 41const uint8_t X86ISA::PS2Mouse::ID[] = {0x00}; 42const uint8_t CommandAck = 0xfa; 43const uint8_t CommandNack = 0xfe; 44const uint8_t BatSuccessful = 0xaa; 45 46void 47X86ISA::I8042::addressRanges(AddrRangeList &range_list) 48{ 49 range_list.clear(); 50 range_list.push_back(RangeSize(dataPort, 1)); 51 range_list.push_back(RangeSize(commandPort, 1)); 52} 53 54void 55X86ISA::I8042::writeData(uint8_t newData, bool mouse) 56{ 57 DPRINTF(I8042, "Set data %#02x.\n", newData); 58 dataReg = newData; 59 statusReg.outputFull = 1; 60 statusReg.mouseOutputFull = (mouse ? 1 : 0); 61 if (!mouse && commandByte.keyboardFullInt) { 62 DPRINTF(I8042, "Sending keyboard interrupt.\n"); 63 keyboardIntPin->raise(); 64 //This is a hack 65 keyboardIntPin->lower(); 66 } else if (mouse && commandByte.mouseFullInt) { 67 DPRINTF(I8042, "Sending mouse interrupt.\n"); 68 mouseIntPin->raise(); 69 //This is a hack 70 mouseIntPin->lower(); 71 } 72} 73 74void 75X86ISA::PS2Device::ack() 76{ 77 bufferData(&CommandAck, sizeof(CommandAck)); 78} 79 80void 81X86ISA::PS2Device::nack() 82{ 83 bufferData(&CommandNack, sizeof(CommandNack)); 84} 85 86void 87X86ISA::PS2Device::bufferData(const uint8_t *data, int size) 88{ 89 assert(data || size == 0); 90 while (size) { 91 outBuffer.push(*(data++)); 92 size--; 93 } 94} 95 96uint8_t 97X86ISA::I8042::readDataOut() 98{ 99 uint8_t data = dataReg; 100 statusReg.outputFull = 0; 101 statusReg.mouseOutputFull = 0; 102 if (keyboard.hasData()) { 103 writeData(keyboard.getData(), false); 104 } else if (mouse.hasData()) { 105 writeData(mouse.getData(), true); 106 } 107 return data; 108} 109 110bool 111X86ISA::PS2Keyboard::processData(uint8_t data) 112{ 113 if (lastCommand != NoCommand) { 114 switch (lastCommand) { 115 case LEDWrite: 116 DPRINTF(I8042, "Setting LEDs: " 117 "caps lock %s, num lock %s, scroll lock %s\n", 118 bits(data, 2) ? "on" : "off", 119 bits(data, 1) ? "on" : "off", 120 bits(data, 0) ? "on" : "off"); 121 ack(); 122 lastCommand = NoCommand; 123 break; 124 case TypematicInfo: 125 DPRINTF(I8042, "Setting typematic info to %#02x.\n", data); 126 ack(); 127 lastCommand = NoCommand; 128 break; 129 } 130 return hasData(); 131 } 132 switch (data) { 133 case LEDWrite: 134 DPRINTF(I8042, "Got LED write command.\n"); 135 ack(); 136 lastCommand = LEDWrite; 137 break; 138 case DiagnosticEcho: 139 panic("Keyboard diagnostic echo unimplemented.\n"); 140 case AlternateScanCodes: 141 panic("Accessing alternate scan codes unimplemented.\n"); 142 case ReadID: 143 DPRINTF(I8042, "Got keyboard read ID command.\n"); 144 ack(); 145 bufferData((uint8_t *)&ID, sizeof(ID)); 146 break; 147 case TypematicInfo: 148 DPRINTF(I8042, "Setting typematic info.\n"); 149 ack(); 150 lastCommand = TypematicInfo; 151 break; 152 case Enable: 153 DPRINTF(I8042, "Enabling the keyboard.\n"); 154 ack(); 155 break; 156 case Disable: 157 DPRINTF(I8042, "Disabling the keyboard.\n"); 158 ack(); 159 break; 160 case DefaultsAndDisable: 161 DPRINTF(I8042, "Disabling and resetting the keyboard.\n"); 162 ack(); 163 break; 164 case AllKeysToTypematic: 165 panic("Setting all keys to typemantic unimplemented.\n"); 166 case AllKeysToMakeRelease: 167 panic("Setting all keys to make/release unimplemented.\n"); 168 case AllKeysToMake: 169 panic("Setting all keys to make unimplemented.\n"); 170 case AllKeysToTypematicMakeRelease: 171 panic("Setting all keys to " 172 "typematic/make/release unimplemented.\n"); 173 case KeyToTypematic: 174 panic("Setting a key to typematic unimplemented.\n"); 175 case KeyToMakeRelease: 176 panic("Setting a key to make/release unimplemented.\n"); 177 case KeyToMakeOnly: 178 panic("Setting key to make only unimplemented.\n"); 179 case Resend: 180 panic("Keyboard resend unimplemented.\n"); 181 case Reset: 182 panic("Keyboard reset unimplemented.\n"); 183 default: 184 panic("Unknown keyboard command %#02x.\n", data); 185 } 186 return hasData(); 187} 188 189bool 190X86ISA::PS2Mouse::processData(uint8_t data) 191{ 192 if (lastCommand != NoCommand) { 193 switch(lastCommand) { 194 case SetResolution: 195 DPRINTF(I8042, "Mouse resolution set to %d.\n", data); 196 resolution = data; 197 ack(); 198 lastCommand = NoCommand; 199 break; 200 case SampleRate: 201 DPRINTF(I8042, "Mouse sample rate %d samples " 202 "per second.\n", data); 203 sampleRate = data; 204 ack(); 205 lastCommand = NoCommand; 206 break; 207 default: 208 panic("Not expecting data for a mouse command.\n"); 209 } 210 return hasData(); 211 } 212 switch (data) { 213 case Scale1to1: 214 DPRINTF(I8042, "Setting mouse scale to 1:1.\n"); 215 status.twoToOne = 0; 216 ack(); 217 break; 218 case Scale2to1: 219 DPRINTF(I8042, "Setting mouse scale to 2:1.\n"); 220 status.twoToOne = 1; 221 ack(); 222 break; 223 case SetResolution: 224 DPRINTF(I8042, "Setting mouse resolution.\n"); 225 lastCommand = SetResolution; 226 ack(); 227 break; 228 case GetStatus: 229 DPRINTF(I8042, "Getting mouse status.\n"); 230 ack(); 231 bufferData((uint8_t *)&(status), 1); 232 bufferData(&resolution, sizeof(resolution)); 233 bufferData(&sampleRate, sizeof(sampleRate)); 234 break; 235 case ReadData: 236 panic("Reading mouse data unimplemented.\n"); 237 case ResetWrapMode: 238 panic("Resetting mouse wrap mode unimplemented.\n"); 239 case WrapMode: 240 panic("Setting mouse wrap mode unimplemented.\n"); 241 case RemoteMode: 242 panic("Setting mouse remote mode unimplemented.\n"); 243 case ReadID: 244 DPRINTF(I8042, "Mouse ID requested.\n"); 245 ack(); 246 bufferData(ID, sizeof(ID)); 247 break; 248 case SampleRate: 249 DPRINTF(I8042, "Setting mouse sample rate.\n"); 250 lastCommand = SampleRate; 251 ack(); 252 break; 253 case DisableReporting: 254 DPRINTF(I8042, "Disabling data reporting.\n"); 255 status.enabled = 0; 256 ack(); 257 break; 258 case EnableReporting: 259 DPRINTF(I8042, "Enabling data reporting.\n"); 260 status.enabled = 1; 261 ack(); 262 break; 263 case DefaultsAndDisable: 264 DPRINTF(I8042, "Disabling and resetting mouse.\n"); 265 sampleRate = 100; 266 resolution = 4; 267 status.twoToOne = 0; 268 status.enabled = 0; 269 ack(); 270 break; 271 case Resend: 272 panic("Mouse resend unimplemented.\n"); 273 case Reset: 274 DPRINTF(I8042, "Resetting the mouse.\n"); 275 sampleRate = 100; 276 resolution = 4; 277 status.twoToOne = 0; 278 status.enabled = 0; 279 ack(); 280 bufferData(&BatSuccessful, sizeof(BatSuccessful)); 281 bufferData(ID, sizeof(ID)); 282 break; 283 default: 284 warn("Unknown mouse command %#02x.\n", data); 285 nack(); 286 break; 287 } 288 return hasData(); 289} 290 291 292Tick 293X86ISA::I8042::read(PacketPtr pkt) 294{ 295 assert(pkt->getSize() == 1); 296 Addr addr = pkt->getAddr(); 297 if (addr == dataPort) { 298 uint8_t data = readDataOut(); 299 //DPRINTF(I8042, "Read from data port got %#02x.\n", data); 300 pkt->set<uint8_t>(data); 301 } else if (addr == commandPort) { 302 //DPRINTF(I8042, "Read status as %#02x.\n", (uint8_t)statusReg); 303 pkt->set<uint8_t>((uint8_t)statusReg); 304 } else { 305 panic("Read from unrecognized port %#x.\n", addr); 306 } 307 pkt->makeAtomicResponse(); 308 return latency; 309} 310 311Tick 312X86ISA::I8042::write(PacketPtr pkt) 313{ 314 assert(pkt->getSize() == 1); 315 Addr addr = pkt->getAddr(); 316 uint8_t data = pkt->get<uint8_t>(); 317 if (addr == dataPort) { 318 statusReg.commandLast = 0; 319 switch (lastCommand) { 320 case NoCommand: 321 if (keyboard.processData(data)) { 322 writeData(keyboard.getData(), false); 323 } 324 break; 325 case WriteToMouse: 326 if (mouse.processData(data)) { 327 writeData(mouse.getData(), true); 328 } 329 break; 330 case WriteCommandByte: 331 commandByte = data; 332 DPRINTF(I8042, "Got data %#02x for \"Write " 333 "command byte\" command.\n", data); 334 statusReg.passedSelfTest = (uint8_t)commandByte.passedSelfTest; 335 break; 336 case WriteMouseOutputBuff: 337 DPRINTF(I8042, "Got data %#02x for \"Write " 338 "mouse output buffer\" command.\n", data); 339 writeData(data, true); 340 break; 341 default: 342 panic("Data written for unrecognized " 343 "command %#02x\n", lastCommand); 344 } 345 lastCommand = NoCommand; 346 } else if (addr == commandPort) { 347 DPRINTF(I8042, "Got command %#02x.\n", data); 348 statusReg.commandLast = 1; 349 // These purposefully leave off the first byte of the controller RAM 350 // so it can be handled specially. 351 if (data > ReadControllerRamBase && 352 data < ReadControllerRamBase + RamSize) { 353 panic("Attempted to use i8042 read controller RAM command to " 354 "get byte %d.\n", data - ReadControllerRamBase); 355 } else if (data > WriteControllerRamBase && 356 data < WriteControllerRamBase + RamSize) { 357 panic("Attempted to use i8042 read controller RAM command to " 358 "get byte %d.\n", data - ReadControllerRamBase); 359 } else if (data >= PulseOutputBitBase && 360 data < PulseOutputBitBase + NumOutputBits) { 361 panic("Attempted to use i8042 pulse output bit command to " 362 "to pulse bit %d.\n", data - PulseOutputBitBase); 363 } 364 switch (data) { 365 case GetCommandByte: 366 DPRINTF(I8042, "Getting command byte.\n"); 367 writeData(commandByte); 368 break; 369 case WriteCommandByte: 370 DPRINTF(I8042, "Setting command byte.\n"); 371 lastCommand = WriteCommandByte; 372 break; 373 case CheckForPassword: 374 panic("i8042 \"Check for password\" command not implemented.\n"); 375 case LoadPassword: 376 panic("i8042 \"Load password\" command not implemented.\n"); 377 case CheckPassword: 378 panic("i8042 \"Check password\" command not implemented.\n"); 379 case DisableMouse: 380 DPRINTF(I8042, "Disabling mouse at controller.\n"); 381 commandByte.disableMouse = 1; 382 break; 383 case EnableMouse: 384 DPRINTF(I8042, "Enabling mouse at controller.\n"); 385 commandByte.disableMouse = 0; 386 break; 387 case TestMouse: 388 panic("i8042 \"Test mouse\" command not implemented.\n"); 389 case SelfTest: 390 panic("i8042 \"Self test\" command not implemented.\n"); 391 case InterfaceTest: 392 panic("i8042 \"Interface test\" command not implemented.\n"); 393 case DiagnosticDump: 394 panic("i8042 \"Diagnostic dump\" command not implemented.\n"); 395 case DisableKeyboard: 396 DPRINTF(I8042, "Disabling keyboard at controller.\n"); 397 commandByte.disableKeyboard = 1; 398 break; 399 case EnableKeyboard: 400 DPRINTF(I8042, "Enabling keyboard at controller.\n"); 401 commandByte.disableKeyboard = 0; 402 break; 403 case ReadInputPort: 404 panic("i8042 \"Read input port\" command not implemented.\n"); 405 case ContinuousPollLow: 406 panic("i8042 \"Continuous poll low\" command not implemented.\n"); 407 case ContinuousPollHigh: 408 panic("i8042 \"Continuous poll high\" command not implemented.\n"); 409 case ReadOutputPort: 410 panic("i8042 \"Read output port\" command not implemented.\n"); 411 case WriteOutputPort: 412 panic("i8042 \"Write output port\" command not implemented.\n"); 413 case WriteKeyboardOutputBuff: 414 panic("i8042 \"Write keyboard output buffer\" " 415 "command not implemented.\n"); 416 case WriteMouseOutputBuff: 417 DPRINTF(I8042, "Got command to write to mouse output buffer.\n"); 418 lastCommand = WriteMouseOutputBuff; 419 break; 420 case WriteToMouse: 421 DPRINTF(I8042, "Expecting mouse command.\n"); 422 lastCommand = WriteToMouse; 423 break; 424 case DisableA20: 425 panic("i8042 \"Disable A20\" command not implemented.\n"); 426 case EnableA20: 427 panic("i8042 \"Enable A20\" command not implemented.\n"); 428 case ReadTestInputs: 429 panic("i8042 \"Read test inputs\" command not implemented.\n"); 430 case SystemReset: 431 panic("i8042 \"System reset\" command not implemented.\n"); 432 default: 433 panic("Write to unknown i8042 " 434 "(keyboard controller) command port.\n"); 435 } 436 } else { 437 panic("Write to unrecognized port %#x.\n", addr); 438 } 439 pkt->makeAtomicResponse(); 440 return latency; 441} 442 443void 444X86ISA::I8042::serialize(std::ostream &os) 445{ 446 uint8_t statusRegData = statusReg.__data; 447 uint8_t commandByteData = commandByte.__data; 448 449 SERIALIZE_SCALAR(dataPort); 450 SERIALIZE_SCALAR(commandPort); 451 SERIALIZE_SCALAR(statusRegData); 452 SERIALIZE_SCALAR(commandByteData); 453 SERIALIZE_SCALAR(dataReg); 454 SERIALIZE_SCALAR(lastCommand); 455 mouse.serialize("mouse", os); 456 keyboard.serialize("keyboard", os); 457} 458 459void 460X86ISA::I8042::unserialize(Checkpoint *cp, const std::string §ion) 461{ 462 uint8_t statusRegData; 463 uint8_t commandByteData; 464 465 UNSERIALIZE_SCALAR(dataPort); 466 UNSERIALIZE_SCALAR(commandPort); 467 UNSERIALIZE_SCALAR(statusRegData); 468 UNSERIALIZE_SCALAR(commandByteData); 469 UNSERIALIZE_SCALAR(dataReg); 470 UNSERIALIZE_SCALAR(lastCommand); 471 mouse.unserialize("mouse", cp, section); 472 keyboard.unserialize("keyboard", cp, section); 473 474 statusReg.__data = statusRegData; 475 commandByte.__data = commandByteData; 476} 477 478void 479X86ISA::PS2Keyboard::serialize(const std::string &base, std::ostream &os) 480{ 481 paramOut(os, base + ".lastCommand", lastCommand); 482 int bufferSize = outBuffer.size(); 483 paramOut(os, base + ".outBuffer.size", bufferSize); 484 uint8_t *buffer = new uint8_t[bufferSize]; 485 for (int i = 0; i < bufferSize; ++i) { 486 buffer[i] = outBuffer.front(); 487 outBuffer.pop(); 488 } 489 arrayParamOut(os, base + ".outBuffer.elts", buffer, 490 bufferSize*sizeof(uint8_t)); 491 delete buffer; 492} 493 494void 495X86ISA::PS2Keyboard::unserialize(const std::string &base, Checkpoint *cp, 496 const std::string §ion) 497{ 498 paramIn(cp, section, base + ".lastCommand", lastCommand); 499 int bufferSize; 500 paramIn(cp, section, base + ".outBuffer.size", bufferSize); 501 uint8_t *buffer = new uint8_t[bufferSize]; 502 arrayParamIn(cp, section, base + ".outBuffer.elts", buffer, 503 bufferSize*sizeof(uint8_t)); 504 for (int i = 0; i < bufferSize; ++i) { 505 outBuffer.push(buffer[i]); 506 } 507 delete buffer; 508} 509 510void 511X86ISA::PS2Mouse::serialize(const std::string &base, std::ostream &os) 512{ 513 uint8_t statusData = status.__data; 514 paramOut(os, base + ".lastCommand", lastCommand); 515 int bufferSize = outBuffer.size(); 516 paramOut(os, base + ".outBuffer.size", bufferSize); 517 uint8_t *buffer = new uint8_t[bufferSize]; 518 for (int i = 0; i < bufferSize; ++i) { 519 buffer[i] = outBuffer.front(); 520 outBuffer.pop(); 521 } 522 arrayParamOut(os, base + ".outBuffer.elts", buffer, 523 bufferSize*sizeof(uint8_t)); 524 delete buffer; 525 paramOut(os, base + ".status", statusData); 526 paramOut(os, base + ".resolution", resolution); 527 paramOut(os, base + ".sampleRate", sampleRate); 528} 529 530void 531X86ISA::PS2Mouse::unserialize(const std::string &base, Checkpoint *cp, 532 const std::string §ion) 533{ 534 uint8_t statusData; 535 paramIn(cp, section, base + ".lastCommand", lastCommand); 536 int bufferSize; 537 paramIn(cp, section, base + ".outBuffer.size", bufferSize); 538 uint8_t *buffer = new uint8_t[bufferSize]; 539 arrayParamIn(cp, section, base + ".outBuffer.elts", buffer, 540 bufferSize*sizeof(uint8_t)); 541 for (int i = 0; i < bufferSize; ++i) { 542 outBuffer.push(buffer[i]); 543 } 544 delete buffer; 545 paramIn(cp, section, base + ".status", statusData); 546 paramIn(cp, section, base + ".resolution", resolution); 547 paramIn(cp, section, base + ".sampleRate", sampleRate); 548 549 status.__data = statusData; 550} 551 552X86ISA::I8042 * 553I8042Params::create() 554{ 555 return new X86ISA::I8042(this); 556}
|