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 memset(&scsi_out, 0, sizeof(struct SCSIReply)); 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),
| 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 memset(&scsi_out, 0, sizeof(struct SCSIReply)); 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),
|
737 SCSIResumeEvent(this), 738 UTPEvent(this) 739{ 740 DPRINTF(UFSHostDevice, "The hostcontroller hosts %d Logic units\n", 741 lunAvail); 742 UFSDevice.resize(lunAvail); 743 744 transferDoneCallback = new MakeCallback<UFSHostDevice, 745 &UFSHostDevice::LUNSignal>(this); 746 memReadCallback = new MakeCallback<UFSHostDevice, 747 &UFSHostDevice::readCallback>(this); 748 749 for(int count = 0; count < lunAvail; count++) { 750 UFSDevice[count] = new UFSSCSIDevice(p, count, transferDoneCallback, 751 memReadCallback); 752 } 753 754 if (UFSSlots > 31) 755 warn("UFSSlots = %d, this will results in %d command slots", 756 UFSSlots, (UFSSlots & 0x1F)); 757 758 if ((UFSSlots & 0x1F) == 0) 759 fatal("Number of UFS command slots should be between 1 and 32."); 760 761 setValues(); 762} 763 764/** 765 * Create the parameters of this device 766 */ 767 768UFSHostDevice* 769UFSHostDeviceParams::create() 770{ 771 return new UFSHostDevice(this); 772} 773 774 775void 776UFSHostDevice::regStats() 777{ 778 using namespace Stats; 779 780 std::string UFSHost_name = name() + ".UFSDiskHost"; 781 782 // Register the stats 783 /** Queue lengths */ 784 stats.currentSCSIQueue 785 .name(UFSHost_name + ".currentSCSIQueue") 786 .desc("Most up to date length of the command queue") 787 .flags(none); 788 stats.currentReadSSDQueue 789 .name(UFSHost_name + ".currentReadSSDQueue") 790 .desc("Most up to date length of the read SSD queue") 791 .flags(none); 792 stats.currentWriteSSDQueue 793 .name(UFSHost_name + ".currentWriteSSDQueue") 794 .desc("Most up to date length of the write SSD queue") 795 .flags(none); 796 797 /** Amount of data read/written */ 798 stats.totalReadSSD 799 .name(UFSHost_name + ".totalReadSSD") 800 .desc("Number of bytes read from SSD") 801 .flags(none); 802 803 stats.totalWrittenSSD 804 .name(UFSHost_name + ".totalWrittenSSD") 805 .desc("Number of bytes written to SSD") 806 .flags(none); 807 808 stats.totalReadDiskTransactions 809 .name(UFSHost_name + ".totalReadDiskTransactions") 810 .desc("Number of transactions from disk") 811 .flags(none); 812 stats.totalWriteDiskTransactions 813 .name(UFSHost_name + ".totalWriteDiskTransactions") 814 .desc("Number of transactions to disk") 815 .flags(none); 816 stats.totalReadUFSTransactions 817 .name(UFSHost_name + ".totalReadUFSTransactions") 818 .desc("Number of transactions from device") 819 .flags(none); 820 stats.totalWriteUFSTransactions 821 .name(UFSHost_name + ".totalWriteUFSTransactions") 822 .desc("Number of transactions to device") 823 .flags(none); 824 825 /** Average bandwidth for reads and writes */ 826 stats.averageReadSSDBW 827 .name(UFSHost_name + ".averageReadSSDBandwidth") 828 .desc("Average read bandwidth (bytes/s)") 829 .flags(nozero); 830 831 stats.averageReadSSDBW = stats.totalReadSSD / simSeconds; 832 833 stats.averageWriteSSDBW 834 .name(UFSHost_name + ".averageWriteSSDBandwidth") 835 .desc("Average write bandwidth (bytes/s)") 836 .flags(nozero); 837 838 stats.averageWriteSSDBW = stats.totalWrittenSSD / simSeconds; 839 840 stats.averageSCSIQueue 841 .name(UFSHost_name + ".averageSCSIQueueLength") 842 .desc("Average command queue length") 843 .flags(nozero); 844 stats.averageReadSSDQueue 845 .name(UFSHost_name + ".averageReadSSDQueueLength") 846 .desc("Average read queue length") 847 .flags(nozero); 848 stats.averageWriteSSDQueue 849 .name(UFSHost_name + ".averageWriteSSDQueueLength") 850 .desc("Average write queue length") 851 .flags(nozero); 852 853 /** Number of doorbells rung*/ 854 stats.curDoorbell 855 .name(UFSHost_name + ".curDoorbell") 856 .desc("Most up to date number of doorbells used") 857 .flags(none); 858 859 stats.curDoorbell = activeDoorbells; 860 861 stats.maxDoorbell 862 .name(UFSHost_name + ".maxDoorbell") 863 .desc("Maximum number of doorbells utilized") 864 .flags(none); 865 stats.averageDoorbell 866 .name(UFSHost_name + ".averageDoorbell") 867 .desc("Average number of Doorbells used") 868 .flags(nozero); 869 870 /** Latency*/ 871 stats.transactionLatency 872 .init(100) 873 .name(UFSHost_name + ".transactionLatency") 874 .desc("Histogram of transaction times") 875 .flags(pdf); 876 877 stats.idleTimes 878 .init(100) 879 .name(UFSHost_name + ".idlePeriods") 880 .desc("Histogram of idle times") 881 .flags(pdf); 882 883} 884 885/** 886 * Register init 887 */ 888void UFSHostDevice::setValues() 889{ 890 /** 891 * The capability register is built up as follows: 892 * 31-29 RES; Testmode support; O3 delivery; 64 bit addr; 893 * 23-19 RES; 18-16 #TM Req slots; 15-5 RES;4-0 # TR slots 894 */ 895 UFSHCIMem.HCCAP = 0x06070000 | (UFSSlots & 0x1F); 896 UFSHCIMem.HCversion = 0x00010000; //version is 1.0 897 UFSHCIMem.HCHCDDID = 0xAA003C3C;// Arbitrary number 898 UFSHCIMem.HCHCPMID = 0x41524D48; //ARMH (not an official MIPI number) 899 UFSHCIMem.TRUTRLDBR = 0x00; 900 UFSHCIMem.TMUTMRLDBR = 0x00; 901 UFSHCIMem.CMDUICCMDR = 0x00; 902 // We can process CMD, TM, TR, device present 903 UFSHCIMem.ORHostControllerStatus = 0x08; 904 UFSHCIMem.TRUTRLBA = 0x00; 905 UFSHCIMem.TRUTRLBAU = 0x00; 906 UFSHCIMem.TMUTMRLBA = 0x00; 907 UFSHCIMem.TMUTMRLBAU = 0x00; 908} 909 910/** 911 * Determine address ranges 912 */ 913 914AddrRangeList 915UFSHostDevice::getAddrRanges() const 916{ 917 AddrRangeList ranges; 918 ranges.push_back(RangeSize(pioAddr, pioSize)); 919 return ranges; 920} 921 922/** 923 * UFSHCD read register. This function allows the system to read the 924 * register entries 925 */ 926 927Tick 928UFSHostDevice::read(PacketPtr pkt) 929{ 930 uint32_t data = 0; 931 932 switch (pkt->getAddr() & 0xFF) 933 { 934 935 case regControllerCapabilities: 936 data = UFSHCIMem.HCCAP; 937 break; 938 939 case regUFSVersion: 940 data = UFSHCIMem.HCversion; 941 break; 942 943 case regControllerDEVID: 944 data = UFSHCIMem.HCHCDDID; 945 break; 946 947 case regControllerPRODID: 948 data = UFSHCIMem.HCHCPMID; 949 break; 950 951 case regInterruptStatus: 952 data = UFSHCIMem.ORInterruptStatus; 953 UFSHCIMem.ORInterruptStatus = 0x00; 954 //TODO: Revise and extend 955 clearInterrupt(); 956 break; 957 958 case regInterruptEnable: 959 data = UFSHCIMem.ORInterruptEnable; 960 break; 961 962 case regControllerStatus: 963 data = UFSHCIMem.ORHostControllerStatus; 964 break; 965 966 case regControllerEnable: 967 data = UFSHCIMem.ORHostControllerEnable; 968 break; 969 970 case regUICErrorCodePHYAdapterLayer: 971 data = UFSHCIMem.ORUECPA; 972 break; 973 974 case regUICErrorCodeDataLinkLayer: 975 data = UFSHCIMem.ORUECDL; 976 break; 977 978 case regUICErrorCodeNetworkLayer: 979 data = UFSHCIMem.ORUECN; 980 break; 981 982 case regUICErrorCodeTransportLayer: 983 data = UFSHCIMem.ORUECT; 984 break; 985 986 case regUICErrorCodeDME: 987 data = UFSHCIMem.ORUECDME; 988 break; 989 990 case regUTPTransferREQINTAGGControl: 991 data = UFSHCIMem.ORUTRIACR; 992 break; 993 994 case regUTPTransferREQListBaseL: 995 data = UFSHCIMem.TRUTRLBA; 996 break; 997 998 case regUTPTransferREQListBaseH: 999 data = UFSHCIMem.TRUTRLBAU; 1000 break; 1001 1002 case regUTPTransferREQDoorbell: 1003 data = UFSHCIMem.TRUTRLDBR; 1004 break; 1005 1006 case regUTPTransferREQListClear: 1007 data = UFSHCIMem.TRUTRLCLR; 1008 break; 1009 1010 case regUTPTransferREQListRunStop: 1011 data = UFSHCIMem.TRUTRLRSR; 1012 break; 1013 1014 case regUTPTaskREQListBaseL: 1015 data = UFSHCIMem.TMUTMRLBA; 1016 break; 1017 1018 case regUTPTaskREQListBaseH: 1019 data = UFSHCIMem.TMUTMRLBAU; 1020 break; 1021 1022 case regUTPTaskREQDoorbell: 1023 data = UFSHCIMem.TMUTMRLDBR; 1024 break; 1025 1026 case regUTPTaskREQListClear: 1027 data = UFSHCIMem.TMUTMRLCLR; 1028 break; 1029 1030 case regUTPTaskREQListRunStop: 1031 data = UFSHCIMem.TMUTMRLRSR; 1032 break; 1033 1034 case regUICCommand: 1035 data = UFSHCIMem.CMDUICCMDR; 1036 break; 1037 1038 case regUICCommandArg1: 1039 data = UFSHCIMem.CMDUCMDARG1; 1040 break; 1041 1042 case regUICCommandArg2: 1043 data = UFSHCIMem.CMDUCMDARG2; 1044 break; 1045 1046 case regUICCommandArg3: 1047 data = UFSHCIMem.CMDUCMDARG3; 1048 break; 1049 1050 default: 1051 data = 0x00; 1052 break; 1053 } 1054 1055 pkt->set<uint32_t>(data); 1056 pkt->makeResponse(); 1057 return pioDelay; 1058} 1059 1060/** 1061 * UFSHCD write function. This function allows access to the writeable 1062 * registers. If any function attempts to write value to an unwriteable 1063 * register entry, then the value will not be written. 1064 */ 1065Tick 1066UFSHostDevice::write(PacketPtr pkt) 1067{ 1068 uint32_t data = 0; 1069 1070 switch (pkt->getSize()) { 1071 1072 case 1: 1073 data = pkt->get<uint8_t>(); 1074 break; 1075 1076 case 2: 1077 data = pkt->get<uint16_t>(); 1078 break; 1079 1080 case 4: 1081 data = pkt->get<uint32_t>(); 1082 break; 1083 1084 default: 1085 panic("Undefined UFSHCD controller write size!\n"); 1086 break; 1087 } 1088 1089 switch (pkt->getAddr() & 0xFF) 1090 { 1091 case regControllerCapabilities://you shall not write to this 1092 break; 1093 1094 case regUFSVersion://you shall not write to this 1095 break; 1096 1097 case regControllerDEVID://you shall not write to this 1098 break; 1099 1100 case regControllerPRODID://you shall not write to this 1101 break; 1102 1103 case regInterruptStatus://you shall not write to this 1104 break; 1105 1106 case regInterruptEnable: 1107 UFSHCIMem.ORInterruptEnable = data; 1108 break; 1109 1110 case regControllerStatus: 1111 UFSHCIMem.ORHostControllerStatus = data; 1112 break; 1113 1114 case regControllerEnable: 1115 UFSHCIMem.ORHostControllerEnable = data; 1116 break; 1117 1118 case regUICErrorCodePHYAdapterLayer: 1119 UFSHCIMem.ORUECPA = data; 1120 break; 1121 1122 case regUICErrorCodeDataLinkLayer: 1123 UFSHCIMem.ORUECDL = data; 1124 break; 1125 1126 case regUICErrorCodeNetworkLayer: 1127 UFSHCIMem.ORUECN = data; 1128 break; 1129 1130 case regUICErrorCodeTransportLayer: 1131 UFSHCIMem.ORUECT = data; 1132 break; 1133 1134 case regUICErrorCodeDME: 1135 UFSHCIMem.ORUECDME = data; 1136 break; 1137 1138 case regUTPTransferREQINTAGGControl: 1139 UFSHCIMem.ORUTRIACR = data; 1140 break; 1141 1142 case regUTPTransferREQListBaseL: 1143 UFSHCIMem.TRUTRLBA = data; 1144 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1145 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU)!= 0x00)) 1146 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1147 break; 1148 1149 case regUTPTransferREQListBaseH: 1150 UFSHCIMem.TRUTRLBAU = data; 1151 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1152 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1153 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1154 break; 1155 1156 case regUTPTransferREQDoorbell: 1157 if (!(UFSHCIMem.TRUTRLDBR) && data) 1158 stats.idleTimes.sample(curTick() - idlePhaseStart); 1159 UFSHCIMem.TRUTRLDBR |= data; 1160 requestHandler(); 1161 break; 1162 1163 case regUTPTransferREQListClear: 1164 UFSHCIMem.TRUTRLCLR = data; 1165 break; 1166 1167 case regUTPTransferREQListRunStop: 1168 UFSHCIMem.TRUTRLRSR = data; 1169 break; 1170 1171 case regUTPTaskREQListBaseL: 1172 UFSHCIMem.TMUTMRLBA = data; 1173 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1174 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1175 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1176 break; 1177 1178 case regUTPTaskREQListBaseH: 1179 UFSHCIMem.TMUTMRLBAU = data; 1180 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1181 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1182 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1183 break; 1184 1185 case regUTPTaskREQDoorbell: 1186 UFSHCIMem.TMUTMRLDBR |= data; 1187 requestHandler(); 1188 break; 1189 1190 case regUTPTaskREQListClear: 1191 UFSHCIMem.TMUTMRLCLR = data; 1192 break; 1193 1194 case regUTPTaskREQListRunStop: 1195 UFSHCIMem.TMUTMRLRSR = data; 1196 break; 1197 1198 case regUICCommand: 1199 UFSHCIMem.CMDUICCMDR = data; 1200 requestHandler(); 1201 break; 1202 1203 case regUICCommandArg1: 1204 UFSHCIMem.CMDUCMDARG1 = data; 1205 break; 1206 1207 case regUICCommandArg2: 1208 UFSHCIMem.CMDUCMDARG2 = data; 1209 break; 1210 1211 case regUICCommandArg3: 1212 UFSHCIMem.CMDUCMDARG3 = data; 1213 break; 1214 1215 default:break;//nothing happens, you try to access a register that 1216 //does not exist 1217 1218 } 1219 1220 pkt->makeResponse(); 1221 return pioDelay; 1222} 1223 1224/** 1225 * Request handler. Determines where the request comes from and initiates the 1226 * appropriate actions accordingly. 1227 */ 1228 1229void 1230UFSHostDevice::requestHandler() 1231{ 1232 Addr address = 0x00; 1233 int mask = 0x01; 1234 int size; 1235 int count = 0; 1236 struct taskStart task_info; 1237 struct transferStart transferstart_info; 1238 transferstart_info.done = 0; 1239 1240 /** 1241 * step1 determine what called us 1242 * step2 determine where to get it 1243 * Look for any request of which we where not yet aware 1244 */ 1245 while (((UFSHCIMem.CMDUICCMDR > 0x00) | 1246 ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) | 1247 ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00)) ) { 1248 1249 if (UFSHCIMem.CMDUICCMDR > 0x00) { 1250 /** 1251 * Command; general control of the Host controller. 1252 * no DMA transfer needed 1253 */ 1254 commandHandler(); 1255 UFSHCIMem.ORInterruptStatus |= UICCommandCOMPL; 1256 generateInterrupt(); 1257 UFSHCIMem.CMDUICCMDR = 0x00; 1258 return; //command, nothing more we can do 1259 1260 } else if ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) { 1261 /** 1262 * Task; flow control, meant for the device/Logic unit 1263 * DMA transfer is needed, flash will not be approached 1264 */ 1265 size = sizeof(UTPUPIUTaskReq); 1266 /**Find the position that is not handled yet*/ 1267 count = findLsbSet((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack)); 1268 address = UFSHCIMem.TMUTMRLBAU; 1269 //<-64 bit 1270 address = (count * size) + (address << 32) + 1271 UFSHCIMem.TMUTMRLBA; 1272 taskCommandTrack |= mask << count; 1273 1274 inform("UFSmodel received a task from the system; this might" 1275 " lead to untested behaviour.\n"); 1276 1277 task_info.mask = mask << count; 1278 task_info.address = address; 1279 task_info.size = size; 1280 task_info.done = UFSHCIMem.TMUTMRLDBR; 1281 taskInfo.push_back(task_info); 1282 taskEventQueue.push_back(this); 1283 writeDevice(&taskEventQueue.back(), false, address, size, 1284 reinterpret_cast<uint8_t*> 1285 (&taskInfo.back().destination), 0, 0); 1286 1287 } else if ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00) { 1288 /** 1289 * Transfer; Data transfer from or to the disk. There will be DMA 1290 * transfers, and the flash might be approached. Further 1291 * commands, are needed to specify the exact command. 1292 */ 1293 size = sizeof(UTPTransferReqDesc); 1294 /**Find the position that is not handled yet*/ 1295 count = findLsbSet((UFSHCIMem.TRUTRLDBR ^ transferTrack)); 1296 address = UFSHCIMem.TRUTRLBAU; 1297 //<-64 bit 1298 address = (count * size) + (address << 32) + UFSHCIMem.TRUTRLBA; 1299 1300 transferTrack |= mask << count; 1301 DPRINTF(UFSHostDevice, "Doorbell register: 0x%8x select #:" 1302 " 0x%8x completion info: 0x%8x\n", UFSHCIMem.TRUTRLDBR, 1303 count, transferstart_info.done); 1304 1305 transferstart_info.done = UFSHCIMem.TRUTRLDBR; 1306 1307 /**stats**/ 1308 transactionStart[count] = curTick(); //note the start time 1309 ++activeDoorbells; 1310 stats.maxDoorbell = (stats.maxDoorbell.value() < activeDoorbells) 1311 ? activeDoorbells : stats.maxDoorbell.value(); 1312 stats.averageDoorbell = stats.maxDoorbell.value(); 1313 1314 /** 1315 * step3 start transfer 1316 * step4 register information; allowing the host to respond in 1317 * the end 1318 */ 1319 transferstart_info.mask = mask << count; 1320 transferstart_info.address = address; 1321 transferstart_info.size = size; 1322 transferstart_info.done = UFSHCIMem.TRUTRLDBR; 1323 transferStartInfo.push_back(transferstart_info); 1324 1325 /**Deleted in readDone, queued in finalUTP*/ 1326 transferStartInfo.back().destination = new struct 1327 UTPTransferReqDesc; 1328 DPRINTF(UFSHostDevice, "Initial transfer start: 0x%8x\n", 1329 transferstart_info.done); 1330 transferEventQueue.push_back(this); 1331 1332 if (transferEventQueue.size() < 2) { 1333 writeDevice(&transferEventQueue.front(), false, 1334 address, size, reinterpret_cast<uint8_t*> 1335 (transferStartInfo.front().destination),0, 0); 1336 DPRINTF(UFSHostDevice, "Transfer scheduled\n"); 1337 } 1338 } 1339 } 1340} 1341 1342/** 1343 * Task start event 1344 */ 1345 1346void 1347UFSHostDevice::taskStart() 1348{ 1349 DPRINTF(UFSHostDevice, "Task start"); 1350 taskHandler(&taskInfo.front().destination, taskInfo.front().mask, 1351 taskInfo.front().address, taskInfo.front().size); 1352 taskInfo.pop_front(); 1353 taskEventQueue.pop_front(); 1354} 1355 1356/** 1357 * Transfer start event 1358 */ 1359 1360void 1361UFSHostDevice::transferStart() 1362{ 1363 DPRINTF(UFSHostDevice, "Enter transfer event\n"); 1364 transferHandler(transferStartInfo.front().destination, 1365 transferStartInfo.front().mask, 1366 transferStartInfo.front().address, 1367 transferStartInfo.front().size, 1368 transferStartInfo.front().done); 1369 1370 transferStartInfo.pop_front(); 1371 DPRINTF(UFSHostDevice, "Transfer queue size at end of event: " 1372 "0x%8x\n", transferEventQueue.size()); 1373} 1374 1375/** 1376 * Handles the commands that are given. At this point in time, not many 1377 * commands have been implemented in the driver. 1378 */ 1379 1380void 1381UFSHostDevice::commandHandler() 1382{ 1383 if (UFSHCIMem.CMDUICCMDR == 0x16) { 1384 UFSHCIMem.ORHostControllerStatus |= 0x0F;//link startup 1385 } 1386 1387} 1388 1389/** 1390 * Handles the tasks that are given. At this point in time, not many tasks 1391 * have been implemented in the driver. 1392 */ 1393 1394void 1395UFSHostDevice::taskHandler(struct UTPUPIUTaskReq* request_in, 1396 uint32_t req_pos, Addr finaladdress, uint32_t 1397 finalsize) 1398{ 1399 /** 1400 * For now, just unpack and acknowledge the task without doing anything. 1401 * TODO Implement UFS tasks. 1402 */ 1403 inform("taskHandler\n"); 1404 inform("%8x\n", request_in->header.dWord0); 1405 inform("%8x\n", request_in->header.dWord1); 1406 inform("%8x\n", request_in->header.dWord2); 1407 1408 request_in->header.dWord2 &= 0xffffff00; 1409 1410 UFSHCIMem.TMUTMRLDBR &= ~(req_pos); 1411 taskCommandTrack &= ~(req_pos); 1412 UFSHCIMem.ORInterruptStatus |= UTPTaskREQCOMPL; 1413 1414 readDevice(true, finaladdress, finalsize, reinterpret_cast<uint8_t*> 1415 (request_in), true, NULL); 1416 1417} 1418 1419/** 1420 * Obtains the SCSI command (if any) 1421 * Two possibilities: if it contains a SCSI command, then it is a usable 1422 * message; if it doesnt contain a SCSI message, then it can't be handeld 1423 * by this code. 1424 * This is the second stage of the transfer. We have the information about 1425 * where the next command can be found and what the type of command is. The 1426 * actions that are needed from the device its side are: get the information 1427 * and store the information such that we can reply. 1428 */ 1429 1430void 1431UFSHostDevice::transferHandler(struct UTPTransferReqDesc* request_in, 1432 int req_pos, Addr finaladdress, uint32_t 1433 finalsize, uint32_t done) 1434{ 1435 1436 Addr cmd_desc_addr = 0x00; 1437 1438 1439 //acknowledge handling of the message 1440 DPRINTF(UFSHostDevice, "SCSI message detected\n"); 1441 request_in->header.dWord2 &= 0xffffff00; 1442 SCSIInfo.RequestIn = request_in; 1443 SCSIInfo.reqPos = req_pos; 1444 SCSIInfo.finalAddress = finaladdress; 1445 SCSIInfo.finalSize = finalsize; 1446 SCSIInfo.destination.resize(request_in->PRDTableOffset * 4 1447 + request_in->PRDTableLength * sizeof(UFSHCDSGEntry)); 1448 SCSIInfo.done = done; 1449 1450 assert(!SCSIResumeEvent.scheduled()); 1451 /** 1452 *Get the UTP command that has the SCSI command 1453 */ 1454 cmd_desc_addr = request_in->commandDescBaseAddrHi; 1455 cmd_desc_addr = (cmd_desc_addr << 32) | 1456 (request_in->commandDescBaseAddrLo & 0xffffffff); 1457 1458 writeDevice(&SCSIResumeEvent, false, cmd_desc_addr, 1459 SCSIInfo.destination.size(), &SCSIInfo.destination[0],0, 0); 1460 1461 DPRINTF(UFSHostDevice, "SCSI scheduled\n"); 1462 1463 transferEventQueue.pop_front(); 1464} 1465 1466/** 1467 * Obtain LUN and put it in the right LUN queue. Each LUN has its own queue 1468 * of commands that need to be executed. This is the first instance where it 1469 * can be determined which Logic unit should handle the transfer. Then check 1470 * wether it should wait and queue or if it can continue. 1471 */ 1472 1473void 1474UFSHostDevice::SCSIStart() 1475{ 1476 DPRINTF(UFSHostDevice, "SCSI message on hold until ready\n"); 1477 uint32_t LUN = SCSIInfo.destination[2]; 1478 UFSDevice[LUN]->SCSIInfoQueue.push_back(SCSIInfo); 1479 1480 DPRINTF(UFSHostDevice, "SCSI queue %d has %d elements\n", LUN, 1481 UFSDevice[LUN]->SCSIInfoQueue.size()); 1482 1483 /**There are 32 doorbells, so at max there can be 32 transactions*/ 1484 if (UFSDevice[LUN]->SCSIInfoQueue.size() < 2) //LUN is available 1485 SCSIResume(LUN); 1486 1487 else if (UFSDevice[LUN]->SCSIInfoQueue.size() > 32) 1488 panic("SCSI queue is getting too big %d\n", UFSDevice[LUN]-> 1489 SCSIInfoQueue.size()); 1490 1491 /** 1492 * First transfer is done, fetch the next; 1493 * At this point, the device is busy, not the HC 1494 */ 1495 if (!transferEventQueue.empty()) { 1496 1497 /** 1498 * loading next data packet in case Another LUN 1499 * is approached in the mean time 1500 */ 1501 writeDevice(&transferEventQueue.front(), false, 1502 transferStartInfo.front().address, 1503 transferStartInfo.front().size, reinterpret_cast<uint8_t*> 1504 (transferStartInfo.front().destination), 0, 0); 1505 1506 DPRINTF(UFSHostDevice, "Transfer scheduled"); 1507 } 1508} 1509 1510/** 1511 * Handles the transfer requests that are given. 1512 * There can be three types of transfer. SCSI specific, Reads and writes 1513 * apart from the data transfer, this also generates its own reply (UPIU 1514 * response). Information for this reply is stored in transferInfo and will 1515 * be used in transferDone 1516 */ 1517 1518void 1519UFSHostDevice::SCSIResume(uint32_t lun_id) 1520{ 1521 DPRINTF(UFSHostDevice, "SCSIresume\n"); 1522 if (UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1523 panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id, 1524 UFSHCIMem.TRUTRLDBR); 1525 1526 /**old info, lets form it such that we can understand it*/ 1527 struct UTPTransferReqDesc* request_in = UFSDevice[lun_id]-> 1528 SCSIInfoQueue.front().RequestIn; 1529 1530 uint32_t req_pos = UFSDevice[lun_id]->SCSIInfoQueue.front().reqPos; 1531 1532 Addr finaladdress = UFSDevice[lun_id]->SCSIInfoQueue.front(). 1533 finalAddress; 1534 1535 uint32_t finalsize = UFSDevice[lun_id]->SCSIInfoQueue.front().finalSize; 1536 1537 uint32_t* transfercommand = reinterpret_cast<uint32_t*> 1538 (&(UFSDevice[lun_id]->SCSIInfoQueue.front().destination[0])); 1539 1540 DPRINTF(UFSHostDevice, "Task tag: 0x%8x\n", transfercommand[0]>>24); 1541 /**call logic unit to handle SCSI command*/ 1542 request_out_datain = UFSDevice[(transfercommand[0] & 0xFF0000) >> 16]-> 1543 SCSICMDHandle(transfercommand); 1544 1545 DPRINTF(UFSHostDevice, "LUN: %d\n", request_out_datain.LUN); 1546 1547 /** 1548 * build response stating that it was succesful 1549 * command completion, Logic unit number, and Task tag 1550 */ 1551 request_in->header.dWord0 = ((request_in->header.dWord0 >> 24) == 0x21) 1552 ? 0x36 : 0x21; 1553 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord0 = 1554 request_in->header.dWord0 | (request_out_datain.LUN << 8) 1555 | (transfercommand[0] & 0xFF000000); 1556 /**SCSI status reply*/ 1557 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord1 = 0x00000000 | 1558 (request_out_datain.status << 24); 1559 /**segment size + EHS length (see UFS standard ch7)*/ 1560 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord2 = 0x00000000 | 1561 ((request_out_datain.senseSize + 2) << 24) | 0x05; 1562 /**amount of data that will follow*/ 1563 UFSDevice[lun_id]->transferInfo.requestOut.senseDataLen = 1564 request_out_datain.senseSize; 1565 1566 //data 1567 for (uint8_t count = 0; count<request_out_datain.senseSize; count++) { 1568 UFSDevice[lun_id]->transferInfo.requestOut.senseData[count] = 1569 request_out_datain.senseCode[count + 1]; 1570 } 1571 1572 /* 1573 * At position defined by "request_in->PRDTableOffset" (counting 32 bit 1574 * words) in array "transfercommand" we have a scatter gather list, which 1575 * is usefull to us if we interpreted it as a UFSHCDSGEntry structure. 1576 */ 1577 struct UFSHCDSGEntry* sglist = reinterpret_cast<UFSHCDSGEntry*> 1578 (&(transfercommand[(request_in->PRDTableOffset)])); 1579 1580 uint32_t length = request_in->PRDTableLength; 1581 DPRINTF(UFSHostDevice, "# PRDT entries: %d\n", length); 1582 1583 Addr response_addr = request_in->commandDescBaseAddrHi; 1584 response_addr = (response_addr << 32) | 1585 ((request_in->commandDescBaseAddrLo + 1586 (request_in->responseUPIULength << 2)) & 0xffffffff); 1587 1588 /**transferdone information packet filling*/ 1589 UFSDevice[lun_id]->transferInfo.responseStartAddr = response_addr; 1590 UFSDevice[lun_id]->transferInfo.reqPos = req_pos; 1591 UFSDevice[lun_id]->transferInfo.size = finalsize; 1592 UFSDevice[lun_id]->transferInfo.address = finaladdress; 1593 UFSDevice[lun_id]->transferInfo.destination = reinterpret_cast<uint8_t*> 1594 (UFSDevice[lun_id]->SCSIInfoQueue.front().RequestIn); 1595 UFSDevice[lun_id]->transferInfo.finished = true; 1596 UFSDevice[lun_id]->transferInfo.lunID = request_out_datain.LUN; 1597 1598 /** 1599 * In this part the data that needs to be transfered will be initiated 1600 * and the chain of DMA (and potentially) disk transactions will be 1601 * started. 1602 */ 1603 if (request_out_datain.expectMore == 0x01) { 1604 /**write transfer*/ 1605 manageWriteTransfer(request_out_datain.LUN, request_out_datain.offset, 1606 length, sglist); 1607 1608 } else if (request_out_datain.expectMore == 0x02) { 1609 /**read transfer*/ 1610 manageReadTransfer(request_out_datain.msgSize, request_out_datain.LUN, 1611 request_out_datain.offset, length, sglist); 1612 1613 } else { 1614 /**not disk related transfer, SCSI maintanance*/ 1615 uint32_t count = 0; 1616 uint32_t size_accum = 0; 1617 DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n", 1618 request_out_datain.msgSize); 1619 1620 /**Transport the SCSI reponse data according to the SG list*/ 1621 while ((length > count) && size_accum 1622 < (request_out_datain.msgSize - 1) && 1623 (request_out_datain.msgSize != 0x00)) { 1624 Addr SCSI_start = sglist[count].upperAddr; 1625 SCSI_start = (SCSI_start << 32) | 1626 (sglist[count].baseAddr & 0xFFFFFFFF); 1627 DPRINTF(UFSHostDevice, "Data DMA start: 0x%8x\n", SCSI_start); 1628 DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n", 1629 (sglist[count].size + 1)); 1630 /** 1631 * safetynet; it has been shown that sg list may be optimistic in 1632 * the amount of data allocated, which can potentially lead to 1633 * some garbage data being send over. Hence this construction 1634 * that finds the least amount of data that needs to be 1635 * transfered. 1636 */ 1637 uint32_t size_to_send = sglist[count].size + 1; 1638 1639 if (request_out_datain.msgSize < (size_to_send + size_accum)) 1640 size_to_send = request_out_datain.msgSize - size_accum; 1641 1642 readDevice(false, SCSI_start, size_to_send, 1643 reinterpret_cast<uint8_t*> 1644 (&(request_out_datain.message.dataMsg[size_accum])), 1645 false, NULL); 1646 1647 size_accum += size_to_send; 1648 DPRINTF(UFSHostDevice, "Total remaining: 0x%8x,accumulated so far" 1649 " : 0x%8x\n", (request_out_datain.msgSize - size_accum), 1650 size_accum); 1651 1652 ++count; 1653 DPRINTF(UFSHostDevice, "Transfer #: %d\n", count); 1654 } 1655 1656 /**Go to the next stage of the answering process*/ 1657 transferDone(response_addr, req_pos, UFSDevice[lun_id]-> 1658 transferInfo.requestOut, finalsize, finaladdress, 1659 reinterpret_cast<uint8_t*>(request_in), true, lun_id); 1660 } 1661 1662 DPRINTF(UFSHostDevice, "SCSI resume done\n"); 1663} 1664 1665/** 1666 * Find finished transfer. Callback function. One of the LUNs is done with 1667 * the disk transfer and reports back to the controller. This function finds 1668 * out who it was, and calls transferDone. 1669 */ 1670void 1671UFSHostDevice::LUNSignal() 1672{ 1673 uint8_t this_lun = 0; 1674 1675 //while we haven't found the right lun, keep searching 1676 while((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedCommand()) 1677 ++this_lun; 1678 1679 if (this_lun < lunAvail) { 1680 //Clear signal. 1681 UFSDevice[this_lun]->clearSignal(); 1682 //found it; call transferDone 1683 transferDone(UFSDevice[this_lun]->transferInfo.responseStartAddr, 1684 UFSDevice[this_lun]->transferInfo.reqPos, 1685 UFSDevice[this_lun]->transferInfo.requestOut, 1686 UFSDevice[this_lun]->transferInfo.size, 1687 UFSDevice[this_lun]->transferInfo.address, 1688 UFSDevice[this_lun]->transferInfo.destination, 1689 UFSDevice[this_lun]->transferInfo.finished, 1690 UFSDevice[this_lun]->transferInfo.lunID); 1691 } 1692 1693 else 1694 panic("no LUN finished in tick %d\n", curTick()); 1695} 1696 1697/** 1698 * Transfer done. When the data transfer is done, this function ensures 1699 * that the application is notified. 1700 */ 1701 1702void 1703UFSHostDevice::transferDone(Addr responseStartAddr, uint32_t req_pos, 1704 struct UTPUPIURSP request_out, uint32_t size, 1705 Addr address, uint8_t* destination, 1706 bool finished, uint32_t lun_id) 1707{ 1708 /**Test whether SCSI queue hasn't popped prematurely*/ 1709 if (UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1710 panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id, 1711 UFSHCIMem.TRUTRLDBR); 1712 1713 DPRINTF(UFSHostDevice, "DMA start: 0x%8x; DMA size: 0x%8x\n", 1714 responseStartAddr, sizeof(request_out)); 1715 1716 struct transferStart lastinfo; 1717 lastinfo.mask = req_pos; 1718 lastinfo.done = finished; 1719 lastinfo.address = address; 1720 lastinfo.size = size; 1721 lastinfo.destination = reinterpret_cast<UTPTransferReqDesc*> 1722 (destination); 1723 lastinfo.lun_id = lun_id; 1724 1725 transferEnd.push_back(lastinfo); 1726 1727 DPRINTF(UFSHostDevice, "Transfer done start\n"); 1728 1729 readDevice(false, responseStartAddr, sizeof(request_out), 1730 reinterpret_cast<uint8_t*> 1731 (&(UFSDevice[lun_id]->transferInfo.requestOut)), 1732 true, &UTPEvent); 1733} 1734 1735/** 1736 * finalUTP. Second part of the transfer done event. 1737 * this sends the final response: the UTP response. After this transaction 1738 * the doorbell shall be cleared, and the interupt shall be set. 1739 */ 1740 1741void 1742UFSHostDevice::finalUTP() 1743{ 1744 uint32_t lun_id = transferEnd.front().lun_id; 1745 1746 UFSDevice[lun_id]->SCSIInfoQueue.pop_front(); 1747 DPRINTF(UFSHostDevice, "SCSIInfoQueue size: %d, lun: %d\n", 1748 UFSDevice[lun_id]->SCSIInfoQueue.size(), lun_id); 1749 1750 /**stats**/ 1751 if (UFSHCIMem.TRUTRLDBR & transferEnd.front().mask) { 1752 uint8_t count = 0; 1753 while (!(transferEnd.front().mask & (0x1 << count))) 1754 ++count; 1755 stats.transactionLatency.sample(curTick() - 1756 transactionStart[count]); 1757 } 1758 1759 /**Last message that will be transfered*/ 1760 readDevice(true, transferEnd.front().address, 1761 transferEnd.front().size, reinterpret_cast<uint8_t*> 1762 (transferEnd.front().destination), true, NULL); 1763 1764 /**clean and ensure that the tracker is updated*/ 1765 transferTrack &= ~(transferEnd.front().mask); 1766 --activeDoorbells; 1767 ++pendingDoorbells; 1768 garbage.push_back(transferEnd.front().destination); 1769 transferEnd.pop_front(); 1770 DPRINTF(UFSHostDevice, "UTP handled\n"); 1771 1772 /**stats**/ 1773 stats.averageDoorbell = stats.maxDoorbell.value(); 1774 1775 DPRINTF(UFSHostDevice, "activeDoorbells: %d, pendingDoorbells: %d," 1776 " garbage: %d, TransferEvent: %d\n", activeDoorbells, 1777 pendingDoorbells, garbage.size(), transferEventQueue.size()); 1778 1779 /**This is the moment that the device is available again*/ 1780 if (!UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1781 SCSIResume(lun_id); 1782} 1783 1784/** 1785 * Read done handling function, is only initiated at the end of a transaction 1786 */ 1787void 1788UFSHostDevice::readDone() 1789{ 1790 DPRINTF(UFSHostDevice, "Read done start\n"); 1791 --readPendingNum; 1792 1793 /**Garbage collection; sort out the allocated UTP descriptor*/ 1794 if (garbage.size() > 0) { 1795 delete garbage.front(); 1796 garbage.pop_front(); 1797 } 1798 1799 /**done, generate interrupt if we havent got one already*/ 1800 if(!(UFSHCIMem.ORInterruptStatus & 0x01)) { 1801 UFSHCIMem.ORInterruptStatus |= UTPTransferREQCOMPL; 1802 generateInterrupt(); 1803 } 1804 1805 1806 if(!readDoneEvent.empty()) { 1807 readDoneEvent.pop_front(); 1808 } 1809} 1810 1811/** 1812 * set interrupt and sort out the doorbell register. 1813 */ 1814 1815void 1816UFSHostDevice::generateInterrupt() 1817{ 1818 /**just to keep track of the transactions*/ 1819 countInt++; 1820 1821 /**step5 clear doorbell*/ 1822 UFSHCIMem.TRUTRLDBR &= transferTrack; 1823 pendingDoorbells = 0; 1824 DPRINTF(UFSHostDevice, "Clear doorbell %X\n", UFSHCIMem.TRUTRLDBR); 1825 1826 /**step6 raise interrupt*/ 1827 gic->sendInt(intNum); 1828 DPRINTF(UFSHostDevice, "Send interrupt @ transaction: 0x%8x!\n", 1829 countInt); 1830} 1831 1832/** 1833 * Clear interrupt 1834 */ 1835 1836void 1837UFSHostDevice::clearInterrupt() 1838{ 1839 gic->clearInt(intNum); 1840 DPRINTF(UFSHostDevice, "Clear interrupt: 0x%8x!\n", countInt); 1841 1842 if (!(UFSHCIMem.TRUTRLDBR)) { 1843 idlePhaseStart = curTick(); 1844 } 1845 /**end of a transaction*/ 1846} 1847 1848/** 1849 * Important to understand about the transfer flow: 1850 * We have basically three stages, The "system memory" stage, the "device 1851 * buffer" stage and the "disk" stage. In this model we assume an infinite 1852 * buffer, or a buffer that is big enough to store all the data in the 1853 * biggest transaction. Between the three stages are two queues. Those queues 1854 * store the messages to simulate their transaction from one stage to the 1855 * next. The manage{Action} function fills up one of the queues and triggers 1856 * the first event, which causes a chain reaction of events executed once 1857 * they pass through their queues. For a write action the stages are ordered 1858 * "system memory", "device buffer" and "disk", whereas the read transfers 1859 * happen "disk", "device buffer" and "system memory". The dma action in the 1860 * dma device is written from a bus perspective whereas this model is written 1861 * from a device perspective. To avoid confusion, the translation between the 1862 * two has been made in the writeDevice and readDevice funtions. 1863 */ 1864 1865 1866/** 1867 * Dma transaction function: write device. Note that the dma action is 1868 * from a device perspective, while this function is from an initiator 1869 * perspective 1870 */ 1871 1872void 1873UFSHostDevice::writeDevice(Event* additional_action, bool toDisk, Addr 1874 start, int size, uint8_t* destination, uint64_t 1875 SCSIDiskOffset, uint32_t lun_id) 1876{ 1877 DPRINTF(UFSHostDevice, "Write transaction Start: 0x%8x; Size: %d\n", 1878 start, size); 1879 1880 /**check whether transfer is all the way to the flash*/ 1881 if (toDisk) { 1882 ++writePendingNum; 1883 1884 while(!writeDoneEvent.empty() && (writeDoneEvent.front().when() 1885 < curTick())) 1886 writeDoneEvent.pop_front(); 1887 1888 writeDoneEvent.push_back(this); 1889 assert(!writeDoneEvent.back().scheduled()); 1890 1891 /**destination is an offset here since we are writing to a disk*/ 1892 struct transferInfo new_transfer; 1893 new_transfer.offset = SCSIDiskOffset; 1894 new_transfer.size = size; 1895 new_transfer.lunID = lun_id; 1896 new_transfer.filePointer = 0; 1897 SSDWriteinfo.push_back(new_transfer); 1898 1899 /**allocate appropriate buffer*/ 1900 SSDWriteinfo.back().buffer.resize(size); 1901 1902 /**transaction*/ 1903 dmaPort.dmaAction(MemCmd::ReadReq, start, size, 1904 &writeDoneEvent.back(), 1905 &SSDWriteinfo.back().buffer[0], 0); 1906 //yes, a readreq at a write device function is correct. 1907 DPRINTF(UFSHostDevice, "Write to disk scheduled\n"); 1908 1909 } else { 1910 assert(!additional_action->scheduled()); 1911 dmaPort.dmaAction(MemCmd::ReadReq, start, size, 1912 additional_action, destination, 0); 1913 DPRINTF(UFSHostDevice, "Write scheduled\n"); 1914 } 1915} 1916 1917/** 1918 * Manage write transfer. Manages correct transfer flow and makes sure that 1919 * the queues are filled on time 1920 */ 1921 1922void 1923UFSHostDevice::manageWriteTransfer(uint8_t LUN, uint64_t offset, uint32_t 1924 sg_table_length, struct UFSHCDSGEntry* 1925 sglist) 1926{ 1927 struct writeToDiskBurst next_packet; 1928 1929 next_packet.SCSIDiskOffset = offset; 1930 1931 UFSDevice[LUN]->setTotalWrite(sg_table_length); 1932 1933 /** 1934 * Break-up the transactions into actions defined by the scatter gather 1935 * list. 1936 */ 1937 for (uint32_t count = 0; count < sg_table_length; count++) { 1938 next_packet.start = sglist[count].upperAddr; 1939 next_packet.start = (next_packet.start << 32) | 1940 (sglist[count].baseAddr & 0xFFFFFFFF); 1941 next_packet.LUN = LUN; 1942 DPRINTF(UFSHostDevice, "Write data DMA start: 0x%8x\n", 1943 next_packet.start); 1944 DPRINTF(UFSHostDevice, "Write data DMA size: 0x%8x\n", 1945 (sglist[count].size + 1)); 1946 assert(sglist[count].size > 0); 1947 1948 if (count != 0) 1949 next_packet.SCSIDiskOffset = next_packet.SCSIDiskOffset + 1950 (sglist[count - 1].size + 1); 1951 1952 next_packet.size = sglist[count].size + 1; 1953 1954 /**If the queue is empty, the transaction should be initiated*/ 1955 if (dmaWriteInfo.empty()) 1956 writeDevice(NULL, true, next_packet.start, next_packet.size, 1957 NULL, next_packet.SCSIDiskOffset, next_packet.LUN); 1958 else 1959 DPRINTF(UFSHostDevice, "Write not initiated queue: %d\n", 1960 dmaWriteInfo.size()); 1961 1962 dmaWriteInfo.push_back(next_packet); 1963 DPRINTF(UFSHostDevice, "Write Location: 0x%8x\n", 1964 next_packet.SCSIDiskOffset); 1965 1966 DPRINTF(UFSHostDevice, "Write transfer #: 0x%8x\n", count + 1); 1967 1968 /** stats **/ 1969 stats.totalWrittenSSD += (sglist[count].size + 1); 1970 } 1971 1972 /**stats**/ 1973 ++stats.totalWriteUFSTransactions; 1974} 1975 1976/** 1977 * Write done handling function. Is only initiated when the flash is directly 1978 * approached 1979 */ 1980 1981void 1982UFSHostDevice::writeDone() 1983{ 1984 /**DMA is done, information no longer needed*/ 1985 assert(dmaWriteInfo.size() > 0); 1986 dmaWriteInfo.pop_front(); 1987 assert(SSDWriteinfo.size() > 0); 1988 uint32_t lun = SSDWriteinfo.front().lunID; 1989 1990 /**If there is nothing on the way, we need to start the events*/ 1991 DPRINTF(UFSHostDevice, "Write done entered, queue: %d\n", 1992 UFSDevice[lun]->SSDWriteDoneInfo.size()); 1993 /**Write the disk*/ 1994 UFSDevice[lun]->writeFlash(&SSDWriteinfo.front().buffer[0], 1995 SSDWriteinfo.front().offset, 1996 SSDWriteinfo.front().size); 1997 1998 /** 1999 * Move to the second queue, enter the logic unit 2000 * This is where the disk is approached and the flash transaction is 2001 * handled SSDWriteDone will take care of the timing 2002 */ 2003 UFSDevice[lun]->SSDWriteDoneInfo.push_back(SSDWriteinfo.front()); 2004 SSDWriteinfo.pop_front(); 2005 2006 --writePendingNum; 2007 /**so far, only the DMA part has been handled, lets do the disk delay*/ 2008 UFSDevice[lun]->SSDWriteStart(); 2009 2010 /** stats **/ 2011 stats.currentWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size(); 2012 stats.averageWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size(); 2013 ++stats.totalWriteDiskTransactions; 2014 2015 /**initiate the next dma action (if any)*/ 2016 if (!dmaWriteInfo.empty()) 2017 writeDevice(NULL, true, dmaWriteInfo.front().start, 2018 dmaWriteInfo.front().size, NULL, 2019 dmaWriteInfo.front().SCSIDiskOffset, 2020 dmaWriteInfo.front().LUN); 2021 DPRINTF(UFSHostDevice, "Write done end\n"); 2022} 2023 2024/** 2025 * SSD write start. Starts the write action in the timing model 2026 */ 2027void 2028UFSHostDevice::UFSSCSIDevice::SSDWriteStart() 2029{ 2030 assert(SSDWriteDoneInfo.size() > 0); 2031 flashDevice->writeMemory( 2032 SSDWriteDoneInfo.front().offset, 2033 SSDWriteDoneInfo.front().size, memWriteCallback); 2034 2035 SSDWriteDoneInfo.pop_front(); 2036 2037 DPRINTF(UFSHostDevice, "Write is started; left in queue: %d\n", 2038 SSDWriteDoneInfo.size()); 2039} 2040 2041 2042/** 2043 * SSDisk write done 2044 */ 2045 2046void 2047UFSHostDevice::UFSSCSIDevice::SSDWriteDone() 2048{ 2049 DPRINTF(UFSHostDevice, "Write disk, aiming for %d messages, %d so far\n", 2050 totalWrite, amountOfWriteTransfers); 2051 2052 //we have done one extra transfer 2053 ++amountOfWriteTransfers; 2054 2055 /**test whether call was correct*/ 2056 assert(totalWrite >= amountOfWriteTransfers && totalWrite != 0); 2057 2058 /**are we there yet? (did we do everything)*/ 2059 if (totalWrite == amountOfWriteTransfers) { 2060 DPRINTF(UFSHostDevice, "Write transactions finished\n"); 2061 totalWrite = 0; 2062 amountOfWriteTransfers = 0; 2063 2064 //Callback UFS Host 2065 setSignal(); 2066 signalDone->process(); 2067 } 2068 2069} 2070 2071/** 2072 * Dma transaction function: read device. Notice that the dma action is from 2073 * a device perspective, while this function is from an initiator perspective 2074 */ 2075 2076void 2077UFSHostDevice::readDevice(bool lastTransfer, Addr start, uint32_t size, 2078 uint8_t* destination, bool no_cache, Event* 2079 additional_action) 2080{ 2081 DPRINTF(UFSHostDevice, "Read start: 0x%8x; Size: %d, data[0]: 0x%8x\n", 2082 start, size, (reinterpret_cast<uint32_t *>(destination))[0]); 2083 2084 /** check wether interrupt is needed */ 2085 if (lastTransfer) { 2086 ++readPendingNum; 2087 readDoneEvent.push_back(this); 2088 assert(!readDoneEvent.back().scheduled()); 2089 dmaPort.dmaAction(MemCmd::WriteReq, start, size, 2090 &readDoneEvent.back(), destination, 0); 2091 //yes, a writereq at a read device function is correct. 2092 2093 } else { 2094 if (additional_action != NULL) 2095 assert(!additional_action->scheduled()); 2096 2097 dmaPort.dmaAction(MemCmd::WriteReq, start, size, 2098 additional_action, destination, 0); 2099 2100 } 2101 2102} 2103 2104/** 2105 * Manage read transfer. Manages correct transfer flow and makes sure that 2106 * the queues are filled on time 2107 */ 2108 2109void 2110UFSHostDevice::manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t 2111 offset, uint32_t sg_table_length, 2112 struct UFSHCDSGEntry* sglist) 2113{ 2114 uint32_t size_accum = 0; 2115 2116 DPRINTF(UFSHostDevice, "Data READ size: %d\n", size); 2117 2118 /** 2119 * Break-up the transactions into actions defined by the scatter gather 2120 * list. 2121 */ 2122 for (uint32_t count = 0; count < sg_table_length; count++) { 2123 struct transferInfo new_transfer; 2124 new_transfer.offset = sglist[count].upperAddr; 2125 new_transfer.offset = (new_transfer.offset << 32) | 2126 (sglist[count].baseAddr & 0xFFFFFFFF); 2127 new_transfer.filePointer = offset + size_accum; 2128 new_transfer.size = (sglist[count].size + 1); 2129 new_transfer.lunID = LUN; 2130 2131 DPRINTF(UFSHostDevice, "Data READ start: 0x%8x; size: %d\n", 2132 new_transfer.offset, new_transfer.size); 2133 2134 UFSDevice[LUN]->SSDReadInfo.push_back(new_transfer); 2135 UFSDevice[LUN]->SSDReadInfo.back().buffer.resize(sglist[count].size 2136 + 1); 2137 2138 /** 2139 * The disk image is read here; but the action is simultated later 2140 * You can see this as the preparation stage, whereas later is the 2141 * simulation phase. 2142 */ 2143 UFSDevice[LUN]->readFlash(&UFSDevice[LUN]-> 2144 SSDReadInfo.back().buffer[0], 2145 offset + size_accum, 2146 sglist[count].size + 1); 2147 2148 size_accum += (sglist[count].size + 1); 2149 2150 DPRINTF(UFSHostDevice, "Transfer %d; Remaining: 0x%8x, Accumulated:" 2151 " 0x%8x\n", (count + 1), (size-size_accum), size_accum); 2152 2153 /** stats **/ 2154 stats.totalReadSSD += (sglist[count].size + 1); 2155 stats.currentReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size(); 2156 stats.averageReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size(); 2157 } 2158 2159 UFSDevice[LUN]->SSDReadStart(sg_table_length); 2160 2161 /** stats **/ 2162 ++stats.totalReadUFSTransactions; 2163 2164} 2165 2166 2167 2168/** 2169 * SSDisk start read; this function was created to keep the interfaces 2170 * between the layers simpler. Without this function UFSHost would need to 2171 * know about the flashdevice. 2172 */ 2173 2174void 2175UFSHostDevice::UFSSCSIDevice::SSDReadStart(uint32_t total_read) 2176{ 2177 totalRead = total_read; 2178 for (uint32_t number_handled = 0; number_handled < SSDReadInfo.size(); 2179 number_handled++) { 2180 /** 2181 * Load all the read request to the Memory device. 2182 * It will call back when done. 2183 */ 2184 flashDevice->readMemory(SSDReadInfo.front().filePointer, 2185 SSDReadInfo.front().size, memReadCallback); 2186 } 2187 2188} 2189 2190 2191/** 2192 * SSDisk read done 2193 */ 2194 2195void 2196UFSHostDevice::UFSSCSIDevice::SSDReadDone() 2197{ 2198 DPRINTF(UFSHostDevice, "SSD read done at lun %d, Aiming for %d messages," 2199 " %d so far\n", lunID, totalRead, amountOfReadTransfers); 2200 2201 if (totalRead == amountOfReadTransfers) { 2202 totalRead = 0; 2203 amountOfReadTransfers = 0; 2204 2205 /**Callback: transferdone*/ 2206 setSignal(); 2207 signalDone->process(); 2208 } 2209 2210} 2211 2212/** 2213 * Read callback, on the way from the disk to the DMA. Called by the flash 2214 * layer. Intermediate step to the host layer 2215 */ 2216void 2217UFSHostDevice::UFSSCSIDevice::readCallback() 2218{ 2219 ++amountOfReadTransfers; 2220 2221 /**Callback; make sure data is transfered upstream: 2222 * UFSHostDevice::readCallback 2223 */ 2224 setReadSignal(); 2225 deviceReadCallback->process(); 2226 2227 //Are we done yet? 2228 SSDReadDone(); 2229} 2230 2231/** 2232 * Read callback, on the way from the disk to the DMA. Called by the UFSSCSI 2233 * layer. 2234 */ 2235 2236void 2237UFSHostDevice::readCallback() 2238{ 2239 DPRINTF(UFSHostDevice, "Read Callback\n"); 2240 uint8_t this_lun = 0; 2241 2242 //while we haven't found the right lun, keep searching 2243 while((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedRead()) 2244 ++this_lun; 2245 2246 DPRINTF(UFSHostDevice, "Found LUN %d messages pending for clean: %d\n", 2247 this_lun, SSDReadPending.size()); 2248 2249 if (this_lun < lunAvail) { 2250 //Clear signal. 2251 UFSDevice[this_lun]->clearReadSignal(); 2252 SSDReadPending.push_back(UFSDevice[this_lun]->SSDReadInfo.front()); 2253 UFSDevice[this_lun]->SSDReadInfo.pop_front(); 2254 readGarbageEventQueue.push_back(this); 2255 2256 //make sure the queue is popped a the end of the dma transaction 2257 readDevice(false, SSDReadPending.front().offset, 2258 SSDReadPending.front().size, 2259 &SSDReadPending.front().buffer[0], false, 2260 &readGarbageEventQueue.back()); 2261 2262 /**stats*/ 2263 ++stats.totalReadDiskTransactions; 2264 } 2265 else 2266 panic("no read finished in tick %d\n", curTick()); 2267} 2268 2269/** 2270 * After a disk read DMA transfer, the structure needs to be freed. This is 2271 * done in this function. 2272 */ 2273void 2274UFSHostDevice::readGarbage() 2275{ 2276 DPRINTF(UFSHostDevice, "Clean read data, %d\n", SSDReadPending.size()); 2277 SSDReadPending.pop_front(); 2278 readGarbageEventQueue.pop_front(); 2279} 2280 2281/** 2282 * Serialize; needed to make checkpoints 2283 */ 2284 2285void 2286UFSHostDevice::serialize(CheckpointOut &cp) const 2287{ 2288 DmaDevice::serialize(cp); 2289 2290 const uint8_t* temp_HCI_mem = reinterpret_cast<const uint8_t*>(&UFSHCIMem); 2291 SERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem)); 2292 2293 uint32_t lun_avail = lunAvail; 2294 SERIALIZE_SCALAR(lun_avail); 2295} 2296 2297 2298/** 2299 * Unserialize; needed to restore from checkpoints 2300 */ 2301 2302void 2303UFSHostDevice::unserialize(CheckpointIn &cp) 2304{ 2305 DmaDevice::unserialize(cp); 2306 uint8_t* temp_HCI_mem = reinterpret_cast<uint8_t*>(&UFSHCIMem); 2307 UNSERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem)); 2308 2309 uint32_t lun_avail; 2310 UNSERIALIZE_SCALAR(lun_avail); 2311 assert(lunAvail == lun_avail); 2312} 2313 2314 2315/** 2316 * Drain; needed to enable checkpoints 2317 */ 2318
| 736 SCSIResumeEvent(this), 737 UTPEvent(this) 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 using namespace Stats; 778 779 std::string UFSHost_name = name() + ".UFSDiskHost"; 780 781 // Register the stats 782 /** Queue lengths */ 783 stats.currentSCSIQueue 784 .name(UFSHost_name + ".currentSCSIQueue") 785 .desc("Most up to date length of the command queue") 786 .flags(none); 787 stats.currentReadSSDQueue 788 .name(UFSHost_name + ".currentReadSSDQueue") 789 .desc("Most up to date length of the read SSD queue") 790 .flags(none); 791 stats.currentWriteSSDQueue 792 .name(UFSHost_name + ".currentWriteSSDQueue") 793 .desc("Most up to date length of the write SSD queue") 794 .flags(none); 795 796 /** Amount of data read/written */ 797 stats.totalReadSSD 798 .name(UFSHost_name + ".totalReadSSD") 799 .desc("Number of bytes read from SSD") 800 .flags(none); 801 802 stats.totalWrittenSSD 803 .name(UFSHost_name + ".totalWrittenSSD") 804 .desc("Number of bytes written to SSD") 805 .flags(none); 806 807 stats.totalReadDiskTransactions 808 .name(UFSHost_name + ".totalReadDiskTransactions") 809 .desc("Number of transactions from disk") 810 .flags(none); 811 stats.totalWriteDiskTransactions 812 .name(UFSHost_name + ".totalWriteDiskTransactions") 813 .desc("Number of transactions to disk") 814 .flags(none); 815 stats.totalReadUFSTransactions 816 .name(UFSHost_name + ".totalReadUFSTransactions") 817 .desc("Number of transactions from device") 818 .flags(none); 819 stats.totalWriteUFSTransactions 820 .name(UFSHost_name + ".totalWriteUFSTransactions") 821 .desc("Number of transactions to device") 822 .flags(none); 823 824 /** Average bandwidth for reads and writes */ 825 stats.averageReadSSDBW 826 .name(UFSHost_name + ".averageReadSSDBandwidth") 827 .desc("Average read bandwidth (bytes/s)") 828 .flags(nozero); 829 830 stats.averageReadSSDBW = stats.totalReadSSD / simSeconds; 831 832 stats.averageWriteSSDBW 833 .name(UFSHost_name + ".averageWriteSSDBandwidth") 834 .desc("Average write bandwidth (bytes/s)") 835 .flags(nozero); 836 837 stats.averageWriteSSDBW = stats.totalWrittenSSD / simSeconds; 838 839 stats.averageSCSIQueue 840 .name(UFSHost_name + ".averageSCSIQueueLength") 841 .desc("Average command queue length") 842 .flags(nozero); 843 stats.averageReadSSDQueue 844 .name(UFSHost_name + ".averageReadSSDQueueLength") 845 .desc("Average read queue length") 846 .flags(nozero); 847 stats.averageWriteSSDQueue 848 .name(UFSHost_name + ".averageWriteSSDQueueLength") 849 .desc("Average write queue length") 850 .flags(nozero); 851 852 /** Number of doorbells rung*/ 853 stats.curDoorbell 854 .name(UFSHost_name + ".curDoorbell") 855 .desc("Most up to date number of doorbells used") 856 .flags(none); 857 858 stats.curDoorbell = activeDoorbells; 859 860 stats.maxDoorbell 861 .name(UFSHost_name + ".maxDoorbell") 862 .desc("Maximum number of doorbells utilized") 863 .flags(none); 864 stats.averageDoorbell 865 .name(UFSHost_name + ".averageDoorbell") 866 .desc("Average number of Doorbells used") 867 .flags(nozero); 868 869 /** Latency*/ 870 stats.transactionLatency 871 .init(100) 872 .name(UFSHost_name + ".transactionLatency") 873 .desc("Histogram of transaction times") 874 .flags(pdf); 875 876 stats.idleTimes 877 .init(100) 878 .name(UFSHost_name + ".idlePeriods") 879 .desc("Histogram of idle times") 880 .flags(pdf); 881 882} 883 884/** 885 * Register init 886 */ 887void UFSHostDevice::setValues() 888{ 889 /** 890 * The capability register is built up as follows: 891 * 31-29 RES; Testmode support; O3 delivery; 64 bit addr; 892 * 23-19 RES; 18-16 #TM Req slots; 15-5 RES;4-0 # TR slots 893 */ 894 UFSHCIMem.HCCAP = 0x06070000 | (UFSSlots & 0x1F); 895 UFSHCIMem.HCversion = 0x00010000; //version is 1.0 896 UFSHCIMem.HCHCDDID = 0xAA003C3C;// Arbitrary number 897 UFSHCIMem.HCHCPMID = 0x41524D48; //ARMH (not an official MIPI number) 898 UFSHCIMem.TRUTRLDBR = 0x00; 899 UFSHCIMem.TMUTMRLDBR = 0x00; 900 UFSHCIMem.CMDUICCMDR = 0x00; 901 // We can process CMD, TM, TR, device present 902 UFSHCIMem.ORHostControllerStatus = 0x08; 903 UFSHCIMem.TRUTRLBA = 0x00; 904 UFSHCIMem.TRUTRLBAU = 0x00; 905 UFSHCIMem.TMUTMRLBA = 0x00; 906 UFSHCIMem.TMUTMRLBAU = 0x00; 907} 908 909/** 910 * Determine address ranges 911 */ 912 913AddrRangeList 914UFSHostDevice::getAddrRanges() const 915{ 916 AddrRangeList ranges; 917 ranges.push_back(RangeSize(pioAddr, pioSize)); 918 return ranges; 919} 920 921/** 922 * UFSHCD read register. This function allows the system to read the 923 * register entries 924 */ 925 926Tick 927UFSHostDevice::read(PacketPtr pkt) 928{ 929 uint32_t data = 0; 930 931 switch (pkt->getAddr() & 0xFF) 932 { 933 934 case regControllerCapabilities: 935 data = UFSHCIMem.HCCAP; 936 break; 937 938 case regUFSVersion: 939 data = UFSHCIMem.HCversion; 940 break; 941 942 case regControllerDEVID: 943 data = UFSHCIMem.HCHCDDID; 944 break; 945 946 case regControllerPRODID: 947 data = UFSHCIMem.HCHCPMID; 948 break; 949 950 case regInterruptStatus: 951 data = UFSHCIMem.ORInterruptStatus; 952 UFSHCIMem.ORInterruptStatus = 0x00; 953 //TODO: Revise and extend 954 clearInterrupt(); 955 break; 956 957 case regInterruptEnable: 958 data = UFSHCIMem.ORInterruptEnable; 959 break; 960 961 case regControllerStatus: 962 data = UFSHCIMem.ORHostControllerStatus; 963 break; 964 965 case regControllerEnable: 966 data = UFSHCIMem.ORHostControllerEnable; 967 break; 968 969 case regUICErrorCodePHYAdapterLayer: 970 data = UFSHCIMem.ORUECPA; 971 break; 972 973 case regUICErrorCodeDataLinkLayer: 974 data = UFSHCIMem.ORUECDL; 975 break; 976 977 case regUICErrorCodeNetworkLayer: 978 data = UFSHCIMem.ORUECN; 979 break; 980 981 case regUICErrorCodeTransportLayer: 982 data = UFSHCIMem.ORUECT; 983 break; 984 985 case regUICErrorCodeDME: 986 data = UFSHCIMem.ORUECDME; 987 break; 988 989 case regUTPTransferREQINTAGGControl: 990 data = UFSHCIMem.ORUTRIACR; 991 break; 992 993 case regUTPTransferREQListBaseL: 994 data = UFSHCIMem.TRUTRLBA; 995 break; 996 997 case regUTPTransferREQListBaseH: 998 data = UFSHCIMem.TRUTRLBAU; 999 break; 1000 1001 case regUTPTransferREQDoorbell: 1002 data = UFSHCIMem.TRUTRLDBR; 1003 break; 1004 1005 case regUTPTransferREQListClear: 1006 data = UFSHCIMem.TRUTRLCLR; 1007 break; 1008 1009 case regUTPTransferREQListRunStop: 1010 data = UFSHCIMem.TRUTRLRSR; 1011 break; 1012 1013 case regUTPTaskREQListBaseL: 1014 data = UFSHCIMem.TMUTMRLBA; 1015 break; 1016 1017 case regUTPTaskREQListBaseH: 1018 data = UFSHCIMem.TMUTMRLBAU; 1019 break; 1020 1021 case regUTPTaskREQDoorbell: 1022 data = UFSHCIMem.TMUTMRLDBR; 1023 break; 1024 1025 case regUTPTaskREQListClear: 1026 data = UFSHCIMem.TMUTMRLCLR; 1027 break; 1028 1029 case regUTPTaskREQListRunStop: 1030 data = UFSHCIMem.TMUTMRLRSR; 1031 break; 1032 1033 case regUICCommand: 1034 data = UFSHCIMem.CMDUICCMDR; 1035 break; 1036 1037 case regUICCommandArg1: 1038 data = UFSHCIMem.CMDUCMDARG1; 1039 break; 1040 1041 case regUICCommandArg2: 1042 data = UFSHCIMem.CMDUCMDARG2; 1043 break; 1044 1045 case regUICCommandArg3: 1046 data = UFSHCIMem.CMDUCMDARG3; 1047 break; 1048 1049 default: 1050 data = 0x00; 1051 break; 1052 } 1053 1054 pkt->set<uint32_t>(data); 1055 pkt->makeResponse(); 1056 return pioDelay; 1057} 1058 1059/** 1060 * UFSHCD write function. This function allows access to the writeable 1061 * registers. If any function attempts to write value to an unwriteable 1062 * register entry, then the value will not be written. 1063 */ 1064Tick 1065UFSHostDevice::write(PacketPtr pkt) 1066{ 1067 uint32_t data = 0; 1068 1069 switch (pkt->getSize()) { 1070 1071 case 1: 1072 data = pkt->get<uint8_t>(); 1073 break; 1074 1075 case 2: 1076 data = pkt->get<uint16_t>(); 1077 break; 1078 1079 case 4: 1080 data = pkt->get<uint32_t>(); 1081 break; 1082 1083 default: 1084 panic("Undefined UFSHCD controller write size!\n"); 1085 break; 1086 } 1087 1088 switch (pkt->getAddr() & 0xFF) 1089 { 1090 case regControllerCapabilities://you shall not write to this 1091 break; 1092 1093 case regUFSVersion://you shall not write to this 1094 break; 1095 1096 case regControllerDEVID://you shall not write to this 1097 break; 1098 1099 case regControllerPRODID://you shall not write to this 1100 break; 1101 1102 case regInterruptStatus://you shall not write to this 1103 break; 1104 1105 case regInterruptEnable: 1106 UFSHCIMem.ORInterruptEnable = data; 1107 break; 1108 1109 case regControllerStatus: 1110 UFSHCIMem.ORHostControllerStatus = data; 1111 break; 1112 1113 case regControllerEnable: 1114 UFSHCIMem.ORHostControllerEnable = data; 1115 break; 1116 1117 case regUICErrorCodePHYAdapterLayer: 1118 UFSHCIMem.ORUECPA = data; 1119 break; 1120 1121 case regUICErrorCodeDataLinkLayer: 1122 UFSHCIMem.ORUECDL = data; 1123 break; 1124 1125 case regUICErrorCodeNetworkLayer: 1126 UFSHCIMem.ORUECN = data; 1127 break; 1128 1129 case regUICErrorCodeTransportLayer: 1130 UFSHCIMem.ORUECT = data; 1131 break; 1132 1133 case regUICErrorCodeDME: 1134 UFSHCIMem.ORUECDME = data; 1135 break; 1136 1137 case regUTPTransferREQINTAGGControl: 1138 UFSHCIMem.ORUTRIACR = data; 1139 break; 1140 1141 case regUTPTransferREQListBaseL: 1142 UFSHCIMem.TRUTRLBA = data; 1143 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1144 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU)!= 0x00)) 1145 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1146 break; 1147 1148 case regUTPTransferREQListBaseH: 1149 UFSHCIMem.TRUTRLBAU = data; 1150 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1151 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1152 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1153 break; 1154 1155 case regUTPTransferREQDoorbell: 1156 if (!(UFSHCIMem.TRUTRLDBR) && data) 1157 stats.idleTimes.sample(curTick() - idlePhaseStart); 1158 UFSHCIMem.TRUTRLDBR |= data; 1159 requestHandler(); 1160 break; 1161 1162 case regUTPTransferREQListClear: 1163 UFSHCIMem.TRUTRLCLR = data; 1164 break; 1165 1166 case regUTPTransferREQListRunStop: 1167 UFSHCIMem.TRUTRLRSR = data; 1168 break; 1169 1170 case regUTPTaskREQListBaseL: 1171 UFSHCIMem.TMUTMRLBA = data; 1172 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1173 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1174 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1175 break; 1176 1177 case regUTPTaskREQListBaseH: 1178 UFSHCIMem.TMUTMRLBAU = data; 1179 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) && 1180 ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00)) 1181 UFSHCIMem.ORHostControllerStatus |= UICCommandReady; 1182 break; 1183 1184 case regUTPTaskREQDoorbell: 1185 UFSHCIMem.TMUTMRLDBR |= data; 1186 requestHandler(); 1187 break; 1188 1189 case regUTPTaskREQListClear: 1190 UFSHCIMem.TMUTMRLCLR = data; 1191 break; 1192 1193 case regUTPTaskREQListRunStop: 1194 UFSHCIMem.TMUTMRLRSR = data; 1195 break; 1196 1197 case regUICCommand: 1198 UFSHCIMem.CMDUICCMDR = data; 1199 requestHandler(); 1200 break; 1201 1202 case regUICCommandArg1: 1203 UFSHCIMem.CMDUCMDARG1 = data; 1204 break; 1205 1206 case regUICCommandArg2: 1207 UFSHCIMem.CMDUCMDARG2 = data; 1208 break; 1209 1210 case regUICCommandArg3: 1211 UFSHCIMem.CMDUCMDARG3 = data; 1212 break; 1213 1214 default:break;//nothing happens, you try to access a register that 1215 //does not exist 1216 1217 } 1218 1219 pkt->makeResponse(); 1220 return pioDelay; 1221} 1222 1223/** 1224 * Request handler. Determines where the request comes from and initiates the 1225 * appropriate actions accordingly. 1226 */ 1227 1228void 1229UFSHostDevice::requestHandler() 1230{ 1231 Addr address = 0x00; 1232 int mask = 0x01; 1233 int size; 1234 int count = 0; 1235 struct taskStart task_info; 1236 struct transferStart transferstart_info; 1237 transferstart_info.done = 0; 1238 1239 /** 1240 * step1 determine what called us 1241 * step2 determine where to get it 1242 * Look for any request of which we where not yet aware 1243 */ 1244 while (((UFSHCIMem.CMDUICCMDR > 0x00) | 1245 ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) | 1246 ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00)) ) { 1247 1248 if (UFSHCIMem.CMDUICCMDR > 0x00) { 1249 /** 1250 * Command; general control of the Host controller. 1251 * no DMA transfer needed 1252 */ 1253 commandHandler(); 1254 UFSHCIMem.ORInterruptStatus |= UICCommandCOMPL; 1255 generateInterrupt(); 1256 UFSHCIMem.CMDUICCMDR = 0x00; 1257 return; //command, nothing more we can do 1258 1259 } else if ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) { 1260 /** 1261 * Task; flow control, meant for the device/Logic unit 1262 * DMA transfer is needed, flash will not be approached 1263 */ 1264 size = sizeof(UTPUPIUTaskReq); 1265 /**Find the position that is not handled yet*/ 1266 count = findLsbSet((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack)); 1267 address = UFSHCIMem.TMUTMRLBAU; 1268 //<-64 bit 1269 address = (count * size) + (address << 32) + 1270 UFSHCIMem.TMUTMRLBA; 1271 taskCommandTrack |= mask << count; 1272 1273 inform("UFSmodel received a task from the system; this might" 1274 " lead to untested behaviour.\n"); 1275 1276 task_info.mask = mask << count; 1277 task_info.address = address; 1278 task_info.size = size; 1279 task_info.done = UFSHCIMem.TMUTMRLDBR; 1280 taskInfo.push_back(task_info); 1281 taskEventQueue.push_back(this); 1282 writeDevice(&taskEventQueue.back(), false, address, size, 1283 reinterpret_cast<uint8_t*> 1284 (&taskInfo.back().destination), 0, 0); 1285 1286 } else if ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00) { 1287 /** 1288 * Transfer; Data transfer from or to the disk. There will be DMA 1289 * transfers, and the flash might be approached. Further 1290 * commands, are needed to specify the exact command. 1291 */ 1292 size = sizeof(UTPTransferReqDesc); 1293 /**Find the position that is not handled yet*/ 1294 count = findLsbSet((UFSHCIMem.TRUTRLDBR ^ transferTrack)); 1295 address = UFSHCIMem.TRUTRLBAU; 1296 //<-64 bit 1297 address = (count * size) + (address << 32) + UFSHCIMem.TRUTRLBA; 1298 1299 transferTrack |= mask << count; 1300 DPRINTF(UFSHostDevice, "Doorbell register: 0x%8x select #:" 1301 " 0x%8x completion info: 0x%8x\n", UFSHCIMem.TRUTRLDBR, 1302 count, transferstart_info.done); 1303 1304 transferstart_info.done = UFSHCIMem.TRUTRLDBR; 1305 1306 /**stats**/ 1307 transactionStart[count] = curTick(); //note the start time 1308 ++activeDoorbells; 1309 stats.maxDoorbell = (stats.maxDoorbell.value() < activeDoorbells) 1310 ? activeDoorbells : stats.maxDoorbell.value(); 1311 stats.averageDoorbell = stats.maxDoorbell.value(); 1312 1313 /** 1314 * step3 start transfer 1315 * step4 register information; allowing the host to respond in 1316 * the end 1317 */ 1318 transferstart_info.mask = mask << count; 1319 transferstart_info.address = address; 1320 transferstart_info.size = size; 1321 transferstart_info.done = UFSHCIMem.TRUTRLDBR; 1322 transferStartInfo.push_back(transferstart_info); 1323 1324 /**Deleted in readDone, queued in finalUTP*/ 1325 transferStartInfo.back().destination = new struct 1326 UTPTransferReqDesc; 1327 DPRINTF(UFSHostDevice, "Initial transfer start: 0x%8x\n", 1328 transferstart_info.done); 1329 transferEventQueue.push_back(this); 1330 1331 if (transferEventQueue.size() < 2) { 1332 writeDevice(&transferEventQueue.front(), false, 1333 address, size, reinterpret_cast<uint8_t*> 1334 (transferStartInfo.front().destination),0, 0); 1335 DPRINTF(UFSHostDevice, "Transfer scheduled\n"); 1336 } 1337 } 1338 } 1339} 1340 1341/** 1342 * Task start event 1343 */ 1344 1345void 1346UFSHostDevice::taskStart() 1347{ 1348 DPRINTF(UFSHostDevice, "Task start"); 1349 taskHandler(&taskInfo.front().destination, taskInfo.front().mask, 1350 taskInfo.front().address, taskInfo.front().size); 1351 taskInfo.pop_front(); 1352 taskEventQueue.pop_front(); 1353} 1354 1355/** 1356 * Transfer start event 1357 */ 1358 1359void 1360UFSHostDevice::transferStart() 1361{ 1362 DPRINTF(UFSHostDevice, "Enter transfer event\n"); 1363 transferHandler(transferStartInfo.front().destination, 1364 transferStartInfo.front().mask, 1365 transferStartInfo.front().address, 1366 transferStartInfo.front().size, 1367 transferStartInfo.front().done); 1368 1369 transferStartInfo.pop_front(); 1370 DPRINTF(UFSHostDevice, "Transfer queue size at end of event: " 1371 "0x%8x\n", transferEventQueue.size()); 1372} 1373 1374/** 1375 * Handles the commands that are given. At this point in time, not many 1376 * commands have been implemented in the driver. 1377 */ 1378 1379void 1380UFSHostDevice::commandHandler() 1381{ 1382 if (UFSHCIMem.CMDUICCMDR == 0x16) { 1383 UFSHCIMem.ORHostControllerStatus |= 0x0F;//link startup 1384 } 1385 1386} 1387 1388/** 1389 * Handles the tasks that are given. At this point in time, not many tasks 1390 * have been implemented in the driver. 1391 */ 1392 1393void 1394UFSHostDevice::taskHandler(struct UTPUPIUTaskReq* request_in, 1395 uint32_t req_pos, Addr finaladdress, uint32_t 1396 finalsize) 1397{ 1398 /** 1399 * For now, just unpack and acknowledge the task without doing anything. 1400 * TODO Implement UFS tasks. 1401 */ 1402 inform("taskHandler\n"); 1403 inform("%8x\n", request_in->header.dWord0); 1404 inform("%8x\n", request_in->header.dWord1); 1405 inform("%8x\n", request_in->header.dWord2); 1406 1407 request_in->header.dWord2 &= 0xffffff00; 1408 1409 UFSHCIMem.TMUTMRLDBR &= ~(req_pos); 1410 taskCommandTrack &= ~(req_pos); 1411 UFSHCIMem.ORInterruptStatus |= UTPTaskREQCOMPL; 1412 1413 readDevice(true, finaladdress, finalsize, reinterpret_cast<uint8_t*> 1414 (request_in), true, NULL); 1415 1416} 1417 1418/** 1419 * Obtains the SCSI command (if any) 1420 * Two possibilities: if it contains a SCSI command, then it is a usable 1421 * message; if it doesnt contain a SCSI message, then it can't be handeld 1422 * by this code. 1423 * This is the second stage of the transfer. We have the information about 1424 * where the next command can be found and what the type of command is. The 1425 * actions that are needed from the device its side are: get the information 1426 * and store the information such that we can reply. 1427 */ 1428 1429void 1430UFSHostDevice::transferHandler(struct UTPTransferReqDesc* request_in, 1431 int req_pos, Addr finaladdress, uint32_t 1432 finalsize, uint32_t done) 1433{ 1434 1435 Addr cmd_desc_addr = 0x00; 1436 1437 1438 //acknowledge handling of the message 1439 DPRINTF(UFSHostDevice, "SCSI message detected\n"); 1440 request_in->header.dWord2 &= 0xffffff00; 1441 SCSIInfo.RequestIn = request_in; 1442 SCSIInfo.reqPos = req_pos; 1443 SCSIInfo.finalAddress = finaladdress; 1444 SCSIInfo.finalSize = finalsize; 1445 SCSIInfo.destination.resize(request_in->PRDTableOffset * 4 1446 + request_in->PRDTableLength * sizeof(UFSHCDSGEntry)); 1447 SCSIInfo.done = done; 1448 1449 assert(!SCSIResumeEvent.scheduled()); 1450 /** 1451 *Get the UTP command that has the SCSI command 1452 */ 1453 cmd_desc_addr = request_in->commandDescBaseAddrHi; 1454 cmd_desc_addr = (cmd_desc_addr << 32) | 1455 (request_in->commandDescBaseAddrLo & 0xffffffff); 1456 1457 writeDevice(&SCSIResumeEvent, false, cmd_desc_addr, 1458 SCSIInfo.destination.size(), &SCSIInfo.destination[0],0, 0); 1459 1460 DPRINTF(UFSHostDevice, "SCSI scheduled\n"); 1461 1462 transferEventQueue.pop_front(); 1463} 1464 1465/** 1466 * Obtain LUN and put it in the right LUN queue. Each LUN has its own queue 1467 * of commands that need to be executed. This is the first instance where it 1468 * can be determined which Logic unit should handle the transfer. Then check 1469 * wether it should wait and queue or if it can continue. 1470 */ 1471 1472void 1473UFSHostDevice::SCSIStart() 1474{ 1475 DPRINTF(UFSHostDevice, "SCSI message on hold until ready\n"); 1476 uint32_t LUN = SCSIInfo.destination[2]; 1477 UFSDevice[LUN]->SCSIInfoQueue.push_back(SCSIInfo); 1478 1479 DPRINTF(UFSHostDevice, "SCSI queue %d has %d elements\n", LUN, 1480 UFSDevice[LUN]->SCSIInfoQueue.size()); 1481 1482 /**There are 32 doorbells, so at max there can be 32 transactions*/ 1483 if (UFSDevice[LUN]->SCSIInfoQueue.size() < 2) //LUN is available 1484 SCSIResume(LUN); 1485 1486 else if (UFSDevice[LUN]->SCSIInfoQueue.size() > 32) 1487 panic("SCSI queue is getting too big %d\n", UFSDevice[LUN]-> 1488 SCSIInfoQueue.size()); 1489 1490 /** 1491 * First transfer is done, fetch the next; 1492 * At this point, the device is busy, not the HC 1493 */ 1494 if (!transferEventQueue.empty()) { 1495 1496 /** 1497 * loading next data packet in case Another LUN 1498 * is approached in the mean time 1499 */ 1500 writeDevice(&transferEventQueue.front(), false, 1501 transferStartInfo.front().address, 1502 transferStartInfo.front().size, reinterpret_cast<uint8_t*> 1503 (transferStartInfo.front().destination), 0, 0); 1504 1505 DPRINTF(UFSHostDevice, "Transfer scheduled"); 1506 } 1507} 1508 1509/** 1510 * Handles the transfer requests that are given. 1511 * There can be three types of transfer. SCSI specific, Reads and writes 1512 * apart from the data transfer, this also generates its own reply (UPIU 1513 * response). Information for this reply is stored in transferInfo and will 1514 * be used in transferDone 1515 */ 1516 1517void 1518UFSHostDevice::SCSIResume(uint32_t lun_id) 1519{ 1520 DPRINTF(UFSHostDevice, "SCSIresume\n"); 1521 if (UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1522 panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id, 1523 UFSHCIMem.TRUTRLDBR); 1524 1525 /**old info, lets form it such that we can understand it*/ 1526 struct UTPTransferReqDesc* request_in = UFSDevice[lun_id]-> 1527 SCSIInfoQueue.front().RequestIn; 1528 1529 uint32_t req_pos = UFSDevice[lun_id]->SCSIInfoQueue.front().reqPos; 1530 1531 Addr finaladdress = UFSDevice[lun_id]->SCSIInfoQueue.front(). 1532 finalAddress; 1533 1534 uint32_t finalsize = UFSDevice[lun_id]->SCSIInfoQueue.front().finalSize; 1535 1536 uint32_t* transfercommand = reinterpret_cast<uint32_t*> 1537 (&(UFSDevice[lun_id]->SCSIInfoQueue.front().destination[0])); 1538 1539 DPRINTF(UFSHostDevice, "Task tag: 0x%8x\n", transfercommand[0]>>24); 1540 /**call logic unit to handle SCSI command*/ 1541 request_out_datain = UFSDevice[(transfercommand[0] & 0xFF0000) >> 16]-> 1542 SCSICMDHandle(transfercommand); 1543 1544 DPRINTF(UFSHostDevice, "LUN: %d\n", request_out_datain.LUN); 1545 1546 /** 1547 * build response stating that it was succesful 1548 * command completion, Logic unit number, and Task tag 1549 */ 1550 request_in->header.dWord0 = ((request_in->header.dWord0 >> 24) == 0x21) 1551 ? 0x36 : 0x21; 1552 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord0 = 1553 request_in->header.dWord0 | (request_out_datain.LUN << 8) 1554 | (transfercommand[0] & 0xFF000000); 1555 /**SCSI status reply*/ 1556 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord1 = 0x00000000 | 1557 (request_out_datain.status << 24); 1558 /**segment size + EHS length (see UFS standard ch7)*/ 1559 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord2 = 0x00000000 | 1560 ((request_out_datain.senseSize + 2) << 24) | 0x05; 1561 /**amount of data that will follow*/ 1562 UFSDevice[lun_id]->transferInfo.requestOut.senseDataLen = 1563 request_out_datain.senseSize; 1564 1565 //data 1566 for (uint8_t count = 0; count<request_out_datain.senseSize; count++) { 1567 UFSDevice[lun_id]->transferInfo.requestOut.senseData[count] = 1568 request_out_datain.senseCode[count + 1]; 1569 } 1570 1571 /* 1572 * At position defined by "request_in->PRDTableOffset" (counting 32 bit 1573 * words) in array "transfercommand" we have a scatter gather list, which 1574 * is usefull to us if we interpreted it as a UFSHCDSGEntry structure. 1575 */ 1576 struct UFSHCDSGEntry* sglist = reinterpret_cast<UFSHCDSGEntry*> 1577 (&(transfercommand[(request_in->PRDTableOffset)])); 1578 1579 uint32_t length = request_in->PRDTableLength; 1580 DPRINTF(UFSHostDevice, "# PRDT entries: %d\n", length); 1581 1582 Addr response_addr = request_in->commandDescBaseAddrHi; 1583 response_addr = (response_addr << 32) | 1584 ((request_in->commandDescBaseAddrLo + 1585 (request_in->responseUPIULength << 2)) & 0xffffffff); 1586 1587 /**transferdone information packet filling*/ 1588 UFSDevice[lun_id]->transferInfo.responseStartAddr = response_addr; 1589 UFSDevice[lun_id]->transferInfo.reqPos = req_pos; 1590 UFSDevice[lun_id]->transferInfo.size = finalsize; 1591 UFSDevice[lun_id]->transferInfo.address = finaladdress; 1592 UFSDevice[lun_id]->transferInfo.destination = reinterpret_cast<uint8_t*> 1593 (UFSDevice[lun_id]->SCSIInfoQueue.front().RequestIn); 1594 UFSDevice[lun_id]->transferInfo.finished = true; 1595 UFSDevice[lun_id]->transferInfo.lunID = request_out_datain.LUN; 1596 1597 /** 1598 * In this part the data that needs to be transfered will be initiated 1599 * and the chain of DMA (and potentially) disk transactions will be 1600 * started. 1601 */ 1602 if (request_out_datain.expectMore == 0x01) { 1603 /**write transfer*/ 1604 manageWriteTransfer(request_out_datain.LUN, request_out_datain.offset, 1605 length, sglist); 1606 1607 } else if (request_out_datain.expectMore == 0x02) { 1608 /**read transfer*/ 1609 manageReadTransfer(request_out_datain.msgSize, request_out_datain.LUN, 1610 request_out_datain.offset, length, sglist); 1611 1612 } else { 1613 /**not disk related transfer, SCSI maintanance*/ 1614 uint32_t count = 0; 1615 uint32_t size_accum = 0; 1616 DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n", 1617 request_out_datain.msgSize); 1618 1619 /**Transport the SCSI reponse data according to the SG list*/ 1620 while ((length > count) && size_accum 1621 < (request_out_datain.msgSize - 1) && 1622 (request_out_datain.msgSize != 0x00)) { 1623 Addr SCSI_start = sglist[count].upperAddr; 1624 SCSI_start = (SCSI_start << 32) | 1625 (sglist[count].baseAddr & 0xFFFFFFFF); 1626 DPRINTF(UFSHostDevice, "Data DMA start: 0x%8x\n", SCSI_start); 1627 DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n", 1628 (sglist[count].size + 1)); 1629 /** 1630 * safetynet; it has been shown that sg list may be optimistic in 1631 * the amount of data allocated, which can potentially lead to 1632 * some garbage data being send over. Hence this construction 1633 * that finds the least amount of data that needs to be 1634 * transfered. 1635 */ 1636 uint32_t size_to_send = sglist[count].size + 1; 1637 1638 if (request_out_datain.msgSize < (size_to_send + size_accum)) 1639 size_to_send = request_out_datain.msgSize - size_accum; 1640 1641 readDevice(false, SCSI_start, size_to_send, 1642 reinterpret_cast<uint8_t*> 1643 (&(request_out_datain.message.dataMsg[size_accum])), 1644 false, NULL); 1645 1646 size_accum += size_to_send; 1647 DPRINTF(UFSHostDevice, "Total remaining: 0x%8x,accumulated so far" 1648 " : 0x%8x\n", (request_out_datain.msgSize - size_accum), 1649 size_accum); 1650 1651 ++count; 1652 DPRINTF(UFSHostDevice, "Transfer #: %d\n", count); 1653 } 1654 1655 /**Go to the next stage of the answering process*/ 1656 transferDone(response_addr, req_pos, UFSDevice[lun_id]-> 1657 transferInfo.requestOut, finalsize, finaladdress, 1658 reinterpret_cast<uint8_t*>(request_in), true, lun_id); 1659 } 1660 1661 DPRINTF(UFSHostDevice, "SCSI resume done\n"); 1662} 1663 1664/** 1665 * Find finished transfer. Callback function. One of the LUNs is done with 1666 * the disk transfer and reports back to the controller. This function finds 1667 * out who it was, and calls transferDone. 1668 */ 1669void 1670UFSHostDevice::LUNSignal() 1671{ 1672 uint8_t this_lun = 0; 1673 1674 //while we haven't found the right lun, keep searching 1675 while((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedCommand()) 1676 ++this_lun; 1677 1678 if (this_lun < lunAvail) { 1679 //Clear signal. 1680 UFSDevice[this_lun]->clearSignal(); 1681 //found it; call transferDone 1682 transferDone(UFSDevice[this_lun]->transferInfo.responseStartAddr, 1683 UFSDevice[this_lun]->transferInfo.reqPos, 1684 UFSDevice[this_lun]->transferInfo.requestOut, 1685 UFSDevice[this_lun]->transferInfo.size, 1686 UFSDevice[this_lun]->transferInfo.address, 1687 UFSDevice[this_lun]->transferInfo.destination, 1688 UFSDevice[this_lun]->transferInfo.finished, 1689 UFSDevice[this_lun]->transferInfo.lunID); 1690 } 1691 1692 else 1693 panic("no LUN finished in tick %d\n", curTick()); 1694} 1695 1696/** 1697 * Transfer done. When the data transfer is done, this function ensures 1698 * that the application is notified. 1699 */ 1700 1701void 1702UFSHostDevice::transferDone(Addr responseStartAddr, uint32_t req_pos, 1703 struct UTPUPIURSP request_out, uint32_t size, 1704 Addr address, uint8_t* destination, 1705 bool finished, uint32_t lun_id) 1706{ 1707 /**Test whether SCSI queue hasn't popped prematurely*/ 1708 if (UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1709 panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id, 1710 UFSHCIMem.TRUTRLDBR); 1711 1712 DPRINTF(UFSHostDevice, "DMA start: 0x%8x; DMA size: 0x%8x\n", 1713 responseStartAddr, sizeof(request_out)); 1714 1715 struct transferStart lastinfo; 1716 lastinfo.mask = req_pos; 1717 lastinfo.done = finished; 1718 lastinfo.address = address; 1719 lastinfo.size = size; 1720 lastinfo.destination = reinterpret_cast<UTPTransferReqDesc*> 1721 (destination); 1722 lastinfo.lun_id = lun_id; 1723 1724 transferEnd.push_back(lastinfo); 1725 1726 DPRINTF(UFSHostDevice, "Transfer done start\n"); 1727 1728 readDevice(false, responseStartAddr, sizeof(request_out), 1729 reinterpret_cast<uint8_t*> 1730 (&(UFSDevice[lun_id]->transferInfo.requestOut)), 1731 true, &UTPEvent); 1732} 1733 1734/** 1735 * finalUTP. Second part of the transfer done event. 1736 * this sends the final response: the UTP response. After this transaction 1737 * the doorbell shall be cleared, and the interupt shall be set. 1738 */ 1739 1740void 1741UFSHostDevice::finalUTP() 1742{ 1743 uint32_t lun_id = transferEnd.front().lun_id; 1744 1745 UFSDevice[lun_id]->SCSIInfoQueue.pop_front(); 1746 DPRINTF(UFSHostDevice, "SCSIInfoQueue size: %d, lun: %d\n", 1747 UFSDevice[lun_id]->SCSIInfoQueue.size(), lun_id); 1748 1749 /**stats**/ 1750 if (UFSHCIMem.TRUTRLDBR & transferEnd.front().mask) { 1751 uint8_t count = 0; 1752 while (!(transferEnd.front().mask & (0x1 << count))) 1753 ++count; 1754 stats.transactionLatency.sample(curTick() - 1755 transactionStart[count]); 1756 } 1757 1758 /**Last message that will be transfered*/ 1759 readDevice(true, transferEnd.front().address, 1760 transferEnd.front().size, reinterpret_cast<uint8_t*> 1761 (transferEnd.front().destination), true, NULL); 1762 1763 /**clean and ensure that the tracker is updated*/ 1764 transferTrack &= ~(transferEnd.front().mask); 1765 --activeDoorbells; 1766 ++pendingDoorbells; 1767 garbage.push_back(transferEnd.front().destination); 1768 transferEnd.pop_front(); 1769 DPRINTF(UFSHostDevice, "UTP handled\n"); 1770 1771 /**stats**/ 1772 stats.averageDoorbell = stats.maxDoorbell.value(); 1773 1774 DPRINTF(UFSHostDevice, "activeDoorbells: %d, pendingDoorbells: %d," 1775 " garbage: %d, TransferEvent: %d\n", activeDoorbells, 1776 pendingDoorbells, garbage.size(), transferEventQueue.size()); 1777 1778 /**This is the moment that the device is available again*/ 1779 if (!UFSDevice[lun_id]->SCSIInfoQueue.empty()) 1780 SCSIResume(lun_id); 1781} 1782 1783/** 1784 * Read done handling function, is only initiated at the end of a transaction 1785 */ 1786void 1787UFSHostDevice::readDone() 1788{ 1789 DPRINTF(UFSHostDevice, "Read done start\n"); 1790 --readPendingNum; 1791 1792 /**Garbage collection; sort out the allocated UTP descriptor*/ 1793 if (garbage.size() > 0) { 1794 delete garbage.front(); 1795 garbage.pop_front(); 1796 } 1797 1798 /**done, generate interrupt if we havent got one already*/ 1799 if(!(UFSHCIMem.ORInterruptStatus & 0x01)) { 1800 UFSHCIMem.ORInterruptStatus |= UTPTransferREQCOMPL; 1801 generateInterrupt(); 1802 } 1803 1804 1805 if(!readDoneEvent.empty()) { 1806 readDoneEvent.pop_front(); 1807 } 1808} 1809 1810/** 1811 * set interrupt and sort out the doorbell register. 1812 */ 1813 1814void 1815UFSHostDevice::generateInterrupt() 1816{ 1817 /**just to keep track of the transactions*/ 1818 countInt++; 1819 1820 /**step5 clear doorbell*/ 1821 UFSHCIMem.TRUTRLDBR &= transferTrack; 1822 pendingDoorbells = 0; 1823 DPRINTF(UFSHostDevice, "Clear doorbell %X\n", UFSHCIMem.TRUTRLDBR); 1824 1825 /**step6 raise interrupt*/ 1826 gic->sendInt(intNum); 1827 DPRINTF(UFSHostDevice, "Send interrupt @ transaction: 0x%8x!\n", 1828 countInt); 1829} 1830 1831/** 1832 * Clear interrupt 1833 */ 1834 1835void 1836UFSHostDevice::clearInterrupt() 1837{ 1838 gic->clearInt(intNum); 1839 DPRINTF(UFSHostDevice, "Clear interrupt: 0x%8x!\n", countInt); 1840 1841 if (!(UFSHCIMem.TRUTRLDBR)) { 1842 idlePhaseStart = curTick(); 1843 } 1844 /**end of a transaction*/ 1845} 1846 1847/** 1848 * Important to understand about the transfer flow: 1849 * We have basically three stages, The "system memory" stage, the "device 1850 * buffer" stage and the "disk" stage. In this model we assume an infinite 1851 * buffer, or a buffer that is big enough to store all the data in the 1852 * biggest transaction. Between the three stages are two queues. Those queues 1853 * store the messages to simulate their transaction from one stage to the 1854 * next. The manage{Action} function fills up one of the queues and triggers 1855 * the first event, which causes a chain reaction of events executed once 1856 * they pass through their queues. For a write action the stages are ordered 1857 * "system memory", "device buffer" and "disk", whereas the read transfers 1858 * happen "disk", "device buffer" and "system memory". The dma action in the 1859 * dma device is written from a bus perspective whereas this model is written 1860 * from a device perspective. To avoid confusion, the translation between the 1861 * two has been made in the writeDevice and readDevice funtions. 1862 */ 1863 1864 1865/** 1866 * Dma transaction function: write device. Note that the dma action is 1867 * from a device perspective, while this function is from an initiator 1868 * perspective 1869 */ 1870 1871void 1872UFSHostDevice::writeDevice(Event* additional_action, bool toDisk, Addr 1873 start, int size, uint8_t* destination, uint64_t 1874 SCSIDiskOffset, uint32_t lun_id) 1875{ 1876 DPRINTF(UFSHostDevice, "Write transaction Start: 0x%8x; Size: %d\n", 1877 start, size); 1878 1879 /**check whether transfer is all the way to the flash*/ 1880 if (toDisk) { 1881 ++writePendingNum; 1882 1883 while(!writeDoneEvent.empty() && (writeDoneEvent.front().when() 1884 < curTick())) 1885 writeDoneEvent.pop_front(); 1886 1887 writeDoneEvent.push_back(this); 1888 assert(!writeDoneEvent.back().scheduled()); 1889 1890 /**destination is an offset here since we are writing to a disk*/ 1891 struct transferInfo new_transfer; 1892 new_transfer.offset = SCSIDiskOffset; 1893 new_transfer.size = size; 1894 new_transfer.lunID = lun_id; 1895 new_transfer.filePointer = 0; 1896 SSDWriteinfo.push_back(new_transfer); 1897 1898 /**allocate appropriate buffer*/ 1899 SSDWriteinfo.back().buffer.resize(size); 1900 1901 /**transaction*/ 1902 dmaPort.dmaAction(MemCmd::ReadReq, start, size, 1903 &writeDoneEvent.back(), 1904 &SSDWriteinfo.back().buffer[0], 0); 1905 //yes, a readreq at a write device function is correct. 1906 DPRINTF(UFSHostDevice, "Write to disk scheduled\n"); 1907 1908 } else { 1909 assert(!additional_action->scheduled()); 1910 dmaPort.dmaAction(MemCmd::ReadReq, start, size, 1911 additional_action, destination, 0); 1912 DPRINTF(UFSHostDevice, "Write scheduled\n"); 1913 } 1914} 1915 1916/** 1917 * Manage write transfer. Manages correct transfer flow and makes sure that 1918 * the queues are filled on time 1919 */ 1920 1921void 1922UFSHostDevice::manageWriteTransfer(uint8_t LUN, uint64_t offset, uint32_t 1923 sg_table_length, struct UFSHCDSGEntry* 1924 sglist) 1925{ 1926 struct writeToDiskBurst next_packet; 1927 1928 next_packet.SCSIDiskOffset = offset; 1929 1930 UFSDevice[LUN]->setTotalWrite(sg_table_length); 1931 1932 /** 1933 * Break-up the transactions into actions defined by the scatter gather 1934 * list. 1935 */ 1936 for (uint32_t count = 0; count < sg_table_length; count++) { 1937 next_packet.start = sglist[count].upperAddr; 1938 next_packet.start = (next_packet.start << 32) | 1939 (sglist[count].baseAddr & 0xFFFFFFFF); 1940 next_packet.LUN = LUN; 1941 DPRINTF(UFSHostDevice, "Write data DMA start: 0x%8x\n", 1942 next_packet.start); 1943 DPRINTF(UFSHostDevice, "Write data DMA size: 0x%8x\n", 1944 (sglist[count].size + 1)); 1945 assert(sglist[count].size > 0); 1946 1947 if (count != 0) 1948 next_packet.SCSIDiskOffset = next_packet.SCSIDiskOffset + 1949 (sglist[count - 1].size + 1); 1950 1951 next_packet.size = sglist[count].size + 1; 1952 1953 /**If the queue is empty, the transaction should be initiated*/ 1954 if (dmaWriteInfo.empty()) 1955 writeDevice(NULL, true, next_packet.start, next_packet.size, 1956 NULL, next_packet.SCSIDiskOffset, next_packet.LUN); 1957 else 1958 DPRINTF(UFSHostDevice, "Write not initiated queue: %d\n", 1959 dmaWriteInfo.size()); 1960 1961 dmaWriteInfo.push_back(next_packet); 1962 DPRINTF(UFSHostDevice, "Write Location: 0x%8x\n", 1963 next_packet.SCSIDiskOffset); 1964 1965 DPRINTF(UFSHostDevice, "Write transfer #: 0x%8x\n", count + 1); 1966 1967 /** stats **/ 1968 stats.totalWrittenSSD += (sglist[count].size + 1); 1969 } 1970 1971 /**stats**/ 1972 ++stats.totalWriteUFSTransactions; 1973} 1974 1975/** 1976 * Write done handling function. Is only initiated when the flash is directly 1977 * approached 1978 */ 1979 1980void 1981UFSHostDevice::writeDone() 1982{ 1983 /**DMA is done, information no longer needed*/ 1984 assert(dmaWriteInfo.size() > 0); 1985 dmaWriteInfo.pop_front(); 1986 assert(SSDWriteinfo.size() > 0); 1987 uint32_t lun = SSDWriteinfo.front().lunID; 1988 1989 /**If there is nothing on the way, we need to start the events*/ 1990 DPRINTF(UFSHostDevice, "Write done entered, queue: %d\n", 1991 UFSDevice[lun]->SSDWriteDoneInfo.size()); 1992 /**Write the disk*/ 1993 UFSDevice[lun]->writeFlash(&SSDWriteinfo.front().buffer[0], 1994 SSDWriteinfo.front().offset, 1995 SSDWriteinfo.front().size); 1996 1997 /** 1998 * Move to the second queue, enter the logic unit 1999 * This is where the disk is approached and the flash transaction is 2000 * handled SSDWriteDone will take care of the timing 2001 */ 2002 UFSDevice[lun]->SSDWriteDoneInfo.push_back(SSDWriteinfo.front()); 2003 SSDWriteinfo.pop_front(); 2004 2005 --writePendingNum; 2006 /**so far, only the DMA part has been handled, lets do the disk delay*/ 2007 UFSDevice[lun]->SSDWriteStart(); 2008 2009 /** stats **/ 2010 stats.currentWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size(); 2011 stats.averageWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size(); 2012 ++stats.totalWriteDiskTransactions; 2013 2014 /**initiate the next dma action (if any)*/ 2015 if (!dmaWriteInfo.empty()) 2016 writeDevice(NULL, true, dmaWriteInfo.front().start, 2017 dmaWriteInfo.front().size, NULL, 2018 dmaWriteInfo.front().SCSIDiskOffset, 2019 dmaWriteInfo.front().LUN); 2020 DPRINTF(UFSHostDevice, "Write done end\n"); 2021} 2022 2023/** 2024 * SSD write start. Starts the write action in the timing model 2025 */ 2026void 2027UFSHostDevice::UFSSCSIDevice::SSDWriteStart() 2028{ 2029 assert(SSDWriteDoneInfo.size() > 0); 2030 flashDevice->writeMemory( 2031 SSDWriteDoneInfo.front().offset, 2032 SSDWriteDoneInfo.front().size, memWriteCallback); 2033 2034 SSDWriteDoneInfo.pop_front(); 2035 2036 DPRINTF(UFSHostDevice, "Write is started; left in queue: %d\n", 2037 SSDWriteDoneInfo.size()); 2038} 2039 2040 2041/** 2042 * SSDisk write done 2043 */ 2044 2045void 2046UFSHostDevice::UFSSCSIDevice::SSDWriteDone() 2047{ 2048 DPRINTF(UFSHostDevice, "Write disk, aiming for %d messages, %d so far\n", 2049 totalWrite, amountOfWriteTransfers); 2050 2051 //we have done one extra transfer 2052 ++amountOfWriteTransfers; 2053 2054 /**test whether call was correct*/ 2055 assert(totalWrite >= amountOfWriteTransfers && totalWrite != 0); 2056 2057 /**are we there yet? (did we do everything)*/ 2058 if (totalWrite == amountOfWriteTransfers) { 2059 DPRINTF(UFSHostDevice, "Write transactions finished\n"); 2060 totalWrite = 0; 2061 amountOfWriteTransfers = 0; 2062 2063 //Callback UFS Host 2064 setSignal(); 2065 signalDone->process(); 2066 } 2067 2068} 2069 2070/** 2071 * Dma transaction function: read device. Notice that the dma action is from 2072 * a device perspective, while this function is from an initiator perspective 2073 */ 2074 2075void 2076UFSHostDevice::readDevice(bool lastTransfer, Addr start, uint32_t size, 2077 uint8_t* destination, bool no_cache, Event* 2078 additional_action) 2079{ 2080 DPRINTF(UFSHostDevice, "Read start: 0x%8x; Size: %d, data[0]: 0x%8x\n", 2081 start, size, (reinterpret_cast<uint32_t *>(destination))[0]); 2082 2083 /** check wether interrupt is needed */ 2084 if (lastTransfer) { 2085 ++readPendingNum; 2086 readDoneEvent.push_back(this); 2087 assert(!readDoneEvent.back().scheduled()); 2088 dmaPort.dmaAction(MemCmd::WriteReq, start, size, 2089 &readDoneEvent.back(), destination, 0); 2090 //yes, a writereq at a read device function is correct. 2091 2092 } else { 2093 if (additional_action != NULL) 2094 assert(!additional_action->scheduled()); 2095 2096 dmaPort.dmaAction(MemCmd::WriteReq, start, size, 2097 additional_action, destination, 0); 2098 2099 } 2100 2101} 2102 2103/** 2104 * Manage read transfer. Manages correct transfer flow and makes sure that 2105 * the queues are filled on time 2106 */ 2107 2108void 2109UFSHostDevice::manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t 2110 offset, uint32_t sg_table_length, 2111 struct UFSHCDSGEntry* sglist) 2112{ 2113 uint32_t size_accum = 0; 2114 2115 DPRINTF(UFSHostDevice, "Data READ size: %d\n", size); 2116 2117 /** 2118 * Break-up the transactions into actions defined by the scatter gather 2119 * list. 2120 */ 2121 for (uint32_t count = 0; count < sg_table_length; count++) { 2122 struct transferInfo new_transfer; 2123 new_transfer.offset = sglist[count].upperAddr; 2124 new_transfer.offset = (new_transfer.offset << 32) | 2125 (sglist[count].baseAddr & 0xFFFFFFFF); 2126 new_transfer.filePointer = offset + size_accum; 2127 new_transfer.size = (sglist[count].size + 1); 2128 new_transfer.lunID = LUN; 2129 2130 DPRINTF(UFSHostDevice, "Data READ start: 0x%8x; size: %d\n", 2131 new_transfer.offset, new_transfer.size); 2132 2133 UFSDevice[LUN]->SSDReadInfo.push_back(new_transfer); 2134 UFSDevice[LUN]->SSDReadInfo.back().buffer.resize(sglist[count].size 2135 + 1); 2136 2137 /** 2138 * The disk image is read here; but the action is simultated later 2139 * You can see this as the preparation stage, whereas later is the 2140 * simulation phase. 2141 */ 2142 UFSDevice[LUN]->readFlash(&UFSDevice[LUN]-> 2143 SSDReadInfo.back().buffer[0], 2144 offset + size_accum, 2145 sglist[count].size + 1); 2146 2147 size_accum += (sglist[count].size + 1); 2148 2149 DPRINTF(UFSHostDevice, "Transfer %d; Remaining: 0x%8x, Accumulated:" 2150 " 0x%8x\n", (count + 1), (size-size_accum), size_accum); 2151 2152 /** stats **/ 2153 stats.totalReadSSD += (sglist[count].size + 1); 2154 stats.currentReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size(); 2155 stats.averageReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size(); 2156 } 2157 2158 UFSDevice[LUN]->SSDReadStart(sg_table_length); 2159 2160 /** stats **/ 2161 ++stats.totalReadUFSTransactions; 2162 2163} 2164 2165 2166 2167/** 2168 * SSDisk start read; this function was created to keep the interfaces 2169 * between the layers simpler. Without this function UFSHost would need to 2170 * know about the flashdevice. 2171 */ 2172 2173void 2174UFSHostDevice::UFSSCSIDevice::SSDReadStart(uint32_t total_read) 2175{ 2176 totalRead = total_read; 2177 for (uint32_t number_handled = 0; number_handled < SSDReadInfo.size(); 2178 number_handled++) { 2179 /** 2180 * Load all the read request to the Memory device. 2181 * It will call back when done. 2182 */ 2183 flashDevice->readMemory(SSDReadInfo.front().filePointer, 2184 SSDReadInfo.front().size, memReadCallback); 2185 } 2186 2187} 2188 2189 2190/** 2191 * SSDisk read done 2192 */ 2193 2194void 2195UFSHostDevice::UFSSCSIDevice::SSDReadDone() 2196{ 2197 DPRINTF(UFSHostDevice, "SSD read done at lun %d, Aiming for %d messages," 2198 " %d so far\n", lunID, totalRead, amountOfReadTransfers); 2199 2200 if (totalRead == amountOfReadTransfers) { 2201 totalRead = 0; 2202 amountOfReadTransfers = 0; 2203 2204 /**Callback: transferdone*/ 2205 setSignal(); 2206 signalDone->process(); 2207 } 2208 2209} 2210 2211/** 2212 * Read callback, on the way from the disk to the DMA. Called by the flash 2213 * layer. Intermediate step to the host layer 2214 */ 2215void 2216UFSHostDevice::UFSSCSIDevice::readCallback() 2217{ 2218 ++amountOfReadTransfers; 2219 2220 /**Callback; make sure data is transfered upstream: 2221 * UFSHostDevice::readCallback 2222 */ 2223 setReadSignal(); 2224 deviceReadCallback->process(); 2225 2226 //Are we done yet? 2227 SSDReadDone(); 2228} 2229 2230/** 2231 * Read callback, on the way from the disk to the DMA. Called by the UFSSCSI 2232 * layer. 2233 */ 2234 2235void 2236UFSHostDevice::readCallback() 2237{ 2238 DPRINTF(UFSHostDevice, "Read Callback\n"); 2239 uint8_t this_lun = 0; 2240 2241 //while we haven't found the right lun, keep searching 2242 while((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedRead()) 2243 ++this_lun; 2244 2245 DPRINTF(UFSHostDevice, "Found LUN %d messages pending for clean: %d\n", 2246 this_lun, SSDReadPending.size()); 2247 2248 if (this_lun < lunAvail) { 2249 //Clear signal. 2250 UFSDevice[this_lun]->clearReadSignal(); 2251 SSDReadPending.push_back(UFSDevice[this_lun]->SSDReadInfo.front()); 2252 UFSDevice[this_lun]->SSDReadInfo.pop_front(); 2253 readGarbageEventQueue.push_back(this); 2254 2255 //make sure the queue is popped a the end of the dma transaction 2256 readDevice(false, SSDReadPending.front().offset, 2257 SSDReadPending.front().size, 2258 &SSDReadPending.front().buffer[0], false, 2259 &readGarbageEventQueue.back()); 2260 2261 /**stats*/ 2262 ++stats.totalReadDiskTransactions; 2263 } 2264 else 2265 panic("no read finished in tick %d\n", curTick()); 2266} 2267 2268/** 2269 * After a disk read DMA transfer, the structure needs to be freed. This is 2270 * done in this function. 2271 */ 2272void 2273UFSHostDevice::readGarbage() 2274{ 2275 DPRINTF(UFSHostDevice, "Clean read data, %d\n", SSDReadPending.size()); 2276 SSDReadPending.pop_front(); 2277 readGarbageEventQueue.pop_front(); 2278} 2279 2280/** 2281 * Serialize; needed to make checkpoints 2282 */ 2283 2284void 2285UFSHostDevice::serialize(CheckpointOut &cp) const 2286{ 2287 DmaDevice::serialize(cp); 2288 2289 const uint8_t* temp_HCI_mem = reinterpret_cast<const uint8_t*>(&UFSHCIMem); 2290 SERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem)); 2291 2292 uint32_t lun_avail = lunAvail; 2293 SERIALIZE_SCALAR(lun_avail); 2294} 2295 2296 2297/** 2298 * Unserialize; needed to restore from checkpoints 2299 */ 2300 2301void 2302UFSHostDevice::unserialize(CheckpointIn &cp) 2303{ 2304 DmaDevice::unserialize(cp); 2305 uint8_t* temp_HCI_mem = reinterpret_cast<uint8_t*>(&UFSHCIMem); 2306 UNSERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem)); 2307 2308 uint32_t lun_avail; 2309 UNSERIALIZE_SCALAR(lun_avail); 2310 assert(lunAvail == lun_avail); 2311} 2312 2313 2314/** 2315 * Drain; needed to enable checkpoints 2316 */ 2317
|