gem5 v24.0.0.0
Loading...
Searching...
No Matches
ufs_device.cc
Go to the documentation of this file.
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
70#include "dev/arm/ufs_device.hh"
71
72namespace gem5
73{
74
79 uint32_t lun_id, const Callback &transfer_cb,
80 const Callback &read_cb):
81 SimObject(p),
82 flashDisk(p.image[lun_id]),
83 flashDevice(p.internalflash[lun_id]),
84 blkSize(p.img_blk_size),
85 lunAvail(p.image.size()),
86 diskSize(flashDisk->size()),
87 capacityLower((diskSize - 1) & 0xffffffff),
88 capacityUpper((diskSize - SectorSize) >> 32),
89 lunID(lun_id),
90 transferCompleted(false),
91 readCompleted(false),
92 totalRead(0),
93 totalWrite(0),
94 amountOfWriteTransfers(0),
95 amountOfReadTransfers(0)
96{
102 signalDone = transfer_cb;
103 memReadCallback = [this]() { readCallback(); };
104 deviceReadCallback = read_cb;
105 memWriteCallback = [this]() { SSDWriteDone(); };
106
111 uint32_t temp_id = ((lun_id | 0x30) << 24) | 0x3A4449;
112 lunInfo.dWord0 = 0x02060000; //data
113 lunInfo.dWord1 = 0x0200001F;
114 lunInfo.vendor0 = 0x484D5241; //ARMH (HMRA)
115 lunInfo.vendor1 = 0x424D4143; //CAMB (BMAC)
116 lunInfo.product0 = 0x356D6567; //gem5 (5meg)
117 lunInfo.product1 = 0x4D534655; //UFSM (MSFU)
118 lunInfo.product2 = 0x4C45444F; //ODEL (LEDO)
119 lunInfo.product3 = temp_id; // ID:"lun_id" ("lun_id":DI)
120 lunInfo.productRevision = 0x01000000; //0x01
121
122 DPRINTF(UFSHostDevice, "Logic unit %d assumes that %d logic units are"
123 " present in the system\n", lunID, lunAvail);
124 DPRINTF(UFSHostDevice,"The disksize of lun: %d should be %d blocks\n",
125 lunID, diskSize);
127}
128
129
135const unsigned int UFSHostDevice::UFSSCSIDevice::controlPage[3] =
136 {0x01400A0A, 0x00000000,
137 0x0000FFFF};
138const unsigned int UFSHostDevice::UFSSCSIDevice::recoveryPage[3] =
139 {0x03800A01, 0x00000000,
140 0xFFFF0003};
141const unsigned int UFSHostDevice::UFSSCSIDevice::cachingPage[5] =
142 {0x00011208, 0x00000000,
143 0x00000000, 0x00000020,
144 0x00000000};
145
147
161{
162 struct SCSIReply scsi_out;
163 scsi_out.reset();
164
169 scsi_out.message.header.dWord0 = UPIUHeaderDataIndWord0 |
170 lunID << 16;
171 scsi_out.message.header.dWord1 = UPIUHeaderDataIndWord1;
172 scsi_out.message.header.dWord2 = UPIUHeaderDataIndWord2;
173 statusCheck(SCSIGood, scsi_out.senseCode);
174 scsi_out.senseSize = scsi_out.senseCode[0];
175 scsi_out.LUN = lunID;
176 scsi_out.status = SCSIGood;
177
178 DPRINTF(UFSHostDevice, "SCSI command:%2x\n", SCSI_msg[4]);
181 switch (SCSI_msg[4] & 0xFF) {
182
183 case SCSIInquiry: {
187 scsi_out.msgSize = 36;
188 scsi_out.message.dataMsg.resize(9);
189
190 for (uint8_t count = 0; count < 9; count++)
191 scsi_out.message.dataMsg[count] =
192 (reinterpret_cast<uint32_t*> (&lunInfo))[count];
193 } break;
194
195 case SCSIRead6: {
199 scsi_out.expectMore = 0x02;
200 scsi_out.msgSize = 0;
201
202 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
203
208 uint32_t tmp = *reinterpret_cast<uint32_t*>(tempptr);
209 uint64_t read_offset = betoh(tmp) & 0x1FFFFF;
210
211 uint32_t read_size = tempptr[4];
212
213
214 scsi_out.msgSize = read_size * blkSize;
215 scsi_out.offset = read_offset * blkSize;
216
217 if ((read_offset + read_size) > diskSize)
218 scsi_out.status = SCSIIllegalRequest;
219
220 DPRINTF(UFSHostDevice, "Read6 offset: 0x%8x, for %d blocks\n",
221 read_offset, read_size);
222
226 statusCheck(scsi_out.status, scsi_out.senseCode);
227 scsi_out.senseSize = scsi_out.senseCode[0];
228 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
229 SCSICheckCondition;
230
231 } break;
232
233 case SCSIRead10: {
234 scsi_out.expectMore = 0x02;
235 scsi_out.msgSize = 0;
236
237 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
238
240 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]);
241 uint64_t read_offset = betoh(tmp);
242
243 uint16_t tmpsize = *reinterpret_cast<uint16_t*>(&tempptr[7]);
244 uint32_t read_size = betoh(tmpsize);
245
246 scsi_out.msgSize = read_size * blkSize;
247 scsi_out.offset = read_offset * blkSize;
248
249 if ((read_offset + read_size) > diskSize)
250 scsi_out.status = SCSIIllegalRequest;
251
252 DPRINTF(UFSHostDevice, "Read10 offset: 0x%8x, for %d blocks\n",
253 read_offset, read_size);
254
258 statusCheck(scsi_out.status, scsi_out.senseCode);
259 scsi_out.senseSize = scsi_out.senseCode[0];
260 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
261 SCSICheckCondition;
262
263 } break;
264
265 case SCSIRead16: {
266 scsi_out.expectMore = 0x02;
267 scsi_out.msgSize = 0;
268
269 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
270
272 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]);
273 uint64_t read_offset = betoh(tmp);
274
275 tmp = *reinterpret_cast<uint32_t*>(&tempptr[6]);
276 read_offset = (read_offset << 32) | betoh(tmp);
277
278 tmp = *reinterpret_cast<uint32_t*>(&tempptr[10]);
279 uint32_t read_size = betoh(tmp);
280
281 scsi_out.msgSize = read_size * blkSize;
282 scsi_out.offset = read_offset * blkSize;
283
284 if ((read_offset + read_size) > diskSize)
285 scsi_out.status = SCSIIllegalRequest;
286
287 DPRINTF(UFSHostDevice, "Read16 offset: 0x%8x, for %d blocks\n",
288 read_offset, read_size);
289
293 statusCheck(scsi_out.status, scsi_out.senseCode);
294 scsi_out.senseSize = scsi_out.senseCode[0];
295 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
296 SCSICheckCondition;
297
298 } break;
299
300 case SCSIReadCapacity10: {
304 scsi_out.msgSize = 8;
305 scsi_out.message.dataMsg.resize(2);
306 scsi_out.message.dataMsg[0] =
307 betoh(capacityLower);//last block
308 scsi_out.message.dataMsg[1] = betoh(blkSize);//blocksize
309
310 } break;
311 case SCSIReadCapacity16: {
312 scsi_out.msgSize = 32;
313 scsi_out.message.dataMsg.resize(8);
314 scsi_out.message.dataMsg[0] =
315 betoh(capacityUpper);//last block
316 scsi_out.message.dataMsg[1] =
317 betoh(capacityLower);//last block
318 scsi_out.message.dataMsg[2] = betoh(blkSize);//blocksize
319 scsi_out.message.dataMsg[3] = 0x00;//
320 scsi_out.message.dataMsg[4] = 0x00;//reserved
321 scsi_out.message.dataMsg[5] = 0x00;//reserved
322 scsi_out.message.dataMsg[6] = 0x00;//reserved
323 scsi_out.message.dataMsg[7] = 0x00;//reserved
324
325 } break;
326
327 case SCSIReportLUNs: {
331 scsi_out.msgSize = (lunAvail * 8) + 8;//list + overhead
332 scsi_out.message.dataMsg.resize(2 * lunAvail + 2);
333 scsi_out.message.dataMsg[0] = (lunAvail * 8) << 24;//LUN listlength
334 scsi_out.message.dataMsg[1] = 0x00;
335
336 for (uint8_t count = 0; count < lunAvail; count++) {
337 //LUN "count"
338 scsi_out.message.dataMsg[2 + 2 * count] = (count & 0x7F) << 8;
339 scsi_out.message.dataMsg[3 + 2 * count] = 0x00;
340 }
341
342 } break;
343
344 case SCSIStartStop: {
345 //Just acknowledge; not deemed relevant ATM
346 scsi_out.msgSize = 0;
347
348 } break;
349
350 case SCSITestUnitReady: {
351 //Just acknowledge; not deemed relevant ATM
352 scsi_out.msgSize = 0;
353
354 } break;
355
356 case SCSIVerify10: {
361 scsi_out.msgSize = 0;
362
363 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
364
366 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]);
367 uint64_t read_offset = betoh(tmp);
368
369 uint16_t tmpsize = *reinterpret_cast<uint16_t*>(&tempptr[7]);
370 uint32_t read_size = betoh(tmpsize);
371
372 if ((read_offset + read_size) > diskSize)
373 scsi_out.status = SCSIIllegalRequest;
374
378 statusCheck(scsi_out.status, scsi_out.senseCode);
379 scsi_out.senseSize = scsi_out.senseCode[0];
380 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
381 SCSICheckCondition;
382
383 } break;
384
385 case SCSIWrite6: {
390 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
391
396 uint32_t tmp = *reinterpret_cast<uint32_t*>(tempptr);
397 uint64_t write_offset = betoh(tmp) & 0x1FFFFF;
398
399 uint32_t write_size = tempptr[4];
400
401 scsi_out.msgSize = write_size * blkSize;
402 scsi_out.offset = write_offset * blkSize;
403 scsi_out.expectMore = 0x01;
404
405 if ((write_offset + write_size) > diskSize)
406 scsi_out.status = SCSIIllegalRequest;
407
408 DPRINTF(UFSHostDevice, "Write6 offset: 0x%8x, for %d blocks\n",
409 write_offset, write_size);
410
414 statusCheck(scsi_out.status, scsi_out.senseCode);
415 scsi_out.senseSize = scsi_out.senseCode[0];
416 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
417 SCSICheckCondition;
418
419 } break;
420
421 case SCSIWrite10: {
422 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
423
425 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]);
426 uint64_t write_offset = betoh(tmp);
427
428 uint16_t tmpsize = *reinterpret_cast<uint16_t*>(&tempptr[7]);
429 uint32_t write_size = betoh(tmpsize);
430
431 scsi_out.msgSize = write_size * blkSize;
432 scsi_out.offset = write_offset * blkSize;
433 scsi_out.expectMore = 0x01;
434
435 if ((write_offset + write_size) > diskSize)
436 scsi_out.status = SCSIIllegalRequest;
437
438 DPRINTF(UFSHostDevice, "Write10 offset: 0x%8x, for %d blocks\n",
439 write_offset, write_size);
440
444 statusCheck(scsi_out.status, scsi_out.senseCode);
445 scsi_out.senseSize = scsi_out.senseCode[0];
446 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
447 SCSICheckCondition;
448
449 } break;
450
451 case SCSIWrite16: {
452 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
453
455 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]);
456 uint64_t write_offset = betoh(tmp);
457
458 tmp = *reinterpret_cast<uint32_t*>(&tempptr[6]);
459 write_offset = (write_offset << 32) | betoh(tmp);
460
461 tmp = *reinterpret_cast<uint32_t*>(&tempptr[10]);
462 uint32_t write_size = betoh(tmp);
463
464 scsi_out.msgSize = write_size * blkSize;
465 scsi_out.offset = write_offset * blkSize;
466 scsi_out.expectMore = 0x01;
467
468 if ((write_offset + write_size) > diskSize)
469 scsi_out.status = SCSIIllegalRequest;
470
471 DPRINTF(UFSHostDevice, "Write16 offset: 0x%8x, for %d blocks\n",
472 write_offset, write_size);
473
477 statusCheck(scsi_out.status, scsi_out.senseCode);
478 scsi_out.senseSize = scsi_out.senseCode[0];
479 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
480 SCSICheckCondition;
481
482 } break;
483
484 case SCSIFormatUnit: {//not yet verified
485 scsi_out.msgSize = 0;
486 scsi_out.expectMore = 0x01;
487
488 } break;
489
490 case SCSISendDiagnostic: {//not yet verified
491 scsi_out.msgSize = 0;
492
493 } break;
494
495 case SCSISynchronizeCache: {
496 //do we have cache (we don't have cache at this moment)
497 //TODO: here will synchronization happen when cache is modelled
498 scsi_out.msgSize = 0;
499
500 } break;
501
502 //UFS SCSI additional command set for full functionality
503 case SCSIModeSelect10:
504 //TODO:
505 //scsi_out.expectMore = 0x01;//not supported due to modepage support
506 //code isn't dead, code suggest what is to be done when implemented
507 break;
508
509 case SCSIModeSense6: case SCSIModeSense10: {
514 if ((SCSI_msg[4] & 0x3F0000) >> 16 == 0x0A) {//control page
515 scsi_out.message.dataMsg.resize((sizeof(controlPage) >> 2) + 2);
516 scsi_out.message.dataMsg[0] = 0x00000A00;//control page code
517 scsi_out.message.dataMsg[1] = 0x00000000;//See JEDEC220 ch8
518
519 for (uint8_t count = 0; count < 3; count++)
520 scsi_out.message.dataMsg[2 + count] = controlPage[count];
521
522 scsi_out.msgSize = 20;
523 DPRINTF(UFSHostDevice, "CONTROL page\n");
524
525 } else if ((SCSI_msg[4] & 0x3F0000) >> 16 == 0x01) {//recovery page
526 scsi_out.message.dataMsg.resize((sizeof(recoveryPage) >> 2)
527 + 2);
528
529 scsi_out.message.dataMsg[0] = 0x00000100;//recovery page code
530 scsi_out.message.dataMsg[1] = 0x00000000;//See JEDEC220 ch8
531
532 for (uint8_t count = 0; count < 3; count++)
533 scsi_out.message.dataMsg[2 + count] = recoveryPage[count];
534
535 scsi_out.msgSize = 20;
536 DPRINTF(UFSHostDevice, "RECOVERY page\n");
537
538 } else if ((SCSI_msg[4] & 0x3F0000) >> 16 == 0x08) {//caching page
539
540 scsi_out.message.dataMsg.resize((sizeof(cachingPage) >> 2) + 2);
541 scsi_out.message.dataMsg[0] = 0x00001200;//caching page code
542 scsi_out.message.dataMsg[1] = 0x00000000;//See JEDEC220 ch8
543
544 for (uint8_t count = 0; count < 5; count++)
545 scsi_out.message.dataMsg[2 + count] = cachingPage[count];
546
547 scsi_out.msgSize = 20;
548 DPRINTF(UFSHostDevice, "CACHE page\n");
549
550 } else if ((SCSI_msg[4] & 0x3F0000) >> 16 == 0x3F) {//ALL the pages!
551
552 scsi_out.message.dataMsg.resize(((sizeof(controlPage) +
553 sizeof(recoveryPage) +
554 sizeof(cachingPage)) >> 2)
555 + 2);
556 scsi_out.message.dataMsg[0] = 0x00003200;//all page code
557 scsi_out.message.dataMsg[1] = 0x00000000;//See JEDEC220 ch8
558
559 for (uint8_t count = 0; count < 3; count++)
560 scsi_out.message.dataMsg[2 + count] = recoveryPage[count];
561
562 for (uint8_t count = 0; count < 5; count++)
563 scsi_out.message.dataMsg[5 + count] = cachingPage[count];
564
565 for (uint8_t count = 0; count < 3; count++)
566 scsi_out.message.dataMsg[10 + count] = controlPage[count];
567
568 scsi_out.msgSize = 52;
569 DPRINTF(UFSHostDevice, "Return ALL the pages!!!\n");
570
571 } else inform("Wrong mode page requested\n");
572
573 scsi_out.message.dataCount = scsi_out.msgSize << 24;
574 } break;
575
576 case SCSIRequestSense: {
577 scsi_out.msgSize = 0;
578
579 } break;
580
581 case SCSIUnmap:break;//not yet verified
582
583 case SCSIWriteBuffer: {
584 scsi_out.expectMore = 0x01;
585
586 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
587
589 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]);
590 uint64_t write_offset = betoh(tmp) & 0xFFFFFF;
591
592 tmp = *reinterpret_cast<uint32_t*>(&tempptr[5]);
593 uint32_t write_size = betoh(tmp) & 0xFFFFFF;
594
595 scsi_out.msgSize = write_size;
596 scsi_out.offset = write_offset;
597
598 } break;
599
600 case SCSIReadBuffer: {
606 scsi_out.expectMore = 0x02;
607
608 uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
609
611 uint32_t tmp = *reinterpret_cast<uint32_t*>(&tempptr[2]);
612 uint64_t read_offset = betoh(tmp) & 0xFFFFFF;
613
614 tmp = *reinterpret_cast<uint32_t*>(&tempptr[5]);
615 uint32_t read_size = betoh(tmp) & 0xFFFFFF;
616
617 scsi_out.msgSize = read_size;
618 scsi_out.offset = read_offset;
619
620 if ((read_offset + read_size) > capacityLower * blkSize)
621 scsi_out.status = SCSIIllegalRequest;
622
623 DPRINTF(UFSHostDevice, "Read buffer location: 0x%8x\n",
624 read_offset);
625 DPRINTF(UFSHostDevice, "Number of bytes: 0x%8x\n", read_size);
626
627 statusCheck(scsi_out.status, scsi_out.senseCode);
628 scsi_out.senseSize = scsi_out.senseCode[0];
629 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
630 SCSICheckCondition;
631
632 } break;
633
634 case SCSIMaintenanceIn: {
641 DPRINTF(UFSHostDevice, "Ignoring Maintenance In command\n");
642 statusCheck(SCSIIllegalRequest, scsi_out.senseCode);
643 scsi_out.senseSize = scsi_out.senseCode[0];
644 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
645 SCSICheckCondition;
646 scsi_out.msgSize = 0;
647 } break;
648
649 default: {
650 statusCheck(SCSIIllegalRequest, scsi_out.senseCode);
651 scsi_out.senseSize = scsi_out.senseCode[0];
652 scsi_out.status = (scsi_out.status == SCSIGood) ? SCSIGood :
653 SCSICheckCondition;
654 scsi_out.msgSize = 0;
655 inform("Unsupported scsi message type: %2x\n", SCSI_msg[4] & 0xFF);
656 inform("0x%8x\n", SCSI_msg[0]);
657 inform("0x%8x\n", SCSI_msg[1]);
658 inform("0x%8x\n", SCSI_msg[2]);
659 inform("0x%8x\n", SCSI_msg[3]);
660 inform("0x%8x\n", SCSI_msg[4]);
661 } break;
662 }
663
664 return scsi_out;
665}
666
673void
675 uint8_t* sensecodelist)
676{
677 for (uint8_t count = 0; count < 19; count++)
678 sensecodelist[count] = 0;
679
680 sensecodelist[0] = 18; //sense length
681 sensecodelist[1] = 0x70; //we send a valid frame
682 sensecodelist[3] = status & 0xF; //mask to be sure + sensecode
683 sensecodelist[8] = 0x1F; //data length
684}
685
690void
692 uint32_t size)
693{
695 for (int count = 0; count < (size / SectorSize); count++)
696 flashDisk->read(&(readaddr[SectorSize*count]), (offset /
697 SectorSize) + count);
698}
699
704void
706 uint32_t size)
707{
709 for (int count = 0; count < (size / SectorSize); count++)
710 flashDisk->write(&(writeaddr[SectorSize * count]),
711 (offset / SectorSize) + count);
712}
713
718UFSHostDevice::UFSHostDevice(const UFSHostDeviceParams &p) :
719 DmaDevice(p),
720 pioAddr(p.pio_addr),
721 pioSize(0x0FFF),
722 pioDelay(p.pio_latency),
723 intNum(p.int_num),
724 gic(p.gic),
725 lunAvail(p.image.size()),
726 UFSSlots(p.ufs_slots - 1),
731 countInt(0),
732 transferTrack(0),
735 stats(this),
736 SCSIResumeEvent([this]{ SCSIStart(); }, name()),
737 UTPEvent([this]{ finalUTP(); }, name())
738{
739 DPRINTF(UFSHostDevice, "The hostcontroller hosts %d Logic units\n",
740 lunAvail);
741 UFSDevice.resize(lunAvail);
742
743 for (int count = 0; count < lunAvail; count++) {
744 UFSDevice[count] = new UFSSCSIDevice(p, count,
745 [this]() { LUNSignal(); },
746 [this]() { readCallback(); });
747 }
748
749 if (UFSSlots > 31)
750 warn("UFSSlots = %d, this will results in %d command slots",
751 UFSSlots, (UFSSlots & 0x1F));
752
753 if ((UFSSlots & 0x1F) == 0)
754 fatal("Number of UFS command slots should be between 1 and 32.");
755
756 setValues();
757}
758
761 : statistics::Group(parent, "UFSDiskHost"),
762 ADD_STAT(currentSCSIQueue, statistics::units::Count::get(),
763 "Most up to date length of the command queue"),
764 ADD_STAT(currentReadSSDQueue, statistics::units::Count::get(),
765 "Most up to date length of the read SSD queue"),
766 ADD_STAT(currentWriteSSDQueue, statistics::units::Count::get(),
767 "Most up to date length of the write SSD queue"),
769 ADD_STAT(totalReadSSD, statistics::units::Byte::get(),
770 "Number of bytes read from SSD"),
771 ADD_STAT(totalWrittenSSD, statistics::units::Byte::get(),
772 "Number of bytes written to SSD"),
773 ADD_STAT(totalReadDiskTransactions, statistics::units::Count::get(),
774 "Number of transactions from disk"),
775 ADD_STAT(totalWriteDiskTransactions, statistics::units::Count::get(),
776 "Number of transactions to disk"),
777 ADD_STAT(totalReadUFSTransactions, statistics::units::Count::get(),
778 "Number of transactions from device"),
779 ADD_STAT(totalWriteUFSTransactions, statistics::units::Count::get(),
780 "Number of transactions to device"),
782 ADD_STAT(averageReadSSDBW, statistics::units::Rate<
783 statistics::units::Byte, statistics::units::Second>::get(),
784 "Average read bandwidth",
785 totalReadSSD / simSeconds),
786 ADD_STAT(averageWriteSSDBW, statistics::units::Rate<
787 statistics::units::Byte, statistics::units::Second>::get(),
788 "Average write bandwidth",
789 totalWrittenSSD / simSeconds),
790 ADD_STAT(averageSCSIQueue, statistics::units::Rate<
791 statistics::units::Count, statistics::units::Tick>::get(),
792 "Average command queue length"),
793 ADD_STAT(averageReadSSDQueue, statistics::units::Rate<
794 statistics::units::Count, statistics::units::Tick>::get(),
795 "Average read queue length"),
796 ADD_STAT(averageWriteSSDQueue, statistics::units::Rate<
797 statistics::units::Count, statistics::units::Tick>::get(),
798 "Average write queue length"),
800 ADD_STAT(curDoorbell, statistics::units::Count::get(),
801 "Most up to date number of doorbells used",
802 parent->activeDoorbells),
803 ADD_STAT(maxDoorbell, statistics::units::Count::get(),
804 "Maximum number of doorbells utilized"),
805 ADD_STAT(averageDoorbell, statistics::units::Rate<
806 statistics::units::Count, statistics::units::Tick>::get(),
807 "Average number of Doorbells used"),
809 ADD_STAT(transactionLatency, statistics::units::Tick::get(),
810 "Histogram of transaction times"),
811 ADD_STAT(idleTimes, statistics::units::Tick::get(), "Histogram of idle times")
812{
813 using namespace statistics;
814
815 // Register the stats
818 .flags(none);
820 .flags(none);
822 .flags(none);
823
826 .flags(none);
827
829 .flags(none);
830
832 .flags(none);
834 .flags(none);
836 .flags(none);
838 .flags(none);
839
842 .flags(nozero);
843
845 .flags(nozero);
846
848 .flags(nozero);
850 .flags(nozero);
852 .flags(nozero);
853
856 .flags(none);
857
859 .flags(none);
861 .flags(nozero);
862
865 .init(100)
866 .flags(pdf);
867
869 .init(100)
870 .flags(pdf);
871}
872
877{
883 UFSHCIMem.HCCAP = 0x06070000 | (UFSSlots & 0x1F);
884 UFSHCIMem.HCversion = 0x00010000; //version is 1.0
885 UFSHCIMem.HCHCDDID = 0xAA003C3C;// Arbitrary number
886 UFSHCIMem.HCHCPMID = 0x41524D48; //ARMH (not an official MIPI number)
887 UFSHCIMem.TRUTRLDBR = 0x00;
888 UFSHCIMem.TMUTMRLDBR = 0x00;
889 UFSHCIMem.CMDUICCMDR = 0x00;
890 // We can process CMD, TM, TR, device present
892 UFSHCIMem.TRUTRLBA = 0x00;
893 UFSHCIMem.TRUTRLBAU = 0x00;
894 UFSHCIMem.TMUTMRLBA = 0x00;
895 UFSHCIMem.TMUTMRLBAU = 0x00;
896}
897
904{
905 AddrRangeList ranges;
906 ranges.push_back(RangeSize(pioAddr, pioSize));
907 return ranges;
908}
909
915Tick
917{
918 uint32_t data = 0;
919
920 switch (pkt->getAddr() & 0xFF)
921 {
922
925 break;
926
927 case regUFSVersion:
929 break;
930
933 break;
934
937 break;
938
942 //TODO: Revise and extend
944 break;
945
948 break;
949
952 break;
953
956 break;
957
960 break;
961
964 break;
965
968 break;
969
972 break;
973
976 break;
977
980 break;
981
984 break;
985
988 break;
989
992 break;
993
996 break;
997
1000 break;
1001
1004 break;
1005
1008 break;
1009
1012 break;
1013
1016 break;
1017
1020 break;
1021
1022 case regUICCommand:
1024 break;
1025
1026 case regUICCommandArg1:
1028 break;
1029
1030 case regUICCommandArg2:
1032 break;
1033
1034 case regUICCommandArg3:
1036 break;
1037
1038 default:
1039 data = 0x00;
1040 break;
1041 }
1042
1043 pkt->setLE<uint32_t>(data);
1044 pkt->makeResponse();
1045 return pioDelay;
1046}
1047
1053Tick
1055{
1056 assert(pkt->getSize() <= 4);
1057
1058 const uint32_t data = pkt->getUintX(ByteOrder::little);
1059
1060 switch (pkt->getAddr() & 0xFF)
1061 {
1062 case regControllerCapabilities://you shall not write to this
1063 break;
1064
1065 case regUFSVersion://you shall not write to this
1066 break;
1067
1068 case regControllerDEVID://you shall not write to this
1069 break;
1070
1071 case regControllerPRODID://you shall not write to this
1072 break;
1073
1074 case regInterruptStatus://you shall not write to this
1075 break;
1076
1077 case regInterruptEnable:
1079 break;
1080
1083 break;
1084
1087 break;
1088
1091 break;
1092
1095 break;
1096
1099 break;
1100
1103 break;
1104
1105 case regUICErrorCodeDME:
1107 break;
1108
1111 break;
1112
1115 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) &&
1118 break;
1119
1122 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) &&
1125 break;
1126
1128 if (!(UFSHCIMem.TRUTRLDBR) && data)
1132 break;
1133
1136 break;
1137
1140 break;
1141
1144 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) &&
1147 break;
1148
1151 if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) &&
1154 break;
1155
1159 break;
1160
1163 break;
1164
1167 break;
1168
1169 case regUICCommand:
1172 break;
1173
1174 case regUICCommandArg1:
1176 break;
1177
1178 case regUICCommandArg2:
1180 break;
1181
1182 case regUICCommandArg3:
1184 break;
1185
1186 default:break;//nothing happens, you try to access a register that
1187 //does not exist
1188
1189 }
1190
1191 pkt->makeResponse();
1192 return pioDelay;
1193}
1194
1200void
1202{
1203 Addr address = 0x00;
1204 int mask = 0x01;
1205 int size;
1206 int count = 0;
1207 struct taskStart task_info;
1208 struct transferStart transferstart_info;
1209 transferstart_info.done = 0;
1210
1216 while (((UFSHCIMem.CMDUICCMDR > 0x00) |
1218 ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00)) ) {
1219
1220 if (UFSHCIMem.CMDUICCMDR > 0x00) {
1228 UFSHCIMem.CMDUICCMDR = 0x00;
1229 return; //command, nothing more we can do
1230
1231 } else if ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) {
1236 size = sizeof(UTPUPIUTaskReq);
1239 address = UFSHCIMem.TMUTMRLBAU;
1240 //<-64 bit
1241 address = (count * size) + (address << 32) +
1244
1245 inform("UFSmodel received a task from the system; this might"
1246 " lead to untested behaviour.\n");
1247
1248 task_info.mask = mask << count;
1249 task_info.address = address;
1250 task_info.size = size;
1251 task_info.done = UFSHCIMem.TMUTMRLDBR;
1252 taskInfo.push_back(task_info);
1253 taskEventQueue.push_back(
1254 EventFunctionWrapper([this]{ taskStart(); }, name()));
1255 writeDevice(&taskEventQueue.back(), false, address, size,
1256 reinterpret_cast<uint8_t*>
1257 (&taskInfo.back().destination), 0, 0);
1258
1259 } else if ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00) {
1265 size = sizeof(UTPTransferReqDesc);
1268 address = UFSHCIMem.TRUTRLBAU;
1269 //<-64 bit
1270 address = (count * size) + (address << 32) + UFSHCIMem.TRUTRLBA;
1271
1272 transferTrack |= mask << count;
1273 DPRINTF(UFSHostDevice, "Doorbell register: 0x%8x select #:"
1274 " 0x%8x completion info: 0x%8x\n", UFSHCIMem.TRUTRLDBR,
1275 count, transferstart_info.done);
1276
1277 transferstart_info.done = UFSHCIMem.TRUTRLDBR;
1278
1280 transactionStart[count] = curTick(); //note the start time
1285
1291 transferstart_info.mask = mask << count;
1292 transferstart_info.address = address;
1293 transferstart_info.size = size;
1294 transferstart_info.done = UFSHCIMem.TRUTRLDBR;
1295 transferStartInfo.push_back(transferstart_info);
1296
1298 transferStartInfo.back().destination = new struct
1300 DPRINTF(UFSHostDevice, "Initial transfer start: 0x%8x\n",
1301 transferstart_info.done);
1302 transferEventQueue.push_back(
1303 EventFunctionWrapper([this]{ transferStart(); }, name()));
1304
1305 if (transferEventQueue.size() < 2) {
1306 writeDevice(&transferEventQueue.front(), false,
1307 address, size, reinterpret_cast<uint8_t*>
1308 (transferStartInfo.front().destination),0, 0);
1309 DPRINTF(UFSHostDevice, "Transfer scheduled\n");
1310 }
1311 }
1312 }
1313}
1314
1319void
1321{
1322 DPRINTF(UFSHostDevice, "Task start");
1323 taskHandler(&taskInfo.front().destination, taskInfo.front().mask,
1324 taskInfo.front().address, taskInfo.front().size);
1325 taskInfo.pop_front();
1326 taskEventQueue.pop_front();
1327}
1328
1333void
1335{
1336 DPRINTF(UFSHostDevice, "Enter transfer event\n");
1337 transferHandler(transferStartInfo.front().destination,
1338 transferStartInfo.front().mask,
1339 transferStartInfo.front().address,
1340 transferStartInfo.front().size,
1341 transferStartInfo.front().done);
1342
1343 transferStartInfo.pop_front();
1344 DPRINTF(UFSHostDevice, "Transfer queue size at end of event: "
1345 "0x%8x\n", transferEventQueue.size());
1346}
1347
1353void
1355{
1356 if (UFSHCIMem.CMDUICCMDR == 0x16) {
1357 UFSHCIMem.ORHostControllerStatus |= 0x0F;//link startup
1358 }
1359
1360}
1361
1367void
1369 uint32_t req_pos, Addr finaladdress, uint32_t
1370 finalsize)
1371{
1376 inform("taskHandler\n");
1377 inform("%8x\n", request_in->header.dWord0);
1378 inform("%8x\n", request_in->header.dWord1);
1379 inform("%8x\n", request_in->header.dWord2);
1380
1381 request_in->header.dWord2 &= 0xffffff00;
1382
1383 UFSHCIMem.TMUTMRLDBR &= ~(req_pos);
1384 taskCommandTrack &= ~(req_pos);
1386
1387 readDevice(true, finaladdress, finalsize, reinterpret_cast<uint8_t*>
1388 (request_in), true, NULL);
1389
1390}
1391
1403void
1405 int req_pos, Addr finaladdress, uint32_t
1406 finalsize, uint32_t done)
1407{
1408
1409 Addr cmd_desc_addr = 0x00;
1410
1411
1412 //acknowledge handling of the message
1413 DPRINTF(UFSHostDevice, "SCSI message detected\n");
1414 request_in->header.dWord2 &= 0xffffff00;
1415 SCSIInfo.RequestIn = request_in;
1416 SCSIInfo.reqPos = req_pos;
1417 SCSIInfo.finalAddress = finaladdress;
1418 SCSIInfo.finalSize = finalsize;
1419 SCSIInfo.destination.resize(request_in->PRDTableOffset * 4
1420 + request_in->PRDTableLength * sizeof(UFSHCDSGEntry));
1421 SCSIInfo.done = done;
1422
1423 assert(!SCSIResumeEvent.scheduled());
1427 cmd_desc_addr = request_in->commandDescBaseAddrHi;
1428 cmd_desc_addr = (cmd_desc_addr << 32) |
1429 (request_in->commandDescBaseAddrLo & 0xffffffff);
1430
1431 writeDevice(&SCSIResumeEvent, false, cmd_desc_addr,
1432 SCSIInfo.destination.size(), &SCSIInfo.destination[0],0, 0);
1433
1434 DPRINTF(UFSHostDevice, "SCSI scheduled\n");
1435
1436 transferEventQueue.pop_front();
1437}
1438
1446void
1448{
1449 DPRINTF(UFSHostDevice, "SCSI message on hold until ready\n");
1450 uint32_t LUN = SCSIInfo.destination[2];
1451 UFSDevice[LUN]->SCSIInfoQueue.push_back(SCSIInfo);
1452
1453 DPRINTF(UFSHostDevice, "SCSI queue %d has %d elements\n", LUN,
1454 UFSDevice[LUN]->SCSIInfoQueue.size());
1455
1457 if (UFSDevice[LUN]->SCSIInfoQueue.size() < 2) //LUN is available
1458 SCSIResume(LUN);
1459
1460 else if (UFSDevice[LUN]->SCSIInfoQueue.size() > 32)
1461 panic("SCSI queue is getting too big %d\n", UFSDevice[LUN]->
1462 SCSIInfoQueue.size());
1463
1468 if (!transferEventQueue.empty()) {
1469
1474 writeDevice(&transferEventQueue.front(), false,
1475 transferStartInfo.front().address,
1476 transferStartInfo.front().size, reinterpret_cast<uint8_t*>
1477 (transferStartInfo.front().destination), 0, 0);
1478
1479 DPRINTF(UFSHostDevice, "Transfer scheduled");
1480 }
1481}
1482
1491void
1493{
1494 DPRINTF(UFSHostDevice, "SCSIresume\n");
1495 if (UFSDevice[lun_id]->SCSIInfoQueue.empty())
1496 panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id,
1498
1500 struct UTPTransferReqDesc* request_in = UFSDevice[lun_id]->
1501 SCSIInfoQueue.front().RequestIn;
1502
1503 uint32_t req_pos = UFSDevice[lun_id]->SCSIInfoQueue.front().reqPos;
1504
1505 Addr finaladdress = UFSDevice[lun_id]->SCSIInfoQueue.front().
1506 finalAddress;
1507
1508 uint32_t finalsize = UFSDevice[lun_id]->SCSIInfoQueue.front().finalSize;
1509
1510 uint32_t* transfercommand = reinterpret_cast<uint32_t*>
1511 (&(UFSDevice[lun_id]->SCSIInfoQueue.front().destination[0]));
1512
1513 DPRINTF(UFSHostDevice, "Task tag: 0x%8x\n", transfercommand[0]>>24);
1515 request_out_datain = UFSDevice[(transfercommand[0] & 0xFF0000) >> 16]->
1516 SCSICMDHandle(transfercommand);
1517
1519
1524 request_in->header.dWord0 = ((request_in->header.dWord0 >> 24) == 0x21)
1525 ? 0x36 : 0x21;
1526 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord0 =
1527 request_in->header.dWord0 | (request_out_datain.LUN << 8)
1528 | (transfercommand[0] & 0xFF000000);
1530 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord1 = 0x00000000 |
1531 (request_out_datain.status << 24);
1533 UFSDevice[lun_id]->transferInfo.requestOut.header.dWord2 = 0x00000000 |
1534 ((request_out_datain.senseSize + 2) << 24) | 0x05;
1536 UFSDevice[lun_id]->transferInfo.requestOut.senseDataLen =
1538
1539 //data
1540 for (uint8_t count = 0; count<request_out_datain.senseSize; count++) {
1541 UFSDevice[lun_id]->transferInfo.requestOut.senseData[count] =
1543 }
1544
1545 /*
1546 * At position defined by "request_in->PRDTableOffset" (counting 32 bit
1547 * words) in array "transfercommand" we have a scatter gather list, which
1548 * is usefull to us if we interpreted it as a UFSHCDSGEntry structure.
1549 */
1550 struct UFSHCDSGEntry* sglist = reinterpret_cast<UFSHCDSGEntry*>
1551 (&(transfercommand[(request_in->PRDTableOffset)]));
1552
1553 uint32_t length = request_in->PRDTableLength;
1554 DPRINTF(UFSHostDevice, "# PRDT entries: %d\n", length);
1555
1556 Addr response_addr = request_in->commandDescBaseAddrHi;
1557 response_addr = (response_addr << 32) |
1558 ((request_in->commandDescBaseAddrLo +
1559 (request_in->responseUPIULength << 2)) & 0xffffffff);
1560
1562 UFSDevice[lun_id]->transferInfo.responseStartAddr = response_addr;
1563 UFSDevice[lun_id]->transferInfo.reqPos = req_pos;
1564 UFSDevice[lun_id]->transferInfo.size = finalsize;
1565 UFSDevice[lun_id]->transferInfo.address = finaladdress;
1566 UFSDevice[lun_id]->transferInfo.destination = reinterpret_cast<uint8_t*>
1567 (UFSDevice[lun_id]->SCSIInfoQueue.front().RequestIn);
1568 UFSDevice[lun_id]->transferInfo.finished = true;
1569 UFSDevice[lun_id]->transferInfo.lunID = request_out_datain.LUN;
1570
1576 if (request_out_datain.expectMore == 0x01) {
1579 length, sglist);
1580
1581 } else if (request_out_datain.expectMore == 0x02) {
1584 request_out_datain.offset, length, sglist);
1585
1586 } else {
1588 uint32_t count = 0;
1589 uint32_t size_accum = 0;
1590 DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n",
1592
1594 while ((length > count) && size_accum
1595 < (request_out_datain.msgSize - 1) &&
1596 (request_out_datain.msgSize != 0x00)) {
1597 Addr SCSI_start = sglist[count].upperAddr;
1598 SCSI_start = (SCSI_start << 32) |
1599 (sglist[count].baseAddr & 0xFFFFFFFF);
1600 DPRINTF(UFSHostDevice, "Data DMA start: 0x%8x\n", SCSI_start);
1601 DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n",
1602 (sglist[count].size + 1));
1610 uint32_t size_to_send = sglist[count].size + 1;
1611
1612 if (request_out_datain.msgSize < (size_to_send + size_accum))
1613 size_to_send = request_out_datain.msgSize - size_accum;
1614
1615 readDevice(false, SCSI_start, size_to_send,
1616 reinterpret_cast<uint8_t*>
1617 (&(request_out_datain.message.dataMsg[size_accum])),
1618 false, NULL);
1619
1620 size_accum += size_to_send;
1621 DPRINTF(UFSHostDevice, "Total remaining: 0x%8x,accumulated so far"
1622 " : 0x%8x\n", (request_out_datain.msgSize - size_accum),
1623 size_accum);
1624
1625 ++count;
1626 DPRINTF(UFSHostDevice, "Transfer #: %d\n", count);
1627 }
1628
1630 transferDone(response_addr, req_pos, UFSDevice[lun_id]->
1631 transferInfo.requestOut, finalsize, finaladdress,
1632 reinterpret_cast<uint8_t*>(request_in), true, lun_id);
1633 }
1634
1635 DPRINTF(UFSHostDevice, "SCSI resume done\n");
1636}
1637
1643void
1645{
1646 uint8_t this_lun = 0;
1647
1648 //while we haven't found the right lun, keep searching
1649 while ((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedCommand())
1650 ++this_lun;
1651
1652 if (this_lun < lunAvail) {
1653 //Clear signal.
1654 UFSDevice[this_lun]->clearSignal();
1655 //found it; call transferDone
1656 transferDone(UFSDevice[this_lun]->transferInfo.responseStartAddr,
1657 UFSDevice[this_lun]->transferInfo.reqPos,
1658 UFSDevice[this_lun]->transferInfo.requestOut,
1659 UFSDevice[this_lun]->transferInfo.size,
1660 UFSDevice[this_lun]->transferInfo.address,
1661 UFSDevice[this_lun]->transferInfo.destination,
1662 UFSDevice[this_lun]->transferInfo.finished,
1663 UFSDevice[this_lun]->transferInfo.lunID);
1664 }
1665
1666 else
1667 panic("no LUN finished in tick %d\n", curTick());
1668}
1669
1675void
1676UFSHostDevice::transferDone(Addr responseStartAddr, uint32_t req_pos,
1677 struct UTPUPIURSP request_out, uint32_t size,
1678 Addr address, uint8_t* destination,
1679 bool finished, uint32_t lun_id)
1680{
1682 if (UFSDevice[lun_id]->SCSIInfoQueue.empty())
1683 panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id,
1685
1686 DPRINTF(UFSHostDevice, "DMA start: 0x%8x; DMA size: 0x%8x\n",
1687 responseStartAddr, sizeof(request_out));
1688
1689 struct transferStart lastinfo;
1690 lastinfo.mask = req_pos;
1691 lastinfo.done = finished;
1692 lastinfo.address = address;
1693 lastinfo.size = size;
1694 lastinfo.destination = reinterpret_cast<UTPTransferReqDesc*>
1695 (destination);
1696 lastinfo.lun_id = lun_id;
1697
1698 transferEnd.push_back(lastinfo);
1699
1700 DPRINTF(UFSHostDevice, "Transfer done start\n");
1701
1702 readDevice(false, responseStartAddr, sizeof(request_out),
1703 reinterpret_cast<uint8_t*>
1704 (&(UFSDevice[lun_id]->transferInfo.requestOut)),
1705 true, &UTPEvent);
1706}
1707
1714void
1716{
1717 uint32_t lun_id = transferEnd.front().lun_id;
1718
1719 UFSDevice[lun_id]->SCSIInfoQueue.pop_front();
1720 DPRINTF(UFSHostDevice, "SCSIInfoQueue size: %d, lun: %d\n",
1721 UFSDevice[lun_id]->SCSIInfoQueue.size(), lun_id);
1722
1724 if (UFSHCIMem.TRUTRLDBR & transferEnd.front().mask) {
1725 uint8_t count = 0;
1726 while (!(transferEnd.front().mask & (0x1 << count)))
1727 ++count;
1730 }
1731
1733 readDevice(true, transferEnd.front().address,
1734 transferEnd.front().size, reinterpret_cast<uint8_t*>
1735 (transferEnd.front().destination), true, NULL);
1736
1738 transferTrack &= ~(transferEnd.front().mask);
1741 garbage.push_back(transferEnd.front().destination);
1742 transferEnd.pop_front();
1743 DPRINTF(UFSHostDevice, "UTP handled\n");
1744
1747
1748 DPRINTF(UFSHostDevice, "activeDoorbells: %d, pendingDoorbells: %d,"
1749 " garbage: %d, TransferEvent: %d\n", activeDoorbells,
1751
1753 if (!UFSDevice[lun_id]->SCSIInfoQueue.empty())
1754 SCSIResume(lun_id);
1755}
1756
1760void
1762{
1763 DPRINTF(UFSHostDevice, "Read done start\n");
1765
1767 if (garbage.size() > 0) {
1768 delete garbage.front();
1769 garbage.pop_front();
1770 }
1771
1773 if (!(UFSHCIMem.ORInterruptStatus & 0x01)) {
1776 }
1777
1778
1779 if (!readDoneEvent.empty()) {
1780 readDoneEvent.pop_front();
1781 }
1782}
1783
1788void
1790{
1792 countInt++;
1793
1796 pendingDoorbells = 0;
1797 DPRINTF(UFSHostDevice, "Clear doorbell %X\n", UFSHCIMem.TRUTRLDBR);
1798
1799 checkDrain();
1800
1802 gic->sendInt(intNum);
1803 DPRINTF(UFSHostDevice, "Send interrupt @ transaction: 0x%8x!\n",
1804 countInt);
1805}
1806
1811void
1813{
1815 DPRINTF(UFSHostDevice, "Clear interrupt: 0x%8x!\n", countInt);
1816
1817 checkDrain();
1818
1819 if (!(UFSHCIMem.TRUTRLDBR)) {
1821 }
1823}
1824
1849void
1850UFSHostDevice::writeDevice(Event* additional_action, bool toDisk, Addr
1851 start, int size, uint8_t* destination, uint64_t
1852 SCSIDiskOffset, uint32_t lun_id)
1853{
1854 DPRINTF(UFSHostDevice, "Write transaction Start: 0x%8x; Size: %d\n",
1855 start, size);
1856
1858 if (toDisk) {
1860
1861 while (!writeDoneEvent.empty() && (writeDoneEvent.front().when()
1862 < curTick()))
1863 writeDoneEvent.pop_front();
1864
1865 writeDoneEvent.push_back(
1866 EventFunctionWrapper([this]{ writeDone(); },
1867 name()));
1868 assert(!writeDoneEvent.back().scheduled());
1869
1871 struct transferInfo new_transfer;
1872 new_transfer.offset = SCSIDiskOffset;
1873 new_transfer.size = size;
1874 new_transfer.lunID = lun_id;
1875 new_transfer.filePointer = 0;
1876 SSDWriteinfo.push_back(new_transfer);
1877
1879 SSDWriteinfo.back().buffer.resize(size);
1880
1882 dmaPort.dmaAction(MemCmd::ReadReq, start, size,
1883 &writeDoneEvent.back(),
1884 &SSDWriteinfo.back().buffer[0], 0);
1885 //yes, a readreq at a write device function is correct.
1886 DPRINTF(UFSHostDevice, "Write to disk scheduled\n");
1887
1888 } else {
1889 assert(!additional_action->scheduled());
1890 dmaPort.dmaAction(MemCmd::ReadReq, start, size,
1891 additional_action, destination, 0);
1892 DPRINTF(UFSHostDevice, "Write scheduled\n");
1893 }
1894}
1895
1901void
1902UFSHostDevice::manageWriteTransfer(uint8_t LUN, uint64_t offset, uint32_t
1903 sg_table_length, struct UFSHCDSGEntry*
1904 sglist)
1905{
1906 struct writeToDiskBurst next_packet;
1907
1908 next_packet.SCSIDiskOffset = offset;
1909
1910 UFSDevice[LUN]->setTotalWrite(sg_table_length);
1911
1916 for (uint32_t count = 0; count < sg_table_length; count++) {
1917 next_packet.start = sglist[count].upperAddr;
1918 next_packet.start = (next_packet.start << 32) |
1919 (sglist[count].baseAddr & 0xFFFFFFFF);
1920 next_packet.LUN = LUN;
1921 DPRINTF(UFSHostDevice, "Write data DMA start: 0x%8x\n",
1922 next_packet.start);
1923 DPRINTF(UFSHostDevice, "Write data DMA size: 0x%8x\n",
1924 (sglist[count].size + 1));
1925 assert(sglist[count].size > 0);
1926
1927 if (count != 0)
1928 next_packet.SCSIDiskOffset = next_packet.SCSIDiskOffset +
1929 (sglist[count - 1].size + 1);
1930
1931 next_packet.size = sglist[count].size + 1;
1932
1934 if (dmaWriteInfo.empty())
1935 writeDevice(NULL, true, next_packet.start, next_packet.size,
1936 NULL, next_packet.SCSIDiskOffset, next_packet.LUN);
1937 else
1938 DPRINTF(UFSHostDevice, "Write not initiated queue: %d\n",
1939 dmaWriteInfo.size());
1940
1941 dmaWriteInfo.push_back(next_packet);
1942 DPRINTF(UFSHostDevice, "Write Location: 0x%8x\n",
1943 next_packet.SCSIDiskOffset);
1944
1945 DPRINTF(UFSHostDevice, "Write transfer #: 0x%8x\n", count + 1);
1946
1948 stats.totalWrittenSSD += (sglist[count].size + 1);
1949 }
1950
1953}
1954
1960void
1962{
1964 assert(dmaWriteInfo.size() > 0);
1965 dmaWriteInfo.pop_front();
1966 assert(SSDWriteinfo.size() > 0);
1967 uint32_t lun = SSDWriteinfo.front().lunID;
1968
1970 DPRINTF(UFSHostDevice, "Write done entered, queue: %d\n",
1971 UFSDevice[lun]->SSDWriteDoneInfo.size());
1973 UFSDevice[lun]->writeFlash(&SSDWriteinfo.front().buffer[0],
1974 SSDWriteinfo.front().offset,
1975 SSDWriteinfo.front().size);
1976
1982 UFSDevice[lun]->SSDWriteDoneInfo.push_back(SSDWriteinfo.front());
1983 SSDWriteinfo.pop_front();
1984
1987 UFSDevice[lun]->SSDWriteStart();
1988
1990 stats.currentWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size();
1991 stats.averageWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size();
1993
1995 if (!dmaWriteInfo.empty())
1996 writeDevice(NULL, true, dmaWriteInfo.front().start,
1997 dmaWriteInfo.front().size, NULL,
1998 dmaWriteInfo.front().SCSIDiskOffset,
1999 dmaWriteInfo.front().LUN);
2000 DPRINTF(UFSHostDevice, "Write done end\n");
2001}
2002
2006void
2008{
2009 assert(SSDWriteDoneInfo.size() > 0);
2010 flashDevice->writeMemory(
2011 SSDWriteDoneInfo.front().offset,
2012 SSDWriteDoneInfo.front().size, memWriteCallback);
2013
2014 SSDWriteDoneInfo.pop_front();
2015
2016 DPRINTF(UFSHostDevice, "Write is started; left in queue: %d\n",
2017 SSDWriteDoneInfo.size());
2018}
2019
2020
2025void
2027{
2028 DPRINTF(UFSHostDevice, "Write disk, aiming for %d messages, %d so far\n",
2029 totalWrite, amountOfWriteTransfers);
2030
2031 //we have done one extra transfer
2032 ++amountOfWriteTransfers;
2033
2035 assert(totalWrite >= amountOfWriteTransfers && totalWrite != 0);
2036
2038 if (totalWrite == amountOfWriteTransfers) {
2039 DPRINTF(UFSHostDevice, "Write transactions finished\n");
2040 totalWrite = 0;
2041 amountOfWriteTransfers = 0;
2042
2043 //Callback UFS Host
2044 setSignal();
2045 signalDone();
2046 }
2047
2048}
2049
2055void
2056UFSHostDevice::readDevice(bool lastTransfer, Addr start, uint32_t size,
2057 uint8_t* destination, bool no_cache, Event*
2058 additional_action)
2059{
2060 DPRINTF(UFSHostDevice, "Read start: 0x%8x; Size: %d, data[0]: 0x%8x\n",
2061 start, size, (reinterpret_cast<uint32_t *>(destination))[0]);
2062
2064 if (lastTransfer) {
2066 readDoneEvent.push_back(
2067 EventFunctionWrapper([this]{ readDone(); },
2068 name()));
2069 assert(!readDoneEvent.back().scheduled());
2070 dmaPort.dmaAction(MemCmd::WriteReq, start, size,
2071 &readDoneEvent.back(), destination, 0);
2072 //yes, a writereq at a read device function is correct.
2073
2074 } else {
2075 if (additional_action != NULL)
2076 assert(!additional_action->scheduled());
2077
2078 dmaPort.dmaAction(MemCmd::WriteReq, start, size,
2079 additional_action, destination, 0);
2080
2081 }
2082
2083}
2084
2090void
2091UFSHostDevice::manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t
2092 offset, uint32_t sg_table_length,
2093 struct UFSHCDSGEntry* sglist)
2094{
2095 uint32_t size_accum = 0;
2096
2097 DPRINTF(UFSHostDevice, "Data READ size: %d\n", size);
2098
2103 for (uint32_t count = 0; count < sg_table_length; count++) {
2104 struct transferInfo new_transfer;
2105 new_transfer.offset = sglist[count].upperAddr;
2106 new_transfer.offset = (new_transfer.offset << 32) |
2107 (sglist[count].baseAddr & 0xFFFFFFFF);
2108 new_transfer.filePointer = offset + size_accum;
2109 new_transfer.size = (sglist[count].size + 1);
2110 new_transfer.lunID = LUN;
2111
2112 DPRINTF(UFSHostDevice, "Data READ start: 0x%8x; size: %d\n",
2113 new_transfer.offset, new_transfer.size);
2114
2115 UFSDevice[LUN]->SSDReadInfo.push_back(new_transfer);
2116 UFSDevice[LUN]->SSDReadInfo.back().buffer.resize(sglist[count].size
2117 + 1);
2118
2124 UFSDevice[LUN]->readFlash(&UFSDevice[LUN]->
2125 SSDReadInfo.back().buffer[0],
2126 offset + size_accum,
2127 sglist[count].size + 1);
2128
2129 size_accum += (sglist[count].size + 1);
2130
2131 DPRINTF(UFSHostDevice, "Transfer %d; Remaining: 0x%8x, Accumulated:"
2132 " 0x%8x\n", (count + 1), (size-size_accum), size_accum);
2133
2135 stats.totalReadSSD += (sglist[count].size + 1);
2136 stats.currentReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size();
2137 stats.averageReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size();
2138 }
2139
2140 UFSDevice[LUN]->SSDReadStart(sg_table_length);
2141
2144
2145}
2146
2147
2148
2155void
2157{
2158 totalRead = total_read;
2159 for (uint32_t number_handled = 0; number_handled < SSDReadInfo.size();
2160 number_handled++) {
2165 flashDevice->readMemory(SSDReadInfo.front().filePointer,
2166 SSDReadInfo.front().size, memReadCallback);
2167 }
2168
2169}
2170
2171
2176void
2178{
2179 DPRINTF(UFSHostDevice, "SSD read done at lun %d, Aiming for %d messages,"
2180 " %d so far\n", lunID, totalRead, amountOfReadTransfers);
2181
2182 if (totalRead == amountOfReadTransfers) {
2183 totalRead = 0;
2184 amountOfReadTransfers = 0;
2185
2187 setSignal();
2188 signalDone();
2189 }
2190
2191}
2192
2197void
2199{
2200 ++amountOfReadTransfers;
2201
2205 setReadSignal();
2206 deviceReadCallback();
2207
2208 //Are we done yet?
2209 SSDReadDone();
2210}
2211
2217void
2219{
2220 DPRINTF(UFSHostDevice, "Read Callback\n");
2221 uint8_t this_lun = 0;
2222
2223 //while we haven't found the right lun, keep searching
2224 while ((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedRead())
2225 ++this_lun;
2226
2227 DPRINTF(UFSHostDevice, "Found LUN %d messages pending for clean: %d\n",
2228 this_lun, SSDReadPending.size());
2229
2230 if (this_lun < lunAvail) {
2231 //Clear signal.
2232 UFSDevice[this_lun]->clearReadSignal();
2233 SSDReadPending.push_back(UFSDevice[this_lun]->SSDReadInfo.front());
2234 UFSDevice[this_lun]->SSDReadInfo.pop_front();
2235 readGarbageEventQueue.push_back(
2236 EventFunctionWrapper([this]{ readGarbage(); }, name()));
2237
2238 //make sure the queue is popped a the end of the dma transaction
2239 readDevice(false, SSDReadPending.front().offset,
2240 SSDReadPending.front().size,
2241 &SSDReadPending.front().buffer[0], false,
2242 &readGarbageEventQueue.back());
2243
2246 }
2247 else
2248 panic("no read finished in tick %d\n", curTick());
2249}
2250
2255void
2257{
2258 DPRINTF(UFSHostDevice, "Clean read data, %d\n", SSDReadPending.size());
2259 SSDReadPending.pop_front();
2260 readGarbageEventQueue.pop_front();
2261}
2262
2267void
2269{
2271
2272 const uint8_t* temp_HCI_mem = reinterpret_cast<const uint8_t*>(&UFSHCIMem);
2273 SERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem));
2274
2275 uint32_t lun_avail = lunAvail;
2276 SERIALIZE_SCALAR(lun_avail);
2277}
2278
2279
2284void
2286{
2288 uint8_t* temp_HCI_mem = reinterpret_cast<uint8_t*>(&UFSHCIMem);
2289 UNSERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem));
2290
2291 uint32_t lun_avail;
2292 UNSERIALIZE_SCALAR(lun_avail);
2293 assert(lunAvail == lun_avail);
2294}
2295
2296
2303{
2304 if (UFSHCIMem.TRUTRLDBR) {
2305 DPRINTF(UFSHostDevice, "UFSDevice is draining...\n");
2306 return DrainState::Draining;
2307 } else {
2308 DPRINTF(UFSHostDevice, "UFSDevice drained\n");
2309 return DrainState::Drained;
2310 }
2311}
2312
2317void
2319{
2321 return;
2322
2323 if (UFSHCIMem.TRUTRLDBR) {
2324 DPRINTF(UFSHostDevice, "UFSDevice is still draining; with %d active"
2325 " doorbells\n", activeDoorbells);
2326 } else {
2327 DPRINTF(UFSHostDevice, "UFSDevice is done draining\n");
2329 }
2330}
2331
2332} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
virtual void initializeMemory(uint64_t disk_size, uint32_t sector_size)=0
Initialize Memory.
virtual void clearInt(uint32_t num)=0
Clear an interrupt from a device that is connected to the GIC.
virtual void sendInt(uint32_t num)=0
Post an interrupt from a device that is connected to the GIC.
void serialize(CheckpointOut &cp) const override
Serialize an object.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, uint8_t *data, Tick delay, Request::Flags flag=0)
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
void setLE(T v)
Set the value in the data pointer to v as little endian.
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition packet.hh:1062
unsigned getSize() const
Definition packet.hh:817
uint64_t getUintX(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness and zero-extended to 64 bits.
Definition packet.cc:352
Abstract superclass for simulation objects.
static const unsigned int cachingPage[5]
void SSDWriteStart()
SSD write start.
void SSDReadDone()
SSD Read done; Determines if the final callback of the transaction should be made at the end of a rea...
static const unsigned int controlPage[3]
These pages are SCSI specific.
std::function< void()> Callback
UFSSCSIDevice(const UFSHostDeviceParams &p, uint32_t lun_id, const Callback &transfer_cb, const Callback &read_cb)
Constructor and destructor.
Definition ufs_device.cc:78
void writeFlash(uint8_t *writeaddr, uint64_t offset, uint32_t size)
Write flash.
void readFlash(uint8_t *readaddr, uint64_t offset, uint32_t size)
Disk access functions.
void statusCheck(uint8_t status, uint8_t *sensecodelist)
Status of SCSI.
Callback signalDone
Callbacks between Host and Device.
Callback memReadCallback
Callbacks between Device and Memory.
static const unsigned int recoveryPage[3]
struct SCSIReply SCSICMDHandle(uint32_t *SCSI_msg)
SCSI command handle function; determines what the command is and returns a reply structure that allow...
struct LUNInfo lunInfo
Logic unit info; needed for SCSI Info messages and LU identification.
void readCallback()
Functions to indicate that the action to the SSD has completed.
void SSDReadStart(uint32_t total_read)
Start the transactions to (and from) the disk The host will queue all the transactions.
void SSDWriteDone()
SSD Write Done; This is the callback function for the memory model.
Host controller layer: This is your Host controller This layer handles the UFS functionality.
int readPendingNum
Track number of DMA transactions in progress.
void taskHandler(struct UTPUPIUTaskReq *request_in, uint32_t req_pos, Addr finaladdress, uint32_t finalsize)
Task handler function.
std::deque< EventFunctionWrapper > taskEventQueue
Multiple tasks transfers can be scheduled at once for the device, the only thing we know for sure abo...
void generateInterrupt()
set interrupt and sort out the doorbell register.
void writeDone()
Write done After a DMA write with data intended for the disk, this function is called.
std::deque< struct taskStart > taskInfo
When a task/transfer is started it needs information about the task/transfer it is about to perform.
std::deque< struct transferInfo > SSDWriteinfo
Information from DMA transaction to disk.
static const unsigned int UICCommandReady
std::deque< EventFunctionWrapper > transferEventQueue
EventFunctionWrapper SCSIResumeEvent
The events that control the functionality.
void serialize(CheckpointOut &cp) const override
Serialize; needed to make checkpoints.
void transferHandler(struct UTPTransferReqDesc *request_in, int req_pos, Addr finaladdress, uint32_t finalsize, uint32_t done)
Transfer handler function.
Tick transactionStart[32]
Helper for latency stats These variables keep track of the latency for every doorbell.
const Addr pioAddr
Host controller information.
void commandHandler()
Command handler function.
HCIMem UFSHCIMem
Host controller memory.
struct SCSIReply request_out_datain
SCSI reply structure, used for direct answering.
static const unsigned int UTPTaskREQCOMPL
void clearInterrupt()
Interrupt control functions.
static const unsigned int UTPTransferREQCOMPL
Bits of interest within UFS data packages.
static const unsigned int UICCommandCOMPL
void writeDevice(Event *additional_action, bool toDisk, Addr start, int size, uint8_t *destination, uint64_t SCSIDiskOffset, uint32_t lun_id)
DMA transfer functions These allow the host to push/pull the data to the memory The provided event in...
void finalUTP()
final UTP, sends the last acknowledge data structure to the system; prepares the clean up functions.
std::deque< struct writeToDiskBurst > dmaWriteInfo
Information to get a DMA transaction.
uint32_t transferTrack
Track the transfer This is allows the driver to "group" certain transfers together by using a tag in ...
DrainState drain() override
Drain; needed to enable checkpoints.
void setValues()
Initialization function.
void requestHandler()
Handler functions.
void unserialize(CheckpointIn &cp) override
Unserialize; needed to restore from checkpoints.
void manageWriteTransfer(uint8_t LUN, uint64_t offset, uint32_t sg_table_length, struct UFSHCDSGEntry *sglist)
Disk transfer management functions these set up the queues, and initiated them, leading to the data t...
struct SCSIResumeInfo SCSIInfo
SCSI resume info information structure for SCSI resume.
Tick read(PacketPtr pkt) override
register access functions
struct UFSHostDeviceStats stats
RequestHandler stats.
void readGarbage()
Read garbage A read from disk data structure can vary in size and is therefor allocated on creation.
std::deque< struct transferStart > transferEnd
To finish the transaction one needs information about the original message.
std::deque< EventFunctionWrapper > readDoneEvent
Transfer flow events Basically these events form two queues, one from memory to UFS device (DMA) and ...
uint32_t countInt
interrupt verification This keeps track of the number of interrupts generated.
std::deque< struct UTPTransferReqDesc * > garbage
garbage queue, ensure clearing of the allocated memory
uint8_t activeDoorbells
Statistics helper variables Active doorbells indicates how many doorbells are in teh process of being...
void manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t offset, uint32_t sg_table_length, struct UFSHCDSGEntry *sglist)
Manage read transfer.
std::vector< UFSSCSIDevice * > UFSDevice
logic units connected to the UFS Host device Note again that the "device" as such is represented by o...
std::deque< struct transferInfo > SSDReadPending
Information from the Disk, waiting to be pushed to the DMA.
void SCSIResume(uint32_t lun_id)
Starts the scsi handling function in the apropriate Logic unit, prepares the right data transfer sche...
std::deque< EventFunctionWrapper > writeDoneEvent
Tick write(PacketPtr pkt) override
UFSHCD write function.
std::deque< struct transferStart > transferStartInfo
AddrRangeList getAddrRanges() const override
Address range functions.
std::deque< EventFunctionWrapper > readGarbageEventQueue
Event after a read to clean up the UTP data structures.
EventFunctionWrapper UTPEvent
Wait for the moment where we can send the last frame.
void readCallback()
Read callback Call back function for the logic units to indicate the completion of a read action.
UFSHostDevice(const UFSHostDeviceParams &p)
Constructor for the UFS Host device.
void transferStart()
Transfer Start function.
void taskStart()
Task Start function.
void transferDone(Addr responseStartAddr, uint32_t req_pos, struct UTPUPIURSP request_out, uint32_t size, Addr address, uint8_t *destination, bool finished, uint32_t lun_id)
transfer done, the beginning of the final stage of the transfer.
void LUNSignal()
LU callback function to indicate that the action has completed.
void readDone()
Read done Started at the end of a transaction after the last read action.
void readDevice(bool lastTransfer, Addr SCSIStart, uint32_t SCSISize, uint8_t *SCSIDestination, bool no_cache, Event *additional_action)
Dma transaction function: read device.
void checkDrain()
Checkdrain; needed to enable checkpoints.
const uint32_t lunAvail
const uint8_t UFSSlots
void SCSIStart()
Transfer SCSI function.
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Statistics container.
Definition group.hh:93
Histogram & init(size_type size)
Set the parameters of this histogram.
size_type size() const
Return the number of elements, always 1 for a scalar.
Counter value() const
Return the current value of this stat as its base type.
#define SectorSize
Definition disk_image.hh:44
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
AddrRange RangeSize(Addr start, Addr size)
constexpr int findLsbSet(uint64_t val)
Returns the bit position of the LSB that is set in the input That function will either use a builtin ...
Definition bitfield.hh:369
void signalDrainDone() const
Signal that an object is drained.
Definition drain.hh:305
DrainState drainState() const
Return the current drain state of an object.
Definition drain.hh:324
DrainState
Object drain/handover states.
Definition drain.hh:75
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
#define UNSERIALIZE_ARRAY(member, size)
Definition serialize.hh:618
#define SERIALIZE_ARRAY(member, size)
Definition serialize.hh:610
#define warn(...)
Definition logging.hh:256
#define inform(...)
Definition logging.hh:257
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 5, 0 > status
Bitfield< 0 > p
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition info.hh:61
const FlagsType nozero
Don't print if this is zero.
Definition info.hh:67
const FlagsType none
Nothing extra to print.
Definition info.hh:53
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
T betoh(T value)
Definition byteswap.hh:175
uint64_t Tick
Tick count type.
Definition types.hh:58
statistics::Formula & simSeconds
Definition stats.cc:45
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
Host Controller Interface This is a set of registers that allow the driver to control the transaction...
uint32_t TMUTMRLBA
Task control registers.
uint32_t TRUTRLBA
Transfer control registers.
uint32_t ORInterruptStatus
Operation and runtime registers.
uint32_t CMDUICCMDR
Command registers.
uint32_t HCCAP
Specify the host capabilities.
SCSI reply structure.
struct UTPTransferReqDesc * RequestIn
std::vector< uint8_t > destination
struct UFSHCDSGEntry - UFSHCI PRD Entry baseAddr: Lower 32bit physical address DW-0 upperAddr: Upper ...
statistics::Average averageSCSIQueue
Average Queue lengths.
statistics::Formula averageReadSSDBW
Average bandwidth for reads and writes.
statistics::Scalar totalWriteDiskTransactions
UFSHostDeviceStats(UFSHostDevice *parent)
Amount of data read/written.
statistics::Histogram transactionLatency
Histogram of latencies.
statistics::Scalar totalReadSSD
Amount of data read/written.
statistics::Formula curDoorbell
Number of doorbells rung.
statistics::Scalar currentSCSIQueue
Queue lengths.
std::vector< uint32_t > dataMsg
struct UTPUPIUHeader header
struct UTPTransferReqDesc - UTRD structure header: UTRD header DW-0 to DW-3 commandDescBaseAddrLo: UC...
struct gem5::UFSHostDevice::UTPTransferReqDesc::RequestDescHeader header
struct UTPUPIURSP - Response UPIU structure header: UPIU header DW-0 to DW-2 residualTransferCount: R...
struct UTPUPIUTaskReq - Task request UPIU structure header - UPIU header structure DW0 to DW-2 inputP...
Task start information.
Different events, and scenarios require different types of information.
Transfer start information.
struct UTPTransferReqDesc * destination
Disk transfer burst information.
const std::string & name()
Definition trace.cc:48
This is a base class for UFS devices The UFS interface consists out of one host controller which conn...

Generated on Tue Jun 18 2024 16:24:03 for gem5 by doxygen 1.11.0