1/* 2 * Copyright (c) 2013-2015 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Rene de Jong 38 */ 39 40/** @file 41 * This is a simulation model for a UFS interface 42 * The UFS interface consists of a host controller and (at least) one device. 43 * The device can contain multiple logic units. 44 * To make this interface as usefull as possible for future development, the 45 * decision has been made to split the UFS functionality from the SCSI 46 * functionality. The class UFS SCSIDevice can therefor be used as a starting 47 * point for creating a more generic SCSI device. This has as a consequence 48 * that the UFSHostDevice class contains functionality from both the host 49 * controller and the device. The current UFS standard (1.1) allows only one 50 * device, and up to 8 logic units. the logic units only handle the SCSI part 51 * of the command, and the device mainly the UFS part. Yet the split between 52 * the SCSIresume function and the SCSICMDHandle might seem a bit awkward. 53 * The SCSICMDHandle function is in essence a SCSI reply generator, and it 54 * distils the essential information from the command. A disktransfer cannot 55 * be made from this position because the scatter gather list is not included 56 * in the SCSI command, but in the Transfer Request descriptor. The device 57 * needs to manage the data transfer. This file is build up as follows: first 58 * the UFSSCSIDevice functions will be presented; then the UFSHostDevice 59 * functions. The UFSHostDevice functions are split in three parts: UFS 60 * transaction flow, data write transfer and data read transfer. The 61 * functions are then ordered in the order in which a transfer takes place. 62 */ 63 64/** 65 * Reference material can be found at the JEDEC website: 66 * UFS standard 67 * http://www.jedec.org/standards-documents/results/jesd220 68 * UFS HCI specification 69 * http://www.jedec.org/standards-documents/results/jesd223 70 */ 71 72#include "dev/arm/ufs_device.hh" 73 74/** 75 * Constructor and destructor functions of UFSHCM device 76 */ 77UFSHostDevice::UFSSCSIDevice::UFSSCSIDevice(const UFSHostDeviceParams* p, 78 uint32_t lun_id, Callback *transfer_cb, 79 Callback *read_cb): 80 SimObject(p), 81 flashDisk(p->image[lun_id]), 82 flashDevice(p->internalflash[lun_id]), 83 blkSize(p->img_blk_size), 84 lunAvail(p->image.size()), 85 diskSize(flashDisk->size()), 86 capacityLower((diskSize - 1) & 0xffffffff), 87 capacityUpper((diskSize - SectorSize) >> 32), 88 lunID(lun_id), 89 transferCompleted(false), 90 readCompleted(false), 91 totalRead(0), 92 totalWrite(0), 93 amountOfWriteTransfers(0), 94 amountOfReadTransfers(0) 95{ 96 /** 97 * These callbacks are used to communicate the events that are 98 * triggered upstream; e.g. from the Memory Device to the UFS SCSI Device 99 * or from the UFS SCSI device to the UFS host. 100 */ 101 signalDone = transfer_cb; 102 memReadCallback = new MakeCallback<UFSSCSIDevice, 103 &UFSHostDevice::UFSSCSIDevice::readCallback>(this); 104 deviceReadCallback = read_cb; 105 memWriteCallback = new MakeCallback<UFSSCSIDevice, 106 &UFSHostDevice::UFSSCSIDevice::SSDWriteDone>(this); 107 108 /** 109 * make ascii out of lun_id (and add more characters) 110 * UFS allows up to 8 logic units, so the numbering should work out 111 */ 112 uint32_t temp_id = ((lun_id | 0x30) << 24) | 0x3A4449; 113 lunInfo.dWord0 = 0x02060000; //data 114 lunInfo.dWord1 = 0x0200001F; 115 lunInfo.vendor0 = 0x484D5241; //ARMH (HMRA) 116 lunInfo.vendor1 = 0x424D4143; //CAMB (BMAC) 117 lunInfo.product0 = 0x356D6567; //gem5 (5meg) 118 lunInfo.product1 = 0x4D534655; //UFSM (MSFU) 119 lunInfo.product2 = 0x4C45444F; //ODEL (LEDO) 120 lunInfo.product3 = temp_id; // ID:"lun_id" ("lun_id":DI) 121 lunInfo.productRevision = 0x01000000; //0x01 122 123 DPRINTF(UFSHostDevice, "Logic unit %d assumes that %d logic units are" 124 " present in the system\n", lunID, lunAvail); 125 DPRINTF(UFSHostDevice,"The disksize of lun: %d should be %d blocks\n", 126 lunID, diskSize); 127 flashDevice->initializeMemory(diskSize, SectorSize); 128} 129 130 131/** 132 * These pages are SCSI specific. For more information refer to: 133 * Universal Flash Storage (UFS) JESD220 FEB 2011 (JEDEC) 134 * http://www.jedec.org/standards-documents/results/jesd220 135 */ 136const unsigned int UFSHostDevice::UFSSCSIDevice::controlPage[3] = 137 {0x01400A0A, 0x00000000, 138 0x0000FFFF}; 139const unsigned int UFSHostDevice::UFSSCSIDevice::recoveryPage[3] = 140 {0x03800A01, 0x00000000, 141 0xFFFF0003}; 142const unsigned int UFSHostDevice::UFSSCSIDevice::cachingPage[5] = 143 {0x00011208, 0x00000000, 144 0x00000000, 0x00000020, 145 0x00000000}; 146 147UFSHostDevice::UFSSCSIDevice::~UFSSCSIDevice() {} 148 149/** 150 * UFS specific SCSI handling function. 151 * The following attributes may still be added: SCSI format unit, 152 * Send diagnostic and UNMAP; 153 * Synchronize Cache and buffer read/write could not be tested yet 154 * All parameters can be found in: 155 * Universal Flash Storage (UFS) JESD220 FEB 2011 (JEDEC) 156 * http://www.jedec.org/standards-documents/results/jesd220 157 * (a JEDEC acount may be required {free of charge}) 158 */ 159 160struct UFSHostDevice::SCSIReply 161UFSHostDevice::UFSSCSIDevice::SCSICMDHandle(uint32_t* SCSI_msg) 162{ 163 struct SCSIReply scsi_out; 164 scsi_out.reset(); 165 166 /** 167 * Create the standard SCSI reponse information 168 * These values might changes over the course of a transfer 169 */ 170 scsi_out.message.header.dWord0 = UPIUHeaderDataIndWord0 | 171 lunID << 16; 172 scsi_out.message.header.dWord1 = UPIUHeaderDataIndWord1; 173 scsi_out.message.header.dWord2 = UPIUHeaderDataIndWord2; 174 statusCheck(SCSIGood, scsi_out.senseCode); 175 scsi_out.senseSize = scsi_out.senseCode[0]; 176 scsi_out.LUN = lunID; 177 scsi_out.status = SCSIGood; 178 179 DPRINTF(UFSHostDevice, "SCSI command:%2x\n", SCSI_msg[4]); 180 /**Determine what the message is and fill the response packet*/ 181 182 switch (SCSI_msg[4] & 0xFF) { 183 184 case SCSIInquiry: { 185 /** 186 * SCSI inquiry: tell about this specific logic unit 187 */ 188 scsi_out.msgSize = 36; 189 scsi_out.message.dataMsg.resize(9); 190 191 for (uint8_t count = 0; count < 9; count++) 192 scsi_out.message.dataMsg[count] = 193 (reinterpret_cast<uint32_t*> (&lunInfo))[count]; 194 } break; 195 196 case SCSIRead6: { 197 /** 198 * Read command. Number indicates the length of the command. 199 */ 200 scsi_out.expectMore = 0x02; 201 scsi_out.msgSize = 0; 202 203 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 204 205 /**BE and not nicely aligned. Apart from that it only has 206 * information in five bits of the first byte that is relevant 207 * for this field. 208 */ 209 uint32_t tmp = *reinterpret_cast<uint32_t*>(tempptr); 210 uint64_t read_offset = betoh(tmp) & 0x1FFFFF; 211 212 uint32_t read_size = tempptr[4]; 213 214 215 scsi_out.msgSize = read_size * blkSize; 216 scsi_out.offset = read_offset * blkSize; 217 218 if ((read_offset + read_size) > diskSize) 219 scsi_out.status = SCSIIllegalRequest; 220 221 DPRINTF(UFSHostDevice, "Read6 offset: 0x%8x, for %d blocks\n", 222 read_offset, read_size); 223 224 /** 225 * Renew status check, for the request may have been illegal 226 */ 227 statusCheck(scsi_out.status, scsi_out.senseCode); 228 scsi_out.senseSize = scsi_out.senseCode[0]; 229 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 230 SCSICheckCondition; 231 232 } break; 233 234 case SCSIRead10: { 235 scsi_out.expectMore = 0x02; 236 scsi_out.msgSize = 0; 237 238 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 239 240 /**BE and not nicely aligned.*/ 241 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]); 242 uint64_t read_offset = betoh(tmp); 243 244 uint16_t tmpsize = *reinterpret_cast<uint16_t*>(&tempptr[7]); 245 uint32_t read_size = betoh(tmpsize); 246 247 scsi_out.msgSize = read_size * blkSize; 248 scsi_out.offset = read_offset * blkSize; 249 250 if ((read_offset + read_size) > diskSize) 251 scsi_out.status = SCSIIllegalRequest; 252 253 DPRINTF(UFSHostDevice, "Read10 offset: 0x%8x, for %d blocks\n", 254 read_offset, read_size); 255 256 /** 257 * Renew status check, for the request may have been illegal 258 */ 259 statusCheck(scsi_out.status, scsi_out.senseCode); 260 scsi_out.senseSize = scsi_out.senseCode[0]; 261 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 262 SCSICheckCondition; 263 264 } break; 265 266 case SCSIRead16: { 267 scsi_out.expectMore = 0x02; 268 scsi_out.msgSize = 0; 269 270 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 271 272 /**BE and not nicely aligned.*/ 273 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]); 274 uint64_t read_offset = betoh(tmp); 275 276 tmp = *reinterpret_cast<uint32_t*>(&tempptr[6]); 277 read_offset = (read_offset << 32) | betoh(tmp); 278 279 tmp = *reinterpret_cast<uint32_t*>(&tempptr[10]); 280 uint32_t read_size = betoh(tmp); 281 282 scsi_out.msgSize = read_size * blkSize; 283 scsi_out.offset = read_offset * blkSize; 284 285 if ((read_offset + read_size) > diskSize) 286 scsi_out.status = SCSIIllegalRequest; 287 288 DPRINTF(UFSHostDevice, "Read16 offset: 0x%8x, for %d blocks\n", 289 read_offset, read_size); 290 291 /** 292 * Renew status check, for the request may have been illegal 293 */ 294 statusCheck(scsi_out.status, scsi_out.senseCode); 295 scsi_out.senseSize = scsi_out.senseCode[0]; 296 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 297 SCSICheckCondition; 298 299 } break; 300 301 case SCSIReadCapacity10: { 302 /** 303 * read the capacity of the device 304 */ 305 scsi_out.msgSize = 8; 306 scsi_out.message.dataMsg.resize(2); 307 scsi_out.message.dataMsg[0] = 308 betoh(capacityLower);//last block 309 scsi_out.message.dataMsg[1] = betoh(blkSize);//blocksize 310 311 } break; 312 case SCSIReadCapacity16: { 313 scsi_out.msgSize = 32; 314 scsi_out.message.dataMsg.resize(8); 315 scsi_out.message.dataMsg[0] = 316 betoh(capacityUpper);//last block 317 scsi_out.message.dataMsg[1] = 318 betoh(capacityLower);//last block 319 scsi_out.message.dataMsg[2] = betoh(blkSize);//blocksize 320 scsi_out.message.dataMsg[3] = 0x00;// 321 scsi_out.message.dataMsg[4] = 0x00;//reserved 322 scsi_out.message.dataMsg[5] = 0x00;//reserved 323 scsi_out.message.dataMsg[6] = 0x00;//reserved 324 scsi_out.message.dataMsg[7] = 0x00;//reserved 325 326 } break; 327 328 case SCSIReportLUNs: { 329 /** 330 * Find out how many Logic Units this device has. 331 */ 332 scsi_out.msgSize = (lunAvail * 8) + 8;//list + overhead 333 scsi_out.message.dataMsg.resize(2 * lunAvail + 2); 334 scsi_out.message.dataMsg[0] = (lunAvail * 8) << 24;//LUN listlength 335 scsi_out.message.dataMsg[1] = 0x00; 336 337 for (uint8_t count = 0; count < lunAvail; count++) { 338 //LUN "count" 339 scsi_out.message.dataMsg[2 + 2 * count] = (count & 0x7F) << 8; 340 scsi_out.message.dataMsg[3 + 2 * count] = 0x00; 341 } 342 343 } break; 344 345 case SCSIStartStop: { 346 //Just acknowledge; not deemed relevant ATM 347 scsi_out.msgSize = 0; 348 349 } break; 350 351 case SCSITestUnitReady: { 352 //Just acknowledge; not deemed relevant ATM 353 scsi_out.msgSize = 0; 354 355 } break; 356 357 case SCSIVerify10: { 358 /** 359 * See if the blocks that the host plans to request are in range of 360 * the device. 361 */ 362 scsi_out.msgSize = 0; 363 364 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 365 366 /**BE and not nicely aligned.*/ 367 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]); 368 uint64_t read_offset = betoh(tmp); 369 370 uint16_t tmpsize = *reinterpret_cast<uint16_t*>(&tempptr[7]); 371 uint32_t read_size = betoh(tmpsize); 372 373 if ((read_offset + read_size) > diskSize) 374 scsi_out.status = SCSIIllegalRequest; 375 376 /** 377 * Renew status check, for the request may have been illegal 378 */ 379 statusCheck(scsi_out.status, scsi_out.senseCode); 380 scsi_out.senseSize = scsi_out.senseCode[0]; 381 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 382 SCSICheckCondition; 383 384 } break; 385 386 case SCSIWrite6: { 387 /** 388 * Write command. 389 */ 390 391 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 392 393 /**BE and not nicely aligned. Apart from that it only has 394 * information in five bits of the first byte that is relevant 395 * for this field. 396 */ 397 uint32_t tmp = *reinterpret_cast<uint32_t*>(tempptr); 398 uint64_t write_offset = betoh(tmp) & 0x1FFFFF; 399 400 uint32_t write_size = tempptr[4]; 401 402 scsi_out.msgSize = write_size * blkSize; 403 scsi_out.offset = write_offset * blkSize; 404 scsi_out.expectMore = 0x01; 405 406 if ((write_offset + write_size) > diskSize) 407 scsi_out.status = SCSIIllegalRequest; 408 409 DPRINTF(UFSHostDevice, "Write6 offset: 0x%8x, for %d blocks\n", 410 write_offset, write_size); 411 412 /** 413 * Renew status check, for the request may have been illegal 414 */ 415 statusCheck(scsi_out.status, scsi_out.senseCode); 416 scsi_out.senseSize = scsi_out.senseCode[0]; 417 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 418 SCSICheckCondition; 419 420 } break; 421 422 case SCSIWrite10: { 423 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 424 425 /**BE and not nicely aligned.*/ 426 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]); 427 uint64_t write_offset = betoh(tmp); 428 429 uint16_t tmpsize = *reinterpret_cast<uint16_t*>(&tempptr[7]); 430 uint32_t write_size = betoh(tmpsize); 431 432 scsi_out.msgSize = write_size * blkSize; 433 scsi_out.offset = write_offset * blkSize; 434 scsi_out.expectMore = 0x01; 435 436 if ((write_offset + write_size) > diskSize) 437 scsi_out.status = SCSIIllegalRequest; 438 439 DPRINTF(UFSHostDevice, "Write10 offset: 0x%8x, for %d blocks\n", 440 write_offset, write_size); 441 442 /** 443 * Renew status check, for the request may have been illegal 444 */ 445 statusCheck(scsi_out.status, scsi_out.senseCode); 446 scsi_out.senseSize = scsi_out.senseCode[0]; 447 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 448 SCSICheckCondition; 449 450 } break; 451 452 case SCSIWrite16: { 453 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 454 455 /**BE and not nicely aligned.*/ 456 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]); 457 uint64_t write_offset = betoh(tmp); 458 459 tmp = *reinterpret_cast<uint32_t*>(&tempptr[6]); 460 write_offset = (write_offset << 32) | betoh(tmp); 461 462 tmp = *reinterpret_cast<uint32_t*>(&tempptr[10]); 463 uint32_t write_size = betoh(tmp); 464 465 scsi_out.msgSize = write_size * blkSize; 466 scsi_out.offset = write_offset * blkSize; 467 scsi_out.expectMore = 0x01; 468 469 if ((write_offset + write_size) > diskSize) 470 scsi_out.status = SCSIIllegalRequest; 471 472 DPRINTF(UFSHostDevice, "Write16 offset: 0x%8x, for %d blocks\n", 473 write_offset, write_size); 474 475 /** 476 * Renew status check, for the request may have been illegal 477 */ 478 statusCheck(scsi_out.status, scsi_out.senseCode); 479 scsi_out.senseSize = scsi_out.senseCode[0]; 480 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 481 SCSICheckCondition; 482 483 } break; 484 485 case SCSIFormatUnit: {//not yet verified 486 scsi_out.msgSize = 0; 487 scsi_out.expectMore = 0x01; 488 489 } break; 490 491 case SCSISendDiagnostic: {//not yet verified 492 scsi_out.msgSize = 0; 493 494 } break; 495 496 case SCSISynchronizeCache: { 497 //do we have cache (we don't have cache at this moment) 498 //TODO: here will synchronization happen when cache is modelled 499 scsi_out.msgSize = 0; 500 501 } break; 502 503 //UFS SCSI additional command set for full functionality 504 case SCSIModeSelect10: 505 //TODO: 506 //scsi_out.expectMore = 0x01;//not supported due to modepage support 507 //code isn't dead, code suggest what is to be done when implemented 508 break; 509 510 case SCSIModeSense6: case SCSIModeSense10: { 511 /** 512 * Get more discriptive information about the SCSI functionality 513 * within this logic unit. 514 */ 515 if ((SCSI_msg[4] & 0x3F0000) >> 16 == 0x0A) {//control page 516 scsi_out.message.dataMsg.resize((sizeof(controlPage) >> 2) + 2); 517 scsi_out.message.dataMsg[0] = 0x00000A00;//control page code 518 scsi_out.message.dataMsg[1] = 0x00000000;//See JEDEC220 ch8 519 520 for (uint8_t count = 0; count < 3; count++) 521 scsi_out.message.dataMsg[2 + count] = controlPage[count]; 522 523 scsi_out.msgSize = 20; 524 DPRINTF(UFSHostDevice, "CONTROL page\n"); 525 526 } else if ((SCSI_msg[4] & 0x3F0000) >> 16 == 0x01) {//recovery page 527 scsi_out.message.dataMsg.resize((sizeof(recoveryPage) >> 2) 528 + 2); 529 530 scsi_out.message.dataMsg[0] = 0x00000100;//recovery page code 531 scsi_out.message.dataMsg[1] = 0x00000000;//See JEDEC220 ch8 532 533 for (uint8_t count = 0; count < 3; count++) 534 scsi_out.message.dataMsg[2 + count] = recoveryPage[count]; 535 536 scsi_out.msgSize = 20; 537 DPRINTF(UFSHostDevice, "RECOVERY page\n"); 538 539 } else if ((SCSI_msg[4] & 0x3F0000) >> 16 == 0x08) {//caching page 540 541 scsi_out.message.dataMsg.resize((sizeof(cachingPage) >> 2) + 2); 542 scsi_out.message.dataMsg[0] = 0x00001200;//caching page code 543 scsi_out.message.dataMsg[1] = 0x00000000;//See JEDEC220 ch8 544 545 for (uint8_t count = 0; count < 5; count++) 546 scsi_out.message.dataMsg[2 + count] = cachingPage[count]; 547 548 scsi_out.msgSize = 20; 549 DPRINTF(UFSHostDevice, "CACHE page\n"); 550 551 } else if ((SCSI_msg[4] & 0x3F0000) >> 16 == 0x3F) {//ALL the pages! 552 553 scsi_out.message.dataMsg.resize(((sizeof(controlPage) + 554 sizeof(recoveryPage) + 555 sizeof(cachingPage)) >> 2) 556 + 2); 557 scsi_out.message.dataMsg[0] = 0x00003200;//all page code 558 scsi_out.message.dataMsg[1] = 0x00000000;//See JEDEC220 ch8 559 560 for (uint8_t count = 0; count < 3; count++) 561 scsi_out.message.dataMsg[2 + count] = recoveryPage[count]; 562 563 for (uint8_t count = 0; count < 5; count++) 564 scsi_out.message.dataMsg[5 + count] = cachingPage[count]; 565 566 for (uint8_t count = 0; count < 3; count++) 567 scsi_out.message.dataMsg[10 + count] = controlPage[count]; 568 569 scsi_out.msgSize = 52; 570 DPRINTF(UFSHostDevice, "Return ALL the pages!!!\n"); 571 572 } else inform("Wrong mode page requested\n"); 573 574 scsi_out.message.dataCount = scsi_out.msgSize << 24; 575 } break; 576 577 case SCSIRequestSense: { 578 scsi_out.msgSize = 0; 579 580 } break; 581 582 case SCSIUnmap:break;//not yet verified 583 584 case SCSIWriteBuffer: { 585 scsi_out.expectMore = 0x01; 586 587 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 588 589 /**BE and not nicely aligned.*/ 590 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]); 591 uint64_t write_offset = betoh(tmp) & 0xFFFFFF; 592 593 tmp = *reinterpret_cast<uint32_t*>(&tempptr[5]); 594 uint32_t write_size = betoh(tmp) & 0xFFFFFF; 595 596 scsi_out.msgSize = write_size; 597 scsi_out.offset = write_offset; 598 599 } break; 600 601 case SCSIReadBuffer: { 602 /** 603 * less trivial than normal read. Size is in bytes instead 604 * of blocks, and it is assumed (though not guaranteed) that 605 * reading is from cache. 606 */ 607 scsi_out.expectMore = 0x02; 608 609 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]); 610 611 /**BE and not nicely aligned.*/ 612 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]); 613 uint64_t read_offset = betoh(tmp) & 0xFFFFFF; 614 615 tmp = *reinterpret_cast<uint32_t*>(&tempptr[5]); 616 uint32_t read_size = betoh(tmp) & 0xFFFFFF; 617 618 scsi_out.msgSize = read_size; 619 scsi_out.offset = read_offset; 620 621 if ((read_offset + read_size) > capacityLower * blkSize) 622 scsi_out.status = SCSIIllegalRequest; 623 624 DPRINTF(UFSHostDevice, "Read buffer location: 0x%8x\n", 625 read_offset); 626 DPRINTF(UFSHostDevice, "Number of bytes: 0x%8x\n", read_size); 627 628 statusCheck(scsi_out.status, scsi_out.senseCode); 629 scsi_out.senseSize = scsi_out.senseCode[0]; 630 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 631 SCSICheckCondition; 632 633 } break; 634 635 case SCSIMaintenanceIn: { 636 /** 637 * linux sends this command three times from kernel 3.9 onwards, 638 * UFS does not support it, nor does this model. Linux knows this, 639 * but tries anyway (useful for some SD card types). 640 * Lets make clear we don't want it and just ignore it. 641 */ 642 DPRINTF(UFSHostDevice, "Ignoring Maintenance In command\n"); 643 statusCheck(SCSIIllegalRequest, scsi_out.senseCode); 644 scsi_out.senseSize = scsi_out.senseCode[0]; 645 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 646 SCSICheckCondition; 647 scsi_out.msgSize = 0; 648 } break; 649 650 default: { 651 statusCheck(SCSIIllegalRequest, scsi_out.senseCode); 652 scsi_out.senseSize = scsi_out.senseCode[0]; 653 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood : 654 SCSICheckCondition; 655 scsi_out.msgSize = 0; 656 inform("Unsupported scsi message type: %2x\n", SCSI_msg[4] & 0xFF); 657 inform("0x%8x\n", SCSI_msg[0]); 658 inform("0x%8x\n", SCSI_msg[1]); 659 inform("0x%8x\n", SCSI_msg[2]); 660 inform("0x%8x\n", SCSI_msg[3]); 661 inform("0x%8x\n", SCSI_msg[4]); 662 } break; 663 } 664 665 return scsi_out; 666} 667 668/** 669 * SCSI status check function. generic device test, creates sense codes 670 * Future versions may include TODO: device checks, which is why this is 671 * in a separate function. 672 */ 673 674void 675UFSHostDevice::UFSSCSIDevice::statusCheck(uint8_t status, 676 uint8_t* sensecodelist) 677{ 678 for (uint8_t count = 0; count < 19; count++) 679 sensecodelist[count] = 0; 680 681 sensecodelist[0] = 18; //sense length 682 sensecodelist[1] = 0x70; //we send a valid frame 683 sensecodelist[3] = status & 0xF; //mask to be sure + sensecode 684 sensecodelist[8] = 0x1F; //data length 685} 686 687/** 688 * read from the flashdisk 689 */ 690 691void 692UFSHostDevice::UFSSCSIDevice::readFlash(uint8_t* readaddr, uint64_t offset, 693 uint32_t size) 694{ 695 /** read from image, and get to memory */ 696 for (int count = 0; count < (size / SectorSize); count++) 697 flashDisk->read(&(readaddr[SectorSize*count]), (offset / 698 SectorSize) + count); 699} 700 701/** 702 * Write to the flashdisk 703 */ 704 705void 706UFSHostDevice::UFSSCSIDevice::writeFlash(uint8_t* writeaddr, uint64_t offset, 707 uint32_t size) 708{ 709 /** Get from fifo and write to image*/ 710 for (int count = 0; count < (size / SectorSize); count++) 711 flashDisk->write(&(writeaddr[SectorSize * count]), 712 (offset / SectorSize) + count); 713} 714 715/** 716 * Constructor for the UFS Host device 717 */ 718 719UFSHostDevice::UFSHostDevice(const UFSHostDeviceParams* p) : 720 DmaDevice(p), 721 pioAddr(p->pio_addr), 722 pioSize(0x0FFF), 723 pioDelay(p->pio_latency), 724 intNum(p->int_num), 725 gic(p->gic), 726 lunAvail(p->image.size()), 727 UFSSlots(p->ufs_slots - 1), 728 readPendingNum(0), 729 writePendingNum(0), 730 activeDoorbells(0), 731 pendingDoorbells(0), 732 countInt(0), 733 transferTrack(0), 734 taskCommandTrack(0), 735 idlePhaseStart(0), 736 SCSIResumeEvent([this]{ SCSIStart(); }, name()), 737 UTPEvent([this]{ finalUTP(); }, name()) 738{ 739 DPRINTF(UFSHostDevice, "The hostcontroller hosts %d Logic units\n", 740 lunAvail); 741 UFSDevice.resize(lunAvail); 742 743 transferDoneCallback = new MakeCallback<UFSHostDevice, 744 &UFSHostDevice::LUNSignal>(this); 745 memReadCallback = new MakeCallback<UFSHostDevice, 746 &UFSHostDevice::readCallback>(this); 747 748 for (int count = 0; count < lunAvail; count++) { 749 UFSDevice[count] = new UFSSCSIDevice(p, count, transferDoneCallback, 750 memReadCallback); 751 } 752 753 if (UFSSlots > 31) 754 warn("UFSSlots = %d, this will results in %d command slots", 755 UFSSlots, (UFSSlots & 0x1F)); 756 757 if ((UFSSlots & 0x1F) == 0) 758 fatal("Number of UFS command slots should be between 1 and 32."); 759 760 setValues(); 761} 762 763/** 764 * Create the parameters of this device 765 */ 766 767UFSHostDevice* 768UFSHostDeviceParams::create() 769{ 770 return new UFSHostDevice(this); 771} 772 773 774void 775UFSHostDevice::regStats() 776{ 777 DmaDevice::regStats(); 778 779 using namespace Stats; 780 781 std::string UFSHost_name = name() + ".UFSDiskHost"; 782 783 // Register the stats 784 /** Queue lengths */ 785 stats.currentSCSIQueue 786 .name(UFSHost_name + ".currentSCSIQueue") 787 .desc("Most up to date length of the command queue") 788 .flags(none); 789 stats.currentReadSSDQueue 790 .name(UFSHost_name + ".currentReadSSDQueue") 791 .desc("Most up to date length of the read SSD queue") 792 .flags(none); 793 stats.currentWriteSSDQueue 794 .name(UFSHost_name + ".currentWriteSSDQueue") 795 .desc("Most up to date length of the write SSD queue") 796 .flags(none); 797 798 /** Amount of data read/written */ 799 stats.totalReadSSD 800 .name(UFSHost_name + ".totalReadSSD") 801 .desc("Number of bytes read from SSD") 802 .flags(none); 803 804 stats.totalWrittenSSD 805 .name(UFSHost_name + ".totalWrittenSSD") 806 .desc("Number of bytes written to SSD") 807 .flags(none); 808 809 stats.totalReadDiskTransactions 810 .name(UFSHost_name + ".totalReadDiskTransactions") 811 .desc("Number of transactions from disk") 812 .flags(none); 813 stats.totalWriteDiskTransactions 814 .name(UFSHost_name + ".totalWriteDiskTransactions") 815 .desc("Number of transactions to disk") 816 .flags(none); 817 stats.totalReadUFSTransactions 818 .name(UFSHost_name + ".totalReadUFSTransactions") 819 .desc("Number of transactions from device") 820 .flags(none); 821 stats.totalWriteUFSTransactions 822 .name(UFSHost_name + ".totalWriteUFSTransactions") 823 .desc("Number of transactions to device") 824 .flags(none); 825 826 /** Average bandwidth for reads and writes */ 827 stats.averageReadSSDBW 828 .name(UFSHost_name + ".averageReadSSDBandwidth") 829 .desc("Average read bandwidth (bytes/s)") 830 .flags(nozero); 831 832 stats.averageReadSSDBW = stats.totalReadSSD / simSeconds; 833 834 stats.averageWriteSSDBW 835 .name(UFSHost_name + ".averageWriteSSDBandwidth") 836 .desc("Average write bandwidth (bytes/s)") 837 .flags(nozero); 838 839 stats.averageWriteSSDBW = stats.totalWrittenSSD / simSeconds; 840 841 stats.averageSCSIQueue 842 .name(UFSHost_name + ".averageSCSIQueueLength") 843 .desc("Average command queue length") 844 .flags(nozero); 845 stats.averageReadSSDQueue 846 .name(UFSHost_name + ".averageReadSSDQueueLength") 847 .desc("Average read queue length") 848 .flags(nozero); 849 stats.averageWriteSSDQueue 850 .name(UFSHost_name + ".averageWriteSSDQueueLength") 851 .desc("Average write queue length") 852 .flags(nozero); 853 854 /** Number of doorbells rung*/ 855 stats.curDoorbell 856 .name(UFSHost_name + ".curDoorbell") 857 .desc("Most up to date number of doorbells used") 858 .flags(none); 859 860 stats.curDoorbell = activeDoorbells; 861 862 stats.maxDoorbell 863 .name(UFSHost_name + ".maxDoorbell") 864 .desc("Maximum number of doorbells utilized") 865 .flags(none); 866 stats.averageDoorbell 867 .name(UFSHost_name + ".averageDoorbell") 868 .desc("Average number of Doorbells used") 869 .flags(nozero); 870 871 /** Latency*/ 872 stats.transactionLatency 873 .init(100) 874 .name(UFSHost_name + ".transactionLatency") 875 .desc("Histogram of transaction times") 876 .flags(pdf); 877 878 stats.idleTimes 879 .init(100) 880 .name(UFSHost_name + ".idlePeriods") 881 .desc("Histogram of idle times") 882 .flags(pdf); 883 884} 885 886/** 887 * Register init 888 */ 889void UFSHostDevice::setValues() 890{ 891 /** 892 * The capability register is built up as follows: 893 * 31-29 RES; Testmode support; O3 delivery; 64 bit addr; 894 * 23-19 RES; 18-16 #TM Req slots; 15-5 RES;4-0 # TR slots 895 */ 896 UFSHCIMem.HCCAP = 0x06070000 | (UFSSlots & 0x1F); 897 UFSHCIMem.HCversion = 0x00010000; //version is 1.0 898 UFSHCIMem.HCHCDDID = 0xAA003C3C;// Arbitrary number 899 UFSHCIMem.HCHCPMID = 0x41524D48; //ARMH (not an official MIPI number) 900 UFSHCIMem.TRUTRLDBR = 0x00; 901 UFSHCIMem.TMUTMRLDBR = 0x00; 902 UFSHCIMem.CMDUICCMDR = 0x00; 903 // We can process CMD, TM, TR, device present 904 UFSHCIMem.ORHostControllerStatus = 0x08; 905 UFSHCIMem.TRUTRLBA = 0x00; 906 UFSHCIMem.TRUTRLBAU = 0x00; 907 UFSHCIMem.TMUTMRLBA = 0x00; 908 UFSHCIMem.TMUTMRLBAU = 0x00; 909} 910 911/** 912 * Determine address ranges 913 */ 914 915AddrRangeList 916UFSHostDevice::getAddrRanges() const 917{ 918 AddrRangeList ranges; 919 ranges.push_back(RangeSize(pioAddr, pioSize)); 920 return ranges; 921} 922 923/** 924 * UFSHCD read register. This function allows the system to read the 925 * register entries 926 */ 927 928Tick 929UFSHostDevice::read(PacketPtr pkt) 930{ 931 uint32_t data = 0; 932 933 switch (pkt->getAddr() & 0xFF) 934 { 935 936 case regControllerCapabilities: 937 data = UFSHCIMem.HCCAP; 938 break; 939 940 case regUFSVersion: 941 data = UFSHCIMem.HCversion; 942 break; 943 944 case regControllerDEVID: 945 data = UFSHCIMem.HCHCDDID; 946 break; 947 948 case regControllerPRODID: 949 data = UFSHCIMem.HCHCPMID; 950 break; 951 952 case regInterruptStatus: 953 data = UFSHCIMem.ORInterruptStatus; 954 UFSHCIMem.ORInterruptStatus = 0x00; 955 //TODO: Revise and extend 956 clearInterrupt(); 957 break; 958 959 case regInterruptEnable: 960 data = UFSHCIMem.ORInterruptEnable; 961 break; 962 963 case regControllerStatus: 964 data = UFSHCIMem.ORHostControllerStatus; 965 break; 966 967 case regControllerEnable: 968 data = UFSHCIMem.ORHostControllerEnable; 969 break; 970 971 case regUICErrorCodePHYAdapterLayer: 972 data = UFSHCIMem.ORUECPA; 973 break; 974 975 case regUICErrorCodeDataLinkLayer: 976 data = UFSHCIMem.ORUECDL; 977 break; 978 979 case regUICErrorCodeNetworkLayer: 980 data = UFSHCIMem.ORUECN; 981 break; 982 983 case regUICErrorCodeTransportLayer: 984 data = UFSHCIMem.ORUECT; 985 break; 986 987 case regUICErrorCodeDME: 988 data = UFSHCIMem.ORUECDME; 989 break; 990 991 case regUTPTransferREQINTAGGControl: 992 data = UFSHCIMem.ORUTRIACR; 993 break; 994 995 case regUTPTransferREQListBaseL: 996 data = UFSHCIMem.TRUTRLBA; 997 break; 998 999 case regUTPTransferREQListBaseH: 1000 data = UFSHCIMem.TRUTRLBAU; 1001 break; 1002 1003 case regUTPTransferREQDoorbell: 1004 data = UFSHCIMem.TRUTRLDBR; 1005 break; 1006 1007 case regUTPTransferREQListClear: 1008 data = UFSHCIMem.TRUTRLCLR; 1009 break; 1010 1011 case regUTPTransferREQListRunStop: 1012 data = UFSHCIMem.TRUTRLRSR; 1013 break; 1014 1015 case regUTPTaskREQListBaseL: 1016 data = UFSHCIMem.TMUTMRLBA; 1017 break; 1018 1019 case regUTPTaskREQListBaseH: 1020 data = UFSHCIMem.TMUTMRLBAU; 1021 break; 1022 1023 case regUTPTaskREQDoorbell: 1024 data = UFSHCIMem.TMUTMRLDBR; 1025 break; 1026 1027 case regUTPTaskREQListClear: 1028 data = UFSHCIMem.TMUTMRLCLR; 1029 break; 1030 1031 case regUTPTaskREQListRunStop: 1032 data = UFSHCIMem.TMUTMRLRSR; 1033 break; 1034 1035 case regUICCommand: 1036 data = UFSHCIMem.CMDUICCMDR; 1037 break; 1038 1039 case regUICCommandArg1: 1040 data = UFSHCIMem.CMDUCMDARG1; 1041 break; 1042 1043 case regUICCommandArg2: 1044 data = UFSHCIMem.CMDUCMDARG2; 1045 break; 1046 1047 case regUICCommandArg3: 1048 data = UFSHCIMem.CMDUCMDARG3; 1049 break; 1050 1051 default: 1052 data = 0x00; 1053 break; 1054 } 1055 1056 pkt->setLE<uint32_t>(data); 1057 pkt->makeResponse(); 1058 return pioDelay; 1059} 1060 1061/** 1062 * UFSHCD write function. This function allows access to the writeable 1063 * registers. If any function attempts to write value to an unwriteable 1064 * register entry, then the value will not be written. 1065 */ 1066Tick 1067UFSHostDevice::write(PacketPtr pkt) 1068{ 1069 uint32_t data = 0; 1070 1071 switch (pkt->getSize()) { 1072 1073 case 1: 1074 data = pkt->getLE<uint8_t>(); 1075 break; 1076 1077 case 2: 1078 data = pkt->getLE<uint16_t>(); 1079 break; 1080 1081 case 4: 1082 data = pkt->getLE<uint32_t>(); 1083 break; 1084 1085 default: 1086 panic("Undefined UFSHCD controller write size!\n"); 1087 break; 1088 } 1089 1090 switch (pkt->getAddr() & 0xFF) 1091 { 1092 case regControllerCapabilities://you shall not write to this 1093 break; 1094 1095 case regUFSVersion://you shall not write to this 1096 break; 1097 1098 case regControllerDEVID://you shall not write to this 1099 break; 1100 1101 case regControllerPRODID://you shall not write to this 1102 break; 1103 1104 case regInterruptStatus://you shall not write to this 1105 break; 1106 1107 case regInterruptEnable: 1108 UFSHCIMem.ORInterruptEnable = data; 1109 break; 1110 1111 case regControllerStatus: 1112 UFSHCIMem.ORHostControllerStatus = data; 1113 break; 1114 1115 case regControllerEnable: 1116 UFSHCIMem.ORHostControllerEnable = data; 1117 break; 1118 1119 case regUICErrorCodePHYAdapterLayer: 1120 UFSHCIMem.ORUECPA = data; 1121 break; 1122 1123 case regUICErrorCodeDataLinkLayer: 1124 UFSHCIMem.ORUECDL = data; 1125 break; 1126 1127 case regUICErrorCodeNetworkLayer: 1128 UFSHCIMem.ORUECN = data; 1129 break; 1130 1131 case regUICErrorCodeTransportLayer: 1132 UFSHCIMem.ORUECT = data; 1133 break; 1134 1135 case regUICErrorCodeDME: 1136 UFSHCIMem.ORUECDME = data; 1137 break; 1138 1139 case regUTPTransferREQINTAGGControl: 1140 UFSHCIMem.ORUTRIACR = data; 1141 break; 1142 1143 case regUTPTransferREQListBaseL: 1144 UFSHCIMem.TRUTRLBA = data; 1145 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1146 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU)!= 0x00)) 1147 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1148 break; 1149 1150 case regUTPTransferREQListBaseH: 1151 UFSHCIMem.TRUTRLBAU = data; 1152 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1153 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1154 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1155 break; 1156 1157 case regUTPTransferREQDoorbell: 1158 if (!(UFSHCIMem.TRUTRLDBR) && data) 1159 stats.idleTimes.sample(curTick() - idlePhaseStart); 1160 UFSHCIMem.TRUTRLDBR |= data; 1161 requestHandler(); 1162 break; 1163 1164 case regUTPTransferREQListClear: 1165 UFSHCIMem.TRUTRLCLR = data; 1166 break; 1167 1168 case regUTPTransferREQListRunStop: 1169 UFSHCIMem.TRUTRLRSR = data; 1170 break; 1171 1172 case regUTPTaskREQListBaseL: 1173 UFSHCIMem.TMUTMRLBA = data; 1174 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1175 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1176 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1177 break; 1178 1179 case regUTPTaskREQListBaseH: 1180 UFSHCIMem.TMUTMRLBAU = data; 1181 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1182 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1183 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1184 break; 1185 1186 case regUTPTaskREQDoorbell: 1187 UFSHCIMem.TMUTMRLDBR |= data; 1188 requestHandler(); 1189 break; 1190 1191 case regUTPTaskREQListClear: 1192 UFSHCIMem.TMUTMRLCLR = data; 1193 break; 1194 1195 case regUTPTaskREQListRunStop: 1196 UFSHCIMem.TMUTMRLRSR = data; 1197 break; 1198 1199 case regUICCommand: 1200 UFSHCIMem.CMDUICCMDR = data; 1201 requestHandler(); 1202 break; 1203 1204 case regUICCommandArg1: 1205 UFSHCIMem.CMDUCMDARG1 = data; 1206 break; 1207 1208 case regUICCommandArg2: 1209 UFSHCIMem.CMDUCMDARG2 = data; 1210 break; 1211 1212 case regUICCommandArg3: 1213 UFSHCIMem.CMDUCMDARG3 = data; 1214 break; 1215 1216 default:break;//nothing happens, you try to access a register that 1217 //does not exist 1218 1219 } 1220 1221 pkt->makeResponse(); 1222 return pioDelay; 1223} 1224 1225/** 1226 * Request handler. Determines where the request comes from and initiates the 1227 * appropriate actions accordingly. 1228 */ 1229 1230void 1231UFSHostDevice::requestHandler() 1232{ 1233 Addr address = 0x00; 1234 int mask = 0x01; 1235 int size; 1236 int count = 0; 1237 struct taskStart task_info; 1238 struct transferStart transferstart_info; 1239 transferstart_info.done = 0; 1240 1241 /** 1242 * step1 determine what called us 1243 * step2 determine where to get it 1244 * Look for any request of which we where not yet aware 1245 */ 1246 while (((UFSHCIMem.CMDUICCMDR > 0x00) | 1247 ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) | 1248 ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00)) ) { 1249 1250 if (UFSHCIMem.CMDUICCMDR > 0x00) { 1251 /** 1252 * Command; general control of the Host controller. 1253 * no DMA transfer needed 1254 */ 1255 commandHandler(); 1256 UFSHCIMem.ORInterruptStatus |= UICCommandCOMPL; 1257 generateInterrupt(); 1258 UFSHCIMem.CMDUICCMDR = 0x00; 1259 return; //command, nothing more we can do 1260 1261 } else if ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) { 1262 /** 1263 * Task; flow control, meant for the device/Logic unit 1264 * DMA transfer is needed, flash will not be approached 1265 */ 1266 size = sizeof(UTPUPIUTaskReq); 1267 /**Find the position that is not handled yet*/ 1268 count = findLsbSet((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack)); 1269 address = UFSHCIMem.TMUTMRLBAU; 1270 //<-64 bit 1271 address = (count * size) + (address << 32) + 1272 UFSHCIMem.TMUTMRLBA; 1273 taskCommandTrack |= mask << count; 1274 1275 inform("UFSmodel received a task from the system; this might" 1276 " lead to untested behaviour.\n"); 1277 1278 task_info.mask = mask << count; 1279 task_info.address = address; 1280 task_info.size = size; 1281 task_info.done = UFSHCIMem.TMUTMRLDBR; 1282 taskInfo.push_back(task_info); 1283 taskEventQueue.push_back( 1284 EventFunctionWrapper([this]{ taskStart(); }, name())); 1285 writeDevice(&taskEventQueue.back(), false, address, size, 1286 reinterpret_cast<uint8_t*> 1287 (&taskInfo.back().destination), 0, 0); 1288 1289 } else if ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00) { 1290 /** 1291 * Transfer; Data transfer from or to the disk. There will be DMA 1292 * transfers, and the flash might be approached. Further 1293 * commands, are needed to specify the exact command. 1294 */ 1295 size = sizeof(UTPTransferReqDesc); 1296 /**Find the position that is not handled yet*/ 1297 count = findLsbSet((UFSHCIMem.TRUTRLDBR ^ transferTrack)); 1298 address = UFSHCIMem.TRUTRLBAU; 1299 //<-64 bit 1300 address = (count * size) + (address << 32) + UFSHCIMem.TRUTRLBA; 1301 1302 transferTrack |= mask << count; 1303 DPRINTF(UFSHostDevice, "Doorbell register: 0x%8x select #:" 1304 " 0x%8x completion info: 0x%8x\n", UFSHCIMem.TRUTRLDBR, 1305 count, transferstart_info.done); 1306 1307 transferstart_info.done = UFSHCIMem.TRUTRLDBR; 1308 1309 /**stats**/ 1310 transactionStart[count] = curTick(); //note the start time 1311 ++activeDoorbells; 1312 stats.maxDoorbell = (stats.maxDoorbell.value() < activeDoorbells) 1313 ? activeDoorbells : stats.maxDoorbell.value(); 1314 stats.averageDoorbell = stats.maxDoorbell.value(); 1315 1316 /** 1317 * step3 start transfer 1318 * step4 register information; allowing the host to respond in 1319 * the end 1320 */ 1321 transferstart_info.mask = mask << count; 1322 transferstart_info.address = address; 1323 transferstart_info.size = size; 1324 transferstart_info.done = UFSHCIMem.TRUTRLDBR; 1325 transferStartInfo.push_back(transferstart_info); 1326 1327 /**Deleted in readDone, queued in finalUTP*/ 1328 transferStartInfo.back().destination = new struct 1329 UTPTransferReqDesc; 1330 DPRINTF(UFSHostDevice, "Initial transfer start: 0x%8x\n", 1331 transferstart_info.done); 1332 transferEventQueue.push_back( 1333 EventFunctionWrapper([this]{ transferStart(); }, name())); 1334 1335 if (transferEventQueue.size() < 2) { 1336 writeDevice(&transferEventQueue.front(), false, 1337 address, size, reinterpret_cast<uint8_t*> 1338 (transferStartInfo.front().destination),0, 0); 1339 DPRINTF(UFSHostDevice, "Transfer scheduled\n"); 1340 } 1341 } 1342 } 1343} 1344 1345/** 1346 * Task start event 1347 */ 1348 1349void 1350UFSHostDevice::taskStart() 1351{ 1352 DPRINTF(UFSHostDevice, "Task start"); 1353 taskHandler(&taskInfo.front().destination, taskInfo.front().mask, 1354 taskInfo.front().address, taskInfo.front().size); 1355 taskInfo.pop_front(); 1356 taskEventQueue.pop_front(); 1357} 1358 1359/** 1360 * Transfer start event 1361 */ 1362 1363void 1364UFSHostDevice::transferStart() 1365{ 1366 DPRINTF(UFSHostDevice, "Enter transfer event\n"); 1367 transferHandler(transferStartInfo.front().destination, 1368 transferStartInfo.front().mask, 1369 transferStartInfo.front().address, 1370 transferStartInfo.front().size, 1371 transferStartInfo.front().done); 1372 1373 transferStartInfo.pop_front(); 1374 DPRINTF(UFSHostDevice, "Transfer queue size at end of event: " 1375 "0x%8x\n", transferEventQueue.size()); 1376} 1377 1378/** 1379 * Handles the commands that are given. At this point in time, not many 1380 * commands have been implemented in the driver. 1381 */ 1382 1383void 1384UFSHostDevice::commandHandler() 1385{ 1386 if (UFSHCIMem.CMDUICCMDR == 0x16) { 1387 UFSHCIMem.ORHostControllerStatus |= 0x0F;//link startup 1388 } 1389 1390} 1391 1392/** 1393 * Handles the tasks that are given. At this point in time, not many tasks 1394 * have been implemented in the driver. 1395 */ 1396 1397void 1398UFSHostDevice::taskHandler(struct UTPUPIUTaskReq* request_in, 1399 uint32_t req_pos, Addr finaladdress, uint32_t 1400 finalsize) 1401{ 1402 /** 1403 * For now, just unpack and acknowledge the task without doing anything. 1404 * TODO Implement UFS tasks. 1405 */ 1406 inform("taskHandler\n"); 1407 inform("%8x\n", request_in->header.dWord0); 1408 inform("%8x\n", request_in->header.dWord1); 1409 inform("%8x\n", request_in->header.dWord2); 1410 1411 request_in->header.dWord2 &= 0xffffff00; 1412 1413 UFSHCIMem.TMUTMRLDBR &= ~(req_pos); 1414 taskCommandTrack &= ~(req_pos); 1415 UFSHCIMem.ORInterruptStatus |= UTPTaskREQCOMPL; 1416 1417 readDevice(true, finaladdress, finalsize, reinterpret_cast<uint8_t*> 1418 (request_in), true, NULL); 1419 1420} 1421 1422/** 1423 * Obtains the SCSI command (if any) 1424 * Two possibilities: if it contains a SCSI command, then it is a usable 1425 * message; if it doesnt contain a SCSI message, then it can't be handeld 1426 * by this code. 1427 * This is the second stage of the transfer. We have the information about 1428 * where the next command can be found and what the type of command is. The 1429 * actions that are needed from the device its side are: get the information 1430 * and store the information such that we can reply. 1431 */ 1432 1433void 1434UFSHostDevice::transferHandler(struct UTPTransferReqDesc* request_in, 1435 int req_pos, Addr finaladdress, uint32_t 1436 finalsize, uint32_t done) 1437{ 1438 1439 Addr cmd_desc_addr = 0x00; 1440 1441 1442 //acknowledge handling of the message 1443 DPRINTF(UFSHostDevice, "SCSI message detected\n"); 1444 request_in->header.dWord2 &= 0xffffff00; 1445 SCSIInfo.RequestIn = request_in; 1446 SCSIInfo.reqPos = req_pos; 1447 SCSIInfo.finalAddress = finaladdress; 1448 SCSIInfo.finalSize = finalsize; 1449 SCSIInfo.destination.resize(request_in->PRDTableOffset * 4 1450 + request_in->PRDTableLength * sizeof(UFSHCDSGEntry)); 1451 SCSIInfo.done = done; 1452 1453 assert(!SCSIResumeEvent.scheduled()); 1454 /** 1455 *Get the UTP command that has the SCSI command 1456 */ 1457 cmd_desc_addr = request_in->commandDescBaseAddrHi; 1458 cmd_desc_addr = (cmd_desc_addr << 32) | 1459 (request_in->commandDescBaseAddrLo & 0xffffffff); 1460 1461 writeDevice(&SCSIResumeEvent, false, cmd_desc_addr, 1462 SCSIInfo.destination.size(), &SCSIInfo.destination[0],0, 0); 1463 1464 DPRINTF(UFSHostDevice, "SCSI scheduled\n"); 1465 1466 transferEventQueue.pop_front(); 1467} 1468 1469/** 1470 * Obtain LUN and put it in the right LUN queue. Each LUN has its own queue 1471 * of commands that need to be executed. This is the first instance where it 1472 * can be determined which Logic unit should handle the transfer. Then check 1473 * wether it should wait and queue or if it can continue. 1474 */ 1475 1476void 1477UFSHostDevice::SCSIStart() 1478{ 1479 DPRINTF(UFSHostDevice, "SCSI message on hold until ready\n"); 1480 uint32_t LUN = SCSIInfo.destination[2]; 1481 UFSDevice[LUN]->SCSIInfoQueue.push_back(SCSIInfo); 1482 1483 DPRINTF(UFSHostDevice, "SCSI queue %d has %d elements\n", LUN, 1484 UFSDevice[LUN]->SCSIInfoQueue.size()); 1485 1486 /**There are 32 doorbells, so at max there can be 32 transactions*/ 1487 if (UFSDevice[LUN]->SCSIInfoQueue.size() < 2) //LUN is available 1488 SCSIResume(LUN); 1489 1490 else if (UFSDevice[LUN]->SCSIInfoQueue.size() > 32) 1491 panic("SCSI queue is getting too big %d\n", UFSDevice[LUN]-> 1492 SCSIInfoQueue.size()); 1493 1494 /** 1495 * First transfer is done, fetch the next; 1496 * At this point, the device is busy, not the HC 1497 */ 1498 if (!transferEventQueue.empty()) { 1499 1500 /** 1501 * loading next data packet in case Another LUN 1502 * is approached in the mean time 1503 */ 1504 writeDevice(&transferEventQueue.front(), false, 1505 transferStartInfo.front().address, 1506 transferStartInfo.front().size, reinterpret_cast<uint8_t*> 1507 (transferStartInfo.front().destination), 0, 0); 1508 1509 DPRINTF(UFSHostDevice, "Transfer scheduled"); 1510 } 1511} 1512 1513/** 1514 * Handles the transfer requests that are given. 1515 * There can be three types of transfer. SCSI specific, Reads and writes 1516 * apart from the data transfer, this also generates its own reply (UPIU 1517 * response). Information for this reply is stored in transferInfo and will 1518 * be used in transferDone 1519 */ 1520 1521void 1522UFSHostDevice::SCSIResume(uint32_t lun_id) 1523{ 1524 DPRINTF(UFSHostDevice, "SCSIresume\n"); 1525 if (UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1526 panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id, 1527 UFSHCIMem.TRUTRLDBR); 1528 1529 /**old info, lets form it such that we can understand it*/ 1530 struct UTPTransferReqDesc* request_in = UFSDevice[lun_id]-> 1531 SCSIInfoQueue.front().RequestIn; 1532 1533 uint32_t req_pos = UFSDevice[lun_id]->SCSIInfoQueue.front().reqPos; 1534 1535 Addr finaladdress = UFSDevice[lun_id]->SCSIInfoQueue.front(). 1536 finalAddress; 1537 1538 uint32_t finalsize = UFSDevice[lun_id]->SCSIInfoQueue.front().finalSize; 1539 1540 uint32_t* transfercommand = reinterpret_cast<uint32_t*> 1541 (&(UFSDevice[lun_id]->SCSIInfoQueue.front().destination[0])); 1542 1543 DPRINTF(UFSHostDevice, "Task tag: 0x%8x\n", transfercommand[0]>>24); 1544 /**call logic unit to handle SCSI command*/ 1545 request_out_datain = UFSDevice[(transfercommand[0] & 0xFF0000) >> 16]-> 1546 SCSICMDHandle(transfercommand); 1547 1548 DPRINTF(UFSHostDevice, "LUN: %d\n", request_out_datain.LUN); 1549 1550 /** 1551 * build response stating that it was succesful 1552 * command completion, Logic unit number, and Task tag 1553 */ 1554 request_in->header.dWord0 = ((request_in->header.dWord0 >> 24) == 0x21) 1555 ? 0x36 : 0x21; 1556 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord0 = 1557 request_in->header.dWord0 | (request_out_datain.LUN << 8) 1558 | (transfercommand[0] & 0xFF000000); 1559 /**SCSI status reply*/ 1560 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord1 = 0x00000000 | 1561 (request_out_datain.status << 24); 1562 /**segment size + EHS length (see UFS standard ch7)*/ 1563 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord2 = 0x00000000 | 1564 ((request_out_datain.senseSize + 2) << 24) | 0x05; 1565 /**amount of data that will follow*/ 1566 UFSDevice[lun_id]->transferInfo.requestOut.senseDataLen = 1567 request_out_datain.senseSize; 1568 1569 //data 1570 for (uint8_t count = 0; count<request_out_datain.senseSize; count++) { 1571 UFSDevice[lun_id]->transferInfo.requestOut.senseData[count] = 1572 request_out_datain.senseCode[count + 1]; 1573 } 1574 1575 /* 1576 * At position defined by "request_in->PRDTableOffset" (counting 32 bit 1577 * words) in array "transfercommand" we have a scatter gather list, which 1578 * is usefull to us if we interpreted it as a UFSHCDSGEntry structure. 1579 */ 1580 struct UFSHCDSGEntry* sglist = reinterpret_cast<UFSHCDSGEntry*> 1581 (&(transfercommand[(request_in->PRDTableOffset)])); 1582 1583 uint32_t length = request_in->PRDTableLength; 1584 DPRINTF(UFSHostDevice, "# PRDT entries: %d\n", length); 1585 1586 Addr response_addr = request_in->commandDescBaseAddrHi; 1587 response_addr = (response_addr << 32) | 1588 ((request_in->commandDescBaseAddrLo + 1589 (request_in->responseUPIULength << 2)) & 0xffffffff); 1590 1591 /**transferdone information packet filling*/ 1592 UFSDevice[lun_id]->transferInfo.responseStartAddr = response_addr; 1593 UFSDevice[lun_id]->transferInfo.reqPos = req_pos; 1594 UFSDevice[lun_id]->transferInfo.size = finalsize; 1595 UFSDevice[lun_id]->transferInfo.address = finaladdress; 1596 UFSDevice[lun_id]->transferInfo.destination = reinterpret_cast<uint8_t*> 1597 (UFSDevice[lun_id]->SCSIInfoQueue.front().RequestIn); 1598 UFSDevice[lun_id]->transferInfo.finished = true; 1599 UFSDevice[lun_id]->transferInfo.lunID = request_out_datain.LUN; 1600 1601 /** 1602 * In this part the data that needs to be transfered will be initiated 1603 * and the chain of DMA (and potentially) disk transactions will be 1604 * started. 1605 */ 1606 if (request_out_datain.expectMore == 0x01) { 1607 /**write transfer*/ 1608 manageWriteTransfer(request_out_datain.LUN, request_out_datain.offset, 1609 length, sglist); 1610 1611 } else if (request_out_datain.expectMore == 0x02) { 1612 /**read transfer*/ 1613 manageReadTransfer(request_out_datain.msgSize, request_out_datain.LUN, 1614 request_out_datain.offset, length, sglist); 1615 1616 } else { 1617 /**not disk related transfer, SCSI maintanance*/ 1618 uint32_t count = 0; 1619 uint32_t size_accum = 0; 1620 DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n", 1621 request_out_datain.msgSize); 1622 1623 /**Transport the SCSI reponse data according to the SG list*/ 1624 while ((length > count) && size_accum 1625 < (request_out_datain.msgSize - 1) && 1626 (request_out_datain.msgSize != 0x00)) { 1627 Addr SCSI_start = sglist[count].upperAddr; 1628 SCSI_start = (SCSI_start << 32) | 1629 (sglist[count].baseAddr & 0xFFFFFFFF); 1630 DPRINTF(UFSHostDevice, "Data DMA start: 0x%8x\n", SCSI_start); 1631 DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n", 1632 (sglist[count].size + 1)); 1633 /** 1634 * safetynet; it has been shown that sg list may be optimistic in 1635 * the amount of data allocated, which can potentially lead to 1636 * some garbage data being send over. Hence this construction 1637 * that finds the least amount of data that needs to be 1638 * transfered. 1639 */ 1640 uint32_t size_to_send = sglist[count].size + 1; 1641 1642 if (request_out_datain.msgSize < (size_to_send + size_accum)) 1643 size_to_send = request_out_datain.msgSize - size_accum; 1644 1645 readDevice(false, SCSI_start, size_to_send, 1646 reinterpret_cast<uint8_t*> 1647 (&(request_out_datain.message.dataMsg[size_accum])), 1648 false, NULL); 1649 1650 size_accum += size_to_send; 1651 DPRINTF(UFSHostDevice, "Total remaining: 0x%8x,accumulated so far" 1652 " : 0x%8x\n", (request_out_datain.msgSize - size_accum), 1653 size_accum); 1654 1655 ++count; 1656 DPRINTF(UFSHostDevice, "Transfer #: %d\n", count); 1657 } 1658 1659 /**Go to the next stage of the answering process*/ 1660 transferDone(response_addr, req_pos, UFSDevice[lun_id]-> 1661 transferInfo.requestOut, finalsize, finaladdress, 1662 reinterpret_cast<uint8_t*>(request_in), true, lun_id); 1663 } 1664 1665 DPRINTF(UFSHostDevice, "SCSI resume done\n"); 1666} 1667 1668/** 1669 * Find finished transfer. Callback function. One of the LUNs is done with 1670 * the disk transfer and reports back to the controller. This function finds 1671 * out who it was, and calls transferDone. 1672 */ 1673void 1674UFSHostDevice::LUNSignal() 1675{ 1676 uint8_t this_lun = 0; 1677 1678 //while we haven't found the right lun, keep searching 1679 while ((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedCommand()) 1680 ++this_lun; 1681 1682 if (this_lun < lunAvail) { 1683 //Clear signal. 1684 UFSDevice[this_lun]->clearSignal(); 1685 //found it; call transferDone 1686 transferDone(UFSDevice[this_lun]->transferInfo.responseStartAddr, 1687 UFSDevice[this_lun]->transferInfo.reqPos, 1688 UFSDevice[this_lun]->transferInfo.requestOut, 1689 UFSDevice[this_lun]->transferInfo.size, 1690 UFSDevice[this_lun]->transferInfo.address, 1691 UFSDevice[this_lun]->transferInfo.destination, 1692 UFSDevice[this_lun]->transferInfo.finished, 1693 UFSDevice[this_lun]->transferInfo.lunID); 1694 } 1695 1696 else 1697 panic("no LUN finished in tick %d\n", curTick()); 1698} 1699 1700/** 1701 * Transfer done. When the data transfer is done, this function ensures 1702 * that the application is notified. 1703 */ 1704 1705void 1706UFSHostDevice::transferDone(Addr responseStartAddr, uint32_t req_pos, 1707 struct UTPUPIURSP request_out, uint32_t size, 1708 Addr address, uint8_t* destination, 1709 bool finished, uint32_t lun_id) 1710{ 1711 /**Test whether SCSI queue hasn't popped prematurely*/ 1712 if (UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1713 panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id, 1714 UFSHCIMem.TRUTRLDBR); 1715 1716 DPRINTF(UFSHostDevice, "DMA start: 0x%8x; DMA size: 0x%8x\n", 1717 responseStartAddr, sizeof(request_out)); 1718 1719 struct transferStart lastinfo; 1720 lastinfo.mask = req_pos; 1721 lastinfo.done = finished; 1722 lastinfo.address = address; 1723 lastinfo.size = size; 1724 lastinfo.destination = reinterpret_cast<UTPTransferReqDesc*> 1725 (destination); 1726 lastinfo.lun_id = lun_id; 1727 1728 transferEnd.push_back(lastinfo); 1729 1730 DPRINTF(UFSHostDevice, "Transfer done start\n"); 1731 1732 readDevice(false, responseStartAddr, sizeof(request_out), 1733 reinterpret_cast<uint8_t*> 1734 (&(UFSDevice[lun_id]->transferInfo.requestOut)), 1735 true, &UTPEvent); 1736} 1737 1738/** 1739 * finalUTP. Second part of the transfer done event. 1740 * this sends the final response: the UTP response. After this transaction 1741 * the doorbell shall be cleared, and the interupt shall be set. 1742 */ 1743 1744void 1745UFSHostDevice::finalUTP() 1746{ 1747 uint32_t lun_id = transferEnd.front().lun_id; 1748 1749 UFSDevice[lun_id]->SCSIInfoQueue.pop_front(); 1750 DPRINTF(UFSHostDevice, "SCSIInfoQueue size: %d, lun: %d\n", 1751 UFSDevice[lun_id]->SCSIInfoQueue.size(), lun_id); 1752 1753 /**stats**/ 1754 if (UFSHCIMem.TRUTRLDBR & transferEnd.front().mask) { 1755 uint8_t count = 0; 1756 while (!(transferEnd.front().mask & (0x1 << count))) 1757 ++count; 1758 stats.transactionLatency.sample(curTick() - 1759 transactionStart[count]); 1760 } 1761 1762 /**Last message that will be transfered*/ 1763 readDevice(true, transferEnd.front().address, 1764 transferEnd.front().size, reinterpret_cast<uint8_t*> 1765 (transferEnd.front().destination), true, NULL); 1766 1767 /**clean and ensure that the tracker is updated*/ 1768 transferTrack &= ~(transferEnd.front().mask); 1769 --activeDoorbells; 1770 ++pendingDoorbells; 1771 garbage.push_back(transferEnd.front().destination); 1772 transferEnd.pop_front(); 1773 DPRINTF(UFSHostDevice, "UTP handled\n"); 1774 1775 /**stats**/ 1776 stats.averageDoorbell = stats.maxDoorbell.value(); 1777 1778 DPRINTF(UFSHostDevice, "activeDoorbells: %d, pendingDoorbells: %d," 1779 " garbage: %d, TransferEvent: %d\n", activeDoorbells, 1780 pendingDoorbells, garbage.size(), transferEventQueue.size()); 1781 1782 /**This is the moment that the device is available again*/ 1783 if (!UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1784 SCSIResume(lun_id); 1785} 1786 1787/** 1788 * Read done handling function, is only initiated at the end of a transaction 1789 */ 1790void 1791UFSHostDevice::readDone() 1792{ 1793 DPRINTF(UFSHostDevice, "Read done start\n"); 1794 --readPendingNum; 1795 1796 /**Garbage collection; sort out the allocated UTP descriptor*/ 1797 if (garbage.size() > 0) { 1798 delete garbage.front(); 1799 garbage.pop_front(); 1800 } 1801 1802 /**done, generate interrupt if we havent got one already*/ 1803 if (!(UFSHCIMem.ORInterruptStatus & 0x01)) { 1804 UFSHCIMem.ORInterruptStatus |= UTPTransferREQCOMPL; 1805 generateInterrupt(); 1806 } 1807 1808 1809 if (!readDoneEvent.empty()) { 1810 readDoneEvent.pop_front(); 1811 } 1812} 1813 1814/** 1815 * set interrupt and sort out the doorbell register. 1816 */ 1817 1818void 1819UFSHostDevice::generateInterrupt() 1820{ 1821 /**just to keep track of the transactions*/ 1822 countInt++; 1823 1824 /**step5 clear doorbell*/ 1825 UFSHCIMem.TRUTRLDBR &= transferTrack; 1826 pendingDoorbells = 0; 1827 DPRINTF(UFSHostDevice, "Clear doorbell %X\n", UFSHCIMem.TRUTRLDBR); 1828 1829 checkDrain(); 1830 1831 /**step6 raise interrupt*/ 1832 gic->sendInt(intNum); 1833 DPRINTF(UFSHostDevice, "Send interrupt @ transaction: 0x%8x!\n", 1834 countInt); 1835} 1836 1837/** 1838 * Clear interrupt 1839 */ 1840 1841void 1842UFSHostDevice::clearInterrupt() 1843{ 1844 gic->clearInt(intNum); 1845 DPRINTF(UFSHostDevice, "Clear interrupt: 0x%8x!\n", countInt); 1846 1847 checkDrain(); 1848 1849 if (!(UFSHCIMem.TRUTRLDBR)) { 1850 idlePhaseStart = curTick(); 1851 } 1852 /**end of a transaction*/ 1853} 1854 1855/** 1856 * Important to understand about the transfer flow: 1857 * We have basically three stages, The "system memory" stage, the "device 1858 * buffer" stage and the "disk" stage. In this model we assume an infinite 1859 * buffer, or a buffer that is big enough to store all the data in the 1860 * biggest transaction. Between the three stages are two queues. Those queues 1861 * store the messages to simulate their transaction from one stage to the 1862 * next. The manage{Action} function fills up one of the queues and triggers 1863 * the first event, which causes a chain reaction of events executed once 1864 * they pass through their queues. For a write action the stages are ordered 1865 * "system memory", "device buffer" and "disk", whereas the read transfers 1866 * happen "disk", "device buffer" and "system memory". The dma action in the 1867 * dma device is written from a bus perspective whereas this model is written 1868 * from a device perspective. To avoid confusion, the translation between the 1869 * two has been made in the writeDevice and readDevice funtions. 1870 */ 1871 1872 1873/** 1874 * Dma transaction function: write device. Note that the dma action is 1875 * from a device perspective, while this function is from an initiator 1876 * perspective 1877 */ 1878 1879void 1880UFSHostDevice::writeDevice(Event* additional_action, bool toDisk, Addr 1881 start, int size, uint8_t* destination, uint64_t 1882 SCSIDiskOffset, uint32_t lun_id) 1883{ 1884 DPRINTF(UFSHostDevice, "Write transaction Start: 0x%8x; Size: %d\n", 1885 start, size); 1886 1887 /**check whether transfer is all the way to the flash*/ 1888 if (toDisk) { 1889 ++writePendingNum; 1890 1891 while (!writeDoneEvent.empty() && (writeDoneEvent.front().when() 1892 < curTick())) 1893 writeDoneEvent.pop_front(); 1894 1895 writeDoneEvent.push_back( 1896 EventFunctionWrapper([this]{ writeDone(); }, 1897 name())); 1898 assert(!writeDoneEvent.back().scheduled()); 1899 1900 /**destination is an offset here since we are writing to a disk*/ 1901 struct transferInfo new_transfer; 1902 new_transfer.offset = SCSIDiskOffset; 1903 new_transfer.size = size; 1904 new_transfer.lunID = lun_id; 1905 new_transfer.filePointer = 0; 1906 SSDWriteinfo.push_back(new_transfer); 1907 1908 /**allocate appropriate buffer*/ 1909 SSDWriteinfo.back().buffer.resize(size); 1910 1911 /**transaction*/ 1912 dmaPort.dmaAction(MemCmd::ReadReq, start, size, 1913 &writeDoneEvent.back(), 1914 &SSDWriteinfo.back().buffer[0], 0); 1915 //yes, a readreq at a write device function is correct. 1916 DPRINTF(UFSHostDevice, "Write to disk scheduled\n"); 1917 1918 } else { 1919 assert(!additional_action->scheduled()); 1920 dmaPort.dmaAction(MemCmd::ReadReq, start, size, 1921 additional_action, destination, 0); 1922 DPRINTF(UFSHostDevice, "Write scheduled\n"); 1923 } 1924} 1925 1926/** 1927 * Manage write transfer. Manages correct transfer flow and makes sure that 1928 * the queues are filled on time 1929 */ 1930 1931void 1932UFSHostDevice::manageWriteTransfer(uint8_t LUN, uint64_t offset, uint32_t 1933 sg_table_length, struct UFSHCDSGEntry* 1934 sglist) 1935{ 1936 struct writeToDiskBurst next_packet; 1937 1938 next_packet.SCSIDiskOffset = offset; 1939 1940 UFSDevice[LUN]->setTotalWrite(sg_table_length); 1941 1942 /** 1943 * Break-up the transactions into actions defined by the scatter gather 1944 * list. 1945 */ 1946 for (uint32_t count = 0; count < sg_table_length; count++) { 1947 next_packet.start = sglist[count].upperAddr; 1948 next_packet.start = (next_packet.start << 32) | 1949 (sglist[count].baseAddr & 0xFFFFFFFF); 1950 next_packet.LUN = LUN; 1951 DPRINTF(UFSHostDevice, "Write data DMA start: 0x%8x\n", 1952 next_packet.start); 1953 DPRINTF(UFSHostDevice, "Write data DMA size: 0x%8x\n", 1954 (sglist[count].size + 1)); 1955 assert(sglist[count].size > 0); 1956 1957 if (count != 0) 1958 next_packet.SCSIDiskOffset = next_packet.SCSIDiskOffset + 1959 (sglist[count - 1].size + 1); 1960 1961 next_packet.size = sglist[count].size + 1; 1962 1963 /**If the queue is empty, the transaction should be initiated*/ 1964 if (dmaWriteInfo.empty()) 1965 writeDevice(NULL, true, next_packet.start, next_packet.size, 1966 NULL, next_packet.SCSIDiskOffset, next_packet.LUN); 1967 else 1968 DPRINTF(UFSHostDevice, "Write not initiated queue: %d\n", 1969 dmaWriteInfo.size()); 1970 1971 dmaWriteInfo.push_back(next_packet); 1972 DPRINTF(UFSHostDevice, "Write Location: 0x%8x\n", 1973 next_packet.SCSIDiskOffset); 1974 1975 DPRINTF(UFSHostDevice, "Write transfer #: 0x%8x\n", count + 1); 1976 1977 /** stats **/ 1978 stats.totalWrittenSSD += (sglist[count].size + 1); 1979 } 1980 1981 /**stats**/ 1982 ++stats.totalWriteUFSTransactions; 1983} 1984 1985/** 1986 * Write done handling function. Is only initiated when the flash is directly 1987 * approached 1988 */ 1989 1990void 1991UFSHostDevice::writeDone() 1992{ 1993 /**DMA is done, information no longer needed*/ 1994 assert(dmaWriteInfo.size() > 0); 1995 dmaWriteInfo.pop_front(); 1996 assert(SSDWriteinfo.size() > 0); 1997 uint32_t lun = SSDWriteinfo.front().lunID; 1998 1999 /**If there is nothing on the way, we need to start the events*/ 2000 DPRINTF(UFSHostDevice, "Write done entered, queue: %d\n", 2001 UFSDevice[lun]->SSDWriteDoneInfo.size()); 2002 /**Write the disk*/ 2003 UFSDevice[lun]->writeFlash(&SSDWriteinfo.front().buffer[0], 2004 SSDWriteinfo.front().offset, 2005 SSDWriteinfo.front().size); 2006 2007 /** 2008 * Move to the second queue, enter the logic unit 2009 * This is where the disk is approached and the flash transaction is 2010 * handled SSDWriteDone will take care of the timing 2011 */ 2012 UFSDevice[lun]->SSDWriteDoneInfo.push_back(SSDWriteinfo.front()); 2013 SSDWriteinfo.pop_front(); 2014 2015 --writePendingNum; 2016 /**so far, only the DMA part has been handled, lets do the disk delay*/ 2017 UFSDevice[lun]->SSDWriteStart(); 2018 2019 /** stats **/ 2020 stats.currentWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size(); 2021 stats.averageWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size(); 2022 ++stats.totalWriteDiskTransactions; 2023 2024 /**initiate the next dma action (if any)*/ 2025 if (!dmaWriteInfo.empty()) 2026 writeDevice(NULL, true, dmaWriteInfo.front().start, 2027 dmaWriteInfo.front().size, NULL, 2028 dmaWriteInfo.front().SCSIDiskOffset, 2029 dmaWriteInfo.front().LUN); 2030 DPRINTF(UFSHostDevice, "Write done end\n"); 2031} 2032 2033/** 2034 * SSD write start. Starts the write action in the timing model 2035 */ 2036void 2037UFSHostDevice::UFSSCSIDevice::SSDWriteStart() 2038{ 2039 assert(SSDWriteDoneInfo.size() > 0); 2040 flashDevice->writeMemory( 2041 SSDWriteDoneInfo.front().offset, 2042 SSDWriteDoneInfo.front().size, memWriteCallback); 2043 2044 SSDWriteDoneInfo.pop_front(); 2045 2046 DPRINTF(UFSHostDevice, "Write is started; left in queue: %d\n", 2047 SSDWriteDoneInfo.size()); 2048} 2049 2050 2051/** 2052 * SSDisk write done 2053 */ 2054 2055void 2056UFSHostDevice::UFSSCSIDevice::SSDWriteDone() 2057{ 2058 DPRINTF(UFSHostDevice, "Write disk, aiming for %d messages, %d so far\n", 2059 totalWrite, amountOfWriteTransfers); 2060 2061 //we have done one extra transfer 2062 ++amountOfWriteTransfers; 2063 2064 /**test whether call was correct*/ 2065 assert(totalWrite >= amountOfWriteTransfers && totalWrite != 0); 2066 2067 /**are we there yet? (did we do everything)*/ 2068 if (totalWrite == amountOfWriteTransfers) { 2069 DPRINTF(UFSHostDevice, "Write transactions finished\n"); 2070 totalWrite = 0; 2071 amountOfWriteTransfers = 0; 2072 2073 //Callback UFS Host 2074 setSignal(); 2075 signalDone->process(); 2076 } 2077 2078} 2079 2080/** 2081 * Dma transaction function: read device. Notice that the dma action is from 2082 * a device perspective, while this function is from an initiator perspective 2083 */ 2084 2085void 2086UFSHostDevice::readDevice(bool lastTransfer, Addr start, uint32_t size, 2087 uint8_t* destination, bool no_cache, Event* 2088 additional_action) 2089{ 2090 DPRINTF(UFSHostDevice, "Read start: 0x%8x; Size: %d, data[0]: 0x%8x\n", 2091 start, size, (reinterpret_cast<uint32_t *>(destination))[0]); 2092 2093 /** check wether interrupt is needed */ 2094 if (lastTransfer) { 2095 ++readPendingNum; 2096 readDoneEvent.push_back( 2097 EventFunctionWrapper([this]{ readDone(); }, 2098 name())); 2099 assert(!readDoneEvent.back().scheduled()); 2100 dmaPort.dmaAction(MemCmd::WriteReq, start, size, 2101 &readDoneEvent.back(), destination, 0); 2102 //yes, a writereq at a read device function is correct. 2103 2104 } else { 2105 if (additional_action != NULL) 2106 assert(!additional_action->scheduled()); 2107 2108 dmaPort.dmaAction(MemCmd::WriteReq, start, size, 2109 additional_action, destination, 0); 2110 2111 } 2112 2113} 2114 2115/** 2116 * Manage read transfer. Manages correct transfer flow and makes sure that 2117 * the queues are filled on time 2118 */ 2119 2120void 2121UFSHostDevice::manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t 2122 offset, uint32_t sg_table_length, 2123 struct UFSHCDSGEntry* sglist) 2124{ 2125 uint32_t size_accum = 0; 2126 2127 DPRINTF(UFSHostDevice, "Data READ size: %d\n", size); 2128 2129 /** 2130 * Break-up the transactions into actions defined by the scatter gather 2131 * list. 2132 */ 2133 for (uint32_t count = 0; count < sg_table_length; count++) { 2134 struct transferInfo new_transfer; 2135 new_transfer.offset = sglist[count].upperAddr; 2136 new_transfer.offset = (new_transfer.offset << 32) | 2137 (sglist[count].baseAddr & 0xFFFFFFFF); 2138 new_transfer.filePointer = offset + size_accum; 2139 new_transfer.size = (sglist[count].size + 1); 2140 new_transfer.lunID = LUN; 2141 2142 DPRINTF(UFSHostDevice, "Data READ start: 0x%8x; size: %d\n", 2143 new_transfer.offset, new_transfer.size); 2144 2145 UFSDevice[LUN]->SSDReadInfo.push_back(new_transfer); 2146 UFSDevice[LUN]->SSDReadInfo.back().buffer.resize(sglist[count].size 2147 + 1); 2148 2149 /** 2150 * The disk image is read here; but the action is simultated later 2151 * You can see this as the preparation stage, whereas later is the 2152 * simulation phase. 2153 */ 2154 UFSDevice[LUN]->readFlash(&UFSDevice[LUN]-> 2155 SSDReadInfo.back().buffer[0], 2156 offset + size_accum, 2157 sglist[count].size + 1); 2158 2159 size_accum += (sglist[count].size + 1); 2160 2161 DPRINTF(UFSHostDevice, "Transfer %d; Remaining: 0x%8x, Accumulated:" 2162 " 0x%8x\n", (count + 1), (size-size_accum), size_accum); 2163 2164 /** stats **/ 2165 stats.totalReadSSD += (sglist[count].size + 1); 2166 stats.currentReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size(); 2167 stats.averageReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size(); 2168 } 2169 2170 UFSDevice[LUN]->SSDReadStart(sg_table_length); 2171 2172 /** stats **/ 2173 ++stats.totalReadUFSTransactions; 2174 2175} 2176 2177 2178 2179/** 2180 * SSDisk start read; this function was created to keep the interfaces 2181 * between the layers simpler. Without this function UFSHost would need to 2182 * know about the flashdevice. 2183 */ 2184 2185void 2186UFSHostDevice::UFSSCSIDevice::SSDReadStart(uint32_t total_read) 2187{ 2188 totalRead = total_read; 2189 for (uint32_t number_handled = 0; number_handled < SSDReadInfo.size(); 2190 number_handled++) { 2191 /** 2192 * Load all the read request to the Memory device. 2193 * It will call back when done. 2194 */ 2195 flashDevice->readMemory(SSDReadInfo.front().filePointer, 2196 SSDReadInfo.front().size, memReadCallback); 2197 } 2198 2199} 2200 2201 2202/** 2203 * SSDisk read done 2204 */ 2205 2206void 2207UFSHostDevice::UFSSCSIDevice::SSDReadDone() 2208{ 2209 DPRINTF(UFSHostDevice, "SSD read done at lun %d, Aiming for %d messages," 2210 " %d so far\n", lunID, totalRead, amountOfReadTransfers); 2211 2212 if (totalRead == amountOfReadTransfers) { 2213 totalRead = 0; 2214 amountOfReadTransfers = 0; 2215 2216 /**Callback: transferdone*/ 2217 setSignal(); 2218 signalDone->process(); 2219 } 2220 2221} 2222 2223/** 2224 * Read callback, on the way from the disk to the DMA. Called by the flash 2225 * layer. Intermediate step to the host layer 2226 */ 2227void 2228UFSHostDevice::UFSSCSIDevice::readCallback() 2229{ 2230 ++amountOfReadTransfers; 2231 2232 /**Callback; make sure data is transfered upstream: 2233 * UFSHostDevice::readCallback 2234 */ 2235 setReadSignal(); 2236 deviceReadCallback->process(); 2237 2238 //Are we done yet? 2239 SSDReadDone(); 2240} 2241 2242/** 2243 * Read callback, on the way from the disk to the DMA. Called by the UFSSCSI 2244 * layer. 2245 */ 2246 2247void 2248UFSHostDevice::readCallback() 2249{ 2250 DPRINTF(UFSHostDevice, "Read Callback\n"); 2251 uint8_t this_lun = 0; 2252 2253 //while we haven't found the right lun, keep searching 2254 while ((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedRead()) 2255 ++this_lun; 2256 2257 DPRINTF(UFSHostDevice, "Found LUN %d messages pending for clean: %d\n", 2258 this_lun, SSDReadPending.size()); 2259 2260 if (this_lun < lunAvail) { 2261 //Clear signal. 2262 UFSDevice[this_lun]->clearReadSignal(); 2263 SSDReadPending.push_back(UFSDevice[this_lun]->SSDReadInfo.front()); 2264 UFSDevice[this_lun]->SSDReadInfo.pop_front(); 2265 readGarbageEventQueue.push_back( 2266 EventFunctionWrapper([this]{ readGarbage(); }, name())); 2267 2268 //make sure the queue is popped a the end of the dma transaction 2269 readDevice(false, SSDReadPending.front().offset, 2270 SSDReadPending.front().size, 2271 &SSDReadPending.front().buffer[0], false, 2272 &readGarbageEventQueue.back()); 2273 2274 /**stats*/ 2275 ++stats.totalReadDiskTransactions; 2276 } 2277 else 2278 panic("no read finished in tick %d\n", curTick()); 2279} 2280 2281/** 2282 * After a disk read DMA transfer, the structure needs to be freed. This is 2283 * done in this function. 2284 */ 2285void 2286UFSHostDevice::readGarbage() 2287{ 2288 DPRINTF(UFSHostDevice, "Clean read data, %d\n", SSDReadPending.size()); 2289 SSDReadPending.pop_front(); 2290 readGarbageEventQueue.pop_front(); 2291} 2292 2293/** 2294 * Serialize; needed to make checkpoints 2295 */ 2296 2297void 2298UFSHostDevice::serialize(CheckpointOut &cp) const 2299{ 2300 DmaDevice::serialize(cp); 2301 2302 const uint8_t* temp_HCI_mem = reinterpret_cast<const uint8_t*>(&UFSHCIMem); 2303 SERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem)); 2304 2305 uint32_t lun_avail = lunAvail; 2306 SERIALIZE_SCALAR(lun_avail); 2307} 2308 2309 2310/** 2311 * Unserialize; needed to restore from checkpoints 2312 */ 2313 2314void 2315UFSHostDevice::unserialize(CheckpointIn &cp) 2316{ 2317 DmaDevice::unserialize(cp); 2318 uint8_t* temp_HCI_mem = reinterpret_cast<uint8_t*>(&UFSHCIMem); 2319 UNSERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem)); 2320 2321 uint32_t lun_avail; 2322 UNSERIALIZE_SCALAR(lun_avail); 2323 assert(lunAvail == lun_avail); 2324} 2325 2326 2327/** 2328 * Drain; needed to enable checkpoints 2329 */ 2330 2331DrainState 2332UFSHostDevice::drain() 2333{ 2334 if (UFSHCIMem.TRUTRLDBR) { 2335 DPRINTF(UFSHostDevice, "UFSDevice is draining...\n"); 2336 return DrainState::Draining; 2337 } else { 2338 DPRINTF(UFSHostDevice, "UFSDevice drained\n"); 2339 return DrainState::Drained; 2340 } 2341} 2342 2343/** 2344 * Checkdrain; needed to enable checkpoints 2345 */ 2346 2347void 2348UFSHostDevice::checkDrain() 2349{ 2350 if (drainState() != DrainState::Draining) 2351 return; 2352 2353 if (UFSHCIMem.TRUTRLDBR) { 2354 DPRINTF(UFSHostDevice, "UFSDevice is still draining; with %d active" 2355 " doorbells\n", activeDoorbells); 2356 } else { 2357 DPRINTF(UFSHostDevice, "UFSDevice is done draining\n"); 2358 signalDrainDone(); 2359 } 2360} 2361