gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  * Authors: Rene de Jong
38  */
39 
72 #include "dev/arm/ufs_device.hh"
73 
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 {
101  signalDone = transfer_cb;
104  deviceReadCallback = read_cb;
107 
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);
128 }
129 
130 
136 const unsigned int UFSHostDevice::UFSSCSIDevice::controlPage[3] =
137  {0x01400A0A, 0x00000000,
138  0x0000FFFF};
139 const unsigned int UFSHostDevice::UFSSCSIDevice::recoveryPage[3] =
140  {0x03800A01, 0x00000000,
141  0xFFFF0003};
142 const unsigned int UFSHostDevice::UFSSCSIDevice::cachingPage[5] =
143  {0x00011208, 0x00000000,
144  0x00000000, 0x00000020,
145  0x00000000};
146 
148 
162 {
163  struct SCSIReply scsi_out;
164  memset(&scsi_out, 0, sizeof(struct SCSIReply));
165 
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]);
182  switch (SCSI_msg[4] & 0xFF) {
183 
184  case SCSIInquiry: {
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: {
200  scsi_out.expectMore = 0x02;
201  scsi_out.msgSize = 0;
202 
203  uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
204 
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 
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 
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 
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 
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 
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: {
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: {
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: {
362  scsi_out.msgSize = 0;
363 
364  uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
365 
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 
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: {
391  uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
392 
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 
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 
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 
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 
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 
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: {
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 
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: {
607  scsi_out.expectMore = 0x02;
608 
609  uint8_t* tempptr = reinterpret_cast<uint8_t*>(&SCSI_msg[4]);
610 
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: {
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 
674 void
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 
691 void
693  uint32_t size)
694 {
696  for (int count = 0; count < (size / SectorSize); count++)
697  flashDisk->read(&(readaddr[SectorSize*count]), (offset /
698  SectorSize) + count);
699 }
700 
705 void
707  uint32_t size)
708 {
710  for (int count = 0; count < (size / SectorSize); count++)
711  flashDisk->write(&(writeaddr[SectorSize * count]),
712  (offset / SectorSize) + count);
713 }
714 
719 UFSHostDevice::UFSHostDevice(const UFSHostDeviceParams* p) :
720  DmaDevice(p),
721  pioAddr(p->pio_addr),
722  pioSize(0x0FFF),
723  pioDelay(p->pio_latency),
724  intNum(p->int_num),
725  gic(p->gic),
726  lunAvail(p->image.size()),
727  UFSSlots(p->ufs_slots - 1),
728  readPendingNum(0),
729  writePendingNum(0),
730  activeDoorbells(0),
731  pendingDoorbells(0),
732  countInt(0),
733  transferTrack(0),
734  taskCommandTrack(0),
735  idlePhaseStart(0),
736  SCSIResumeEvent(this),
737  UTPEvent(this)
738 {
739  DPRINTF(UFSHostDevice, "The hostcontroller hosts %d Logic units\n",
740  lunAvail);
741  UFSDevice.resize(lunAvail);
742 
744  &UFSHostDevice::LUNSignal>(this);
747 
748  for (int count = 0; count < lunAvail; count++) {
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 
768 UFSHostDeviceParams::create()
769 {
770  return new UFSHostDevice(this);
771 }
772 
773 
774 void
776 {
778 
779  using namespace Stats;
780 
781  std::string UFSHost_name = name() + ".UFSDiskHost";
782 
783  // Register the stats
786  .name(UFSHost_name + ".currentSCSIQueue")
787  .desc("Most up to date length of the command queue")
788  .flags(none);
790  .name(UFSHost_name + ".currentReadSSDQueue")
791  .desc("Most up to date length of the read SSD queue")
792  .flags(none);
794  .name(UFSHost_name + ".currentWriteSSDQueue")
795  .desc("Most up to date length of the write SSD queue")
796  .flags(none);
797 
800  .name(UFSHost_name + ".totalReadSSD")
801  .desc("Number of bytes read from SSD")
802  .flags(none);
803 
805  .name(UFSHost_name + ".totalWrittenSSD")
806  .desc("Number of bytes written to SSD")
807  .flags(none);
808 
810  .name(UFSHost_name + ".totalReadDiskTransactions")
811  .desc("Number of transactions from disk")
812  .flags(none);
814  .name(UFSHost_name + ".totalWriteDiskTransactions")
815  .desc("Number of transactions to disk")
816  .flags(none);
818  .name(UFSHost_name + ".totalReadUFSTransactions")
819  .desc("Number of transactions from device")
820  .flags(none);
822  .name(UFSHost_name + ".totalWriteUFSTransactions")
823  .desc("Number of transactions to device")
824  .flags(none);
825 
828  .name(UFSHost_name + ".averageReadSSDBandwidth")
829  .desc("Average read bandwidth (bytes/s)")
830  .flags(nozero);
831 
833 
835  .name(UFSHost_name + ".averageWriteSSDBandwidth")
836  .desc("Average write bandwidth (bytes/s)")
837  .flags(nozero);
838 
840 
842  .name(UFSHost_name + ".averageSCSIQueueLength")
843  .desc("Average command queue length")
844  .flags(nozero);
846  .name(UFSHost_name + ".averageReadSSDQueueLength")
847  .desc("Average read queue length")
848  .flags(nozero);
850  .name(UFSHost_name + ".averageWriteSSDQueueLength")
851  .desc("Average write queue length")
852  .flags(nozero);
853 
856  .name(UFSHost_name + ".curDoorbell")
857  .desc("Most up to date number of doorbells used")
858  .flags(none);
859 
861 
863  .name(UFSHost_name + ".maxDoorbell")
864  .desc("Maximum number of doorbells utilized")
865  .flags(none);
867  .name(UFSHost_name + ".averageDoorbell")
868  .desc("Average number of Doorbells used")
869  .flags(nozero);
870 
873  .init(100)
874  .name(UFSHost_name + ".transactionLatency")
875  .desc("Histogram of transaction times")
876  .flags(pdf);
877 
879  .init(100)
880  .name(UFSHost_name + ".idlePeriods")
881  .desc("Histogram of idle times")
882  .flags(pdf);
883 
884 }
885 
890 {
896  UFSHCIMem.HCCAP = 0x06070000 | (UFSSlots & 0x1F);
897  UFSHCIMem.HCversion = 0x00010000; //version is 1.0
898  UFSHCIMem.HCHCDDID = 0xAA003C3C;// Arbitrary number
899  UFSHCIMem.HCHCPMID = 0x41524D48; //ARMH (not an official MIPI number)
900  UFSHCIMem.TRUTRLDBR = 0x00;
901  UFSHCIMem.TMUTMRLDBR = 0x00;
902  UFSHCIMem.CMDUICCMDR = 0x00;
903  // We can process CMD, TM, TR, device present
905  UFSHCIMem.TRUTRLBA = 0x00;
906  UFSHCIMem.TRUTRLBAU = 0x00;
907  UFSHCIMem.TMUTMRLBA = 0x00;
908  UFSHCIMem.TMUTMRLBAU = 0x00;
909 }
910 
917 {
918  AddrRangeList ranges;
919  ranges.push_back(RangeSize(pioAddr, pioSize));
920  return ranges;
921 }
922 
928 Tick
930 {
931  uint32_t data = 0;
932 
933  switch (pkt->getAddr() & 0xFF)
934  {
935 
937  data = UFSHCIMem.HCCAP;
938  break;
939 
940  case regUFSVersion:
941  data = UFSHCIMem.HCversion;
942  break;
943 
944  case regControllerDEVID:
945  data = UFSHCIMem.HCHCDDID;
946  break;
947 
948  case regControllerPRODID:
949  data = UFSHCIMem.HCHCPMID;
950  break;
951 
952  case regInterruptStatus:
955  //TODO: Revise and extend
956  clearInterrupt();
957  break;
958 
959  case regInterruptEnable:
961  break;
962 
963  case regControllerStatus:
965  break;
966 
967  case regControllerEnable:
969  break;
970 
972  data = UFSHCIMem.ORUECPA;
973  break;
974 
976  data = UFSHCIMem.ORUECDL;
977  break;
978 
980  data = UFSHCIMem.ORUECN;
981  break;
982 
984  data = UFSHCIMem.ORUECT;
985  break;
986 
987  case regUICErrorCodeDME:
988  data = UFSHCIMem.ORUECDME;
989  break;
990 
992  data = UFSHCIMem.ORUTRIACR;
993  break;
994 
996  data = UFSHCIMem.TRUTRLBA;
997  break;
998 
1000  data = UFSHCIMem.TRUTRLBAU;
1001  break;
1002 
1004  data = UFSHCIMem.TRUTRLDBR;
1005  break;
1006 
1008  data = UFSHCIMem.TRUTRLCLR;
1009  break;
1010 
1012  data = UFSHCIMem.TRUTRLRSR;
1013  break;
1014 
1016  data = UFSHCIMem.TMUTMRLBA;
1017  break;
1018 
1020  data = UFSHCIMem.TMUTMRLBAU;
1021  break;
1022 
1023  case regUTPTaskREQDoorbell:
1024  data = UFSHCIMem.TMUTMRLDBR;
1025  break;
1026 
1028  data = UFSHCIMem.TMUTMRLCLR;
1029  break;
1030 
1032  data = UFSHCIMem.TMUTMRLRSR;
1033  break;
1034 
1035  case regUICCommand:
1036  data = UFSHCIMem.CMDUICCMDR;
1037  break;
1038 
1039  case regUICCommandArg1:
1040  data = UFSHCIMem.CMDUCMDARG1;
1041  break;
1042 
1043  case regUICCommandArg2:
1044  data = UFSHCIMem.CMDUCMDARG2;
1045  break;
1046 
1047  case regUICCommandArg3:
1048  data = UFSHCIMem.CMDUCMDARG3;
1049  break;
1050 
1051  default:
1052  data = 0x00;
1053  break;
1054  }
1055 
1056  pkt->set<uint32_t>(data);
1057  pkt->makeResponse();
1058  return pioDelay;
1059 }
1060 
1066 Tick
1068 {
1069  uint32_t data = 0;
1070 
1071  switch (pkt->getSize()) {
1072 
1073  case 1:
1074  data = pkt->get<uint8_t>();
1075  break;
1076 
1077  case 2:
1078  data = pkt->get<uint16_t>();
1079  break;
1080 
1081  case 4:
1082  data = pkt->get<uint32_t>();
1083  break;
1084 
1085  default:
1086  panic("Undefined UFSHCD controller write size!\n");
1087  break;
1088  }
1089 
1090  switch (pkt->getAddr() & 0xFF)
1091  {
1092  case regControllerCapabilities://you shall not write to this
1093  break;
1094 
1095  case regUFSVersion://you shall not write to this
1096  break;
1097 
1098  case regControllerDEVID://you shall not write to this
1099  break;
1100 
1101  case regControllerPRODID://you shall not write to this
1102  break;
1103 
1104  case regInterruptStatus://you shall not write to this
1105  break;
1106 
1107  case regInterruptEnable:
1109  break;
1110 
1111  case regControllerStatus:
1113  break;
1114 
1115  case regControllerEnable:
1117  break;
1118 
1121  break;
1122 
1125  break;
1126 
1128  UFSHCIMem.ORUECN = data;
1129  break;
1130 
1132  UFSHCIMem.ORUECT = data;
1133  break;
1134 
1135  case regUICErrorCodeDME:
1137  break;
1138 
1141  break;
1142 
1145  if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) &&
1146  ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU)!= 0x00))
1148  break;
1149 
1151  UFSHCIMem.TRUTRLBAU = data;
1152  if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) &&
1153  ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00))
1155  break;
1156 
1158  if (!(UFSHCIMem.TRUTRLDBR) && data)
1161  requestHandler();
1162  break;
1163 
1166  break;
1167 
1170  break;
1171 
1174  if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) &&
1175  ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00))
1177  break;
1178 
1181  if (((UFSHCIMem.TRUTRLBA | UFSHCIMem.TRUTRLBAU) != 0x00) &&
1182  ((UFSHCIMem.TMUTMRLBA | UFSHCIMem.TMUTMRLBAU) != 0x00))
1184  break;
1185 
1186  case regUTPTaskREQDoorbell:
1188  requestHandler();
1189  break;
1190 
1193  break;
1194 
1197  break;
1198 
1199  case regUICCommand:
1201  requestHandler();
1202  break;
1203 
1204  case regUICCommandArg1:
1206  break;
1207 
1208  case regUICCommandArg2:
1210  break;
1211 
1212  case regUICCommandArg3:
1214  break;
1215 
1216  default:break;//nothing happens, you try to access a register that
1217  //does not exist
1218 
1219  }
1220 
1221  pkt->makeResponse();
1222  return pioDelay;
1223 }
1224 
1230 void
1232 {
1233  Addr address = 0x00;
1234  int mask = 0x01;
1235  int size;
1236  int count = 0;
1237  struct taskStart task_info;
1238  struct transferStart transferstart_info;
1239  transferstart_info.done = 0;
1240 
1246  while (((UFSHCIMem.CMDUICCMDR > 0x00) |
1247  ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) |
1248  ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00)) ) {
1249 
1250  if (UFSHCIMem.CMDUICCMDR > 0x00) {
1255  commandHandler();
1258  UFSHCIMem.CMDUICCMDR = 0x00;
1259  return; //command, nothing more we can do
1260 
1261  } else if ((UFSHCIMem.TMUTMRLDBR ^ taskCommandTrack) > 0x00) {
1266  size = sizeof(UTPUPIUTaskReq);
1269  address = UFSHCIMem.TMUTMRLBAU;
1270  //<-64 bit
1271  address = (count * size) + (address << 32) +
1273  taskCommandTrack |= mask << count;
1274 
1275  inform("UFSmodel received a task from the system; this might"
1276  " lead to untested behaviour.\n");
1277 
1278  task_info.mask = mask << count;
1279  task_info.address = address;
1280  task_info.size = size;
1281  task_info.done = UFSHCIMem.TMUTMRLDBR;
1282  taskInfo.push_back(task_info);
1283  taskEventQueue.push_back(this);
1284  writeDevice(&taskEventQueue.back(), false, address, size,
1285  reinterpret_cast<uint8_t*>
1286  (&taskInfo.back().destination), 0, 0);
1287 
1288  } else if ((UFSHCIMem.TRUTRLDBR ^ transferTrack) > 0x00) {
1294  size = sizeof(UTPTransferReqDesc);
1297  address = UFSHCIMem.TRUTRLBAU;
1298  //<-64 bit
1299  address = (count * size) + (address << 32) + UFSHCIMem.TRUTRLBA;
1300 
1301  transferTrack |= mask << count;
1302  DPRINTF(UFSHostDevice, "Doorbell register: 0x%8x select #:"
1303  " 0x%8x completion info: 0x%8x\n", UFSHCIMem.TRUTRLDBR,
1304  count, transferstart_info.done);
1305 
1306  transferstart_info.done = UFSHCIMem.TRUTRLDBR;
1307 
1309  transactionStart[count] = curTick(); //note the start time
1310  ++activeDoorbells;
1314 
1320  transferstart_info.mask = mask << count;
1321  transferstart_info.address = address;
1322  transferstart_info.size = size;
1323  transferstart_info.done = UFSHCIMem.TRUTRLDBR;
1324  transferStartInfo.push_back(transferstart_info);
1325 
1327  transferStartInfo.back().destination = new struct
1329  DPRINTF(UFSHostDevice, "Initial transfer start: 0x%8x\n",
1330  transferstart_info.done);
1331  transferEventQueue.push_back(this);
1332 
1333  if (transferEventQueue.size() < 2) {
1334  writeDevice(&transferEventQueue.front(), false,
1335  address, size, reinterpret_cast<uint8_t*>
1336  (transferStartInfo.front().destination),0, 0);
1337  DPRINTF(UFSHostDevice, "Transfer scheduled\n");
1338  }
1339  }
1340  }
1341 }
1342 
1347 void
1349 {
1350  DPRINTF(UFSHostDevice, "Task start");
1351  taskHandler(&taskInfo.front().destination, taskInfo.front().mask,
1352  taskInfo.front().address, taskInfo.front().size);
1353  taskInfo.pop_front();
1354  taskEventQueue.pop_front();
1355 }
1356 
1361 void
1363 {
1364  DPRINTF(UFSHostDevice, "Enter transfer event\n");
1365  transferHandler(transferStartInfo.front().destination,
1366  transferStartInfo.front().mask,
1367  transferStartInfo.front().address,
1368  transferStartInfo.front().size,
1369  transferStartInfo.front().done);
1370 
1371  transferStartInfo.pop_front();
1372  DPRINTF(UFSHostDevice, "Transfer queue size at end of event: "
1373  "0x%8x\n", transferEventQueue.size());
1374 }
1375 
1381 void
1383 {
1384  if (UFSHCIMem.CMDUICCMDR == 0x16) {
1385  UFSHCIMem.ORHostControllerStatus |= 0x0F;//link startup
1386  }
1387 
1388 }
1389 
1395 void
1397  uint32_t req_pos, Addr finaladdress, uint32_t
1398  finalsize)
1399 {
1404  inform("taskHandler\n");
1405  inform("%8x\n", request_in->header.dWord0);
1406  inform("%8x\n", request_in->header.dWord1);
1407  inform("%8x\n", request_in->header.dWord2);
1408 
1409  request_in->header.dWord2 &= 0xffffff00;
1410 
1411  UFSHCIMem.TMUTMRLDBR &= ~(req_pos);
1412  taskCommandTrack &= ~(req_pos);
1414 
1415  readDevice(true, finaladdress, finalsize, reinterpret_cast<uint8_t*>
1416  (request_in), true, NULL);
1417 
1418 }
1419 
1431 void
1433  int req_pos, Addr finaladdress, uint32_t
1434  finalsize, uint32_t done)
1435 {
1436 
1437  Addr cmd_desc_addr = 0x00;
1438 
1439 
1440  //acknowledge handling of the message
1441  DPRINTF(UFSHostDevice, "SCSI message detected\n");
1442  request_in->header.dWord2 &= 0xffffff00;
1443  SCSIInfo.RequestIn = request_in;
1444  SCSIInfo.reqPos = req_pos;
1445  SCSIInfo.finalAddress = finaladdress;
1446  SCSIInfo.finalSize = finalsize;
1447  SCSIInfo.destination.resize(request_in->PRDTableOffset * 4
1448  + request_in->PRDTableLength * sizeof(UFSHCDSGEntry));
1449  SCSIInfo.done = done;
1450 
1451  assert(!SCSIResumeEvent.scheduled());
1455  cmd_desc_addr = request_in->commandDescBaseAddrHi;
1456  cmd_desc_addr = (cmd_desc_addr << 32) |
1457  (request_in->commandDescBaseAddrLo & 0xffffffff);
1458 
1459  writeDevice(&SCSIResumeEvent, false, cmd_desc_addr,
1460  SCSIInfo.destination.size(), &SCSIInfo.destination[0],0, 0);
1461 
1462  DPRINTF(UFSHostDevice, "SCSI scheduled\n");
1463 
1464  transferEventQueue.pop_front();
1465 }
1466 
1474 void
1476 {
1477  DPRINTF(UFSHostDevice, "SCSI message on hold until ready\n");
1478  uint32_t LUN = SCSIInfo.destination[2];
1479  UFSDevice[LUN]->SCSIInfoQueue.push_back(SCSIInfo);
1480 
1481  DPRINTF(UFSHostDevice, "SCSI queue %d has %d elements\n", LUN,
1482  UFSDevice[LUN]->SCSIInfoQueue.size());
1483 
1485  if (UFSDevice[LUN]->SCSIInfoQueue.size() < 2) //LUN is available
1486  SCSIResume(LUN);
1487 
1488  else if (UFSDevice[LUN]->SCSIInfoQueue.size() > 32)
1489  panic("SCSI queue is getting too big %d\n", UFSDevice[LUN]->
1490  SCSIInfoQueue.size());
1491 
1496  if (!transferEventQueue.empty()) {
1497 
1502  writeDevice(&transferEventQueue.front(), false,
1503  transferStartInfo.front().address,
1504  transferStartInfo.front().size, reinterpret_cast<uint8_t*>
1505  (transferStartInfo.front().destination), 0, 0);
1506 
1507  DPRINTF(UFSHostDevice, "Transfer scheduled");
1508  }
1509 }
1510 
1519 void
1521 {
1522  DPRINTF(UFSHostDevice, "SCSIresume\n");
1523  if (UFSDevice[lun_id]->SCSIInfoQueue.empty())
1524  panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id,
1526 
1528  struct UTPTransferReqDesc* request_in = UFSDevice[lun_id]->
1529  SCSIInfoQueue.front().RequestIn;
1530 
1531  uint32_t req_pos = UFSDevice[lun_id]->SCSIInfoQueue.front().reqPos;
1532 
1533  Addr finaladdress = UFSDevice[lun_id]->SCSIInfoQueue.front().
1534  finalAddress;
1535 
1536  uint32_t finalsize = UFSDevice[lun_id]->SCSIInfoQueue.front().finalSize;
1537 
1538  uint32_t* transfercommand = reinterpret_cast<uint32_t*>
1539  (&(UFSDevice[lun_id]->SCSIInfoQueue.front().destination[0]));
1540 
1541  DPRINTF(UFSHostDevice, "Task tag: 0x%8x\n", transfercommand[0]>>24);
1543  request_out_datain = UFSDevice[(transfercommand[0] & 0xFF0000) >> 16]->
1544  SCSICMDHandle(transfercommand);
1545 
1547 
1552  request_in->header.dWord0 = ((request_in->header.dWord0 >> 24) == 0x21)
1553  ? 0x36 : 0x21;
1554  UFSDevice[lun_id]->transferInfo.requestOut.header.dWord0 =
1555  request_in->header.dWord0 | (request_out_datain.LUN << 8)
1556  | (transfercommand[0] & 0xFF000000);
1558  UFSDevice[lun_id]->transferInfo.requestOut.header.dWord1 = 0x00000000 |
1559  (request_out_datain.status << 24);
1561  UFSDevice[lun_id]->transferInfo.requestOut.header.dWord2 = 0x00000000 |
1562  ((request_out_datain.senseSize + 2) << 24) | 0x05;
1564  UFSDevice[lun_id]->transferInfo.requestOut.senseDataLen =
1566 
1567  //data
1568  for (uint8_t count = 0; count<request_out_datain.senseSize; count++) {
1569  UFSDevice[lun_id]->transferInfo.requestOut.senseData[count] =
1571  }
1572 
1573  /*
1574  * At position defined by "request_in->PRDTableOffset" (counting 32 bit
1575  * words) in array "transfercommand" we have a scatter gather list, which
1576  * is usefull to us if we interpreted it as a UFSHCDSGEntry structure.
1577  */
1578  struct UFSHCDSGEntry* sglist = reinterpret_cast<UFSHCDSGEntry*>
1579  (&(transfercommand[(request_in->PRDTableOffset)]));
1580 
1581  uint32_t length = request_in->PRDTableLength;
1582  DPRINTF(UFSHostDevice, "# PRDT entries: %d\n", length);
1583 
1584  Addr response_addr = request_in->commandDescBaseAddrHi;
1585  response_addr = (response_addr << 32) |
1586  ((request_in->commandDescBaseAddrLo +
1587  (request_in->responseUPIULength << 2)) & 0xffffffff);
1588 
1590  UFSDevice[lun_id]->transferInfo.responseStartAddr = response_addr;
1591  UFSDevice[lun_id]->transferInfo.reqPos = req_pos;
1592  UFSDevice[lun_id]->transferInfo.size = finalsize;
1593  UFSDevice[lun_id]->transferInfo.address = finaladdress;
1594  UFSDevice[lun_id]->transferInfo.destination = reinterpret_cast<uint8_t*>
1595  (UFSDevice[lun_id]->SCSIInfoQueue.front().RequestIn);
1596  UFSDevice[lun_id]->transferInfo.finished = true;
1597  UFSDevice[lun_id]->transferInfo.lunID = request_out_datain.LUN;
1598 
1604  if (request_out_datain.expectMore == 0x01) {
1607  length, sglist);
1608 
1609  } else if (request_out_datain.expectMore == 0x02) {
1612  request_out_datain.offset, length, sglist);
1613 
1614  } else {
1616  uint32_t count = 0;
1617  uint32_t size_accum = 0;
1618  DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n",
1620 
1622  while ((length > count) && size_accum
1623  < (request_out_datain.msgSize - 1) &&
1624  (request_out_datain.msgSize != 0x00)) {
1625  Addr SCSI_start = sglist[count].upperAddr;
1626  SCSI_start = (SCSI_start << 32) |
1627  (sglist[count].baseAddr & 0xFFFFFFFF);
1628  DPRINTF(UFSHostDevice, "Data DMA start: 0x%8x\n", SCSI_start);
1629  DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n",
1630  (sglist[count].size + 1));
1638  uint32_t size_to_send = sglist[count].size + 1;
1639 
1640  if (request_out_datain.msgSize < (size_to_send + size_accum))
1641  size_to_send = request_out_datain.msgSize - size_accum;
1642 
1643  readDevice(false, SCSI_start, size_to_send,
1644  reinterpret_cast<uint8_t*>
1645  (&(request_out_datain.message.dataMsg[size_accum])),
1646  false, NULL);
1647 
1648  size_accum += size_to_send;
1649  DPRINTF(UFSHostDevice, "Total remaining: 0x%8x,accumulated so far"
1650  " : 0x%8x\n", (request_out_datain.msgSize - size_accum),
1651  size_accum);
1652 
1653  ++count;
1654  DPRINTF(UFSHostDevice, "Transfer #: %d\n", count);
1655  }
1656 
1658  transferDone(response_addr, req_pos, UFSDevice[lun_id]->
1659  transferInfo.requestOut, finalsize, finaladdress,
1660  reinterpret_cast<uint8_t*>(request_in), true, lun_id);
1661  }
1662 
1663  DPRINTF(UFSHostDevice, "SCSI resume done\n");
1664 }
1665 
1671 void
1673 {
1674  uint8_t this_lun = 0;
1675 
1676  //while we haven't found the right lun, keep searching
1677  while ((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedCommand())
1678  ++this_lun;
1679 
1680  if (this_lun < lunAvail) {
1681  //Clear signal.
1682  UFSDevice[this_lun]->clearSignal();
1683  //found it; call transferDone
1684  transferDone(UFSDevice[this_lun]->transferInfo.responseStartAddr,
1685  UFSDevice[this_lun]->transferInfo.reqPos,
1686  UFSDevice[this_lun]->transferInfo.requestOut,
1687  UFSDevice[this_lun]->transferInfo.size,
1688  UFSDevice[this_lun]->transferInfo.address,
1689  UFSDevice[this_lun]->transferInfo.destination,
1690  UFSDevice[this_lun]->transferInfo.finished,
1691  UFSDevice[this_lun]->transferInfo.lunID);
1692  }
1693 
1694  else
1695  panic("no LUN finished in tick %d\n", curTick());
1696 }
1697 
1703 void
1704 UFSHostDevice::transferDone(Addr responseStartAddr, uint32_t req_pos,
1705  struct UTPUPIURSP request_out, uint32_t size,
1706  Addr address, uint8_t* destination,
1707  bool finished, uint32_t lun_id)
1708 {
1710  if (UFSDevice[lun_id]->SCSIInfoQueue.empty())
1711  panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id,
1713 
1714  DPRINTF(UFSHostDevice, "DMA start: 0x%8x; DMA size: 0x%8x\n",
1715  responseStartAddr, sizeof(request_out));
1716 
1717  struct transferStart lastinfo;
1718  lastinfo.mask = req_pos;
1719  lastinfo.done = finished;
1720  lastinfo.address = address;
1721  lastinfo.size = size;
1722  lastinfo.destination = reinterpret_cast<UTPTransferReqDesc*>
1723  (destination);
1724  lastinfo.lun_id = lun_id;
1725 
1726  transferEnd.push_back(lastinfo);
1727 
1728  DPRINTF(UFSHostDevice, "Transfer done start\n");
1729 
1730  readDevice(false, responseStartAddr, sizeof(request_out),
1731  reinterpret_cast<uint8_t*>
1732  (&(UFSDevice[lun_id]->transferInfo.requestOut)),
1733  true, &UTPEvent);
1734 }
1735 
1742 void
1744 {
1745  uint32_t lun_id = transferEnd.front().lun_id;
1746 
1747  UFSDevice[lun_id]->SCSIInfoQueue.pop_front();
1748  DPRINTF(UFSHostDevice, "SCSIInfoQueue size: %d, lun: %d\n",
1749  UFSDevice[lun_id]->SCSIInfoQueue.size(), lun_id);
1750 
1752  if (UFSHCIMem.TRUTRLDBR & transferEnd.front().mask) {
1753  uint8_t count = 0;
1754  while (!(transferEnd.front().mask & (0x1 << count)))
1755  ++count;
1757  transactionStart[count]);
1758  }
1759 
1761  readDevice(true, transferEnd.front().address,
1762  transferEnd.front().size, reinterpret_cast<uint8_t*>
1763  (transferEnd.front().destination), true, NULL);
1764 
1766  transferTrack &= ~(transferEnd.front().mask);
1767  --activeDoorbells;
1768  ++pendingDoorbells;
1769  garbage.push_back(transferEnd.front().destination);
1770  transferEnd.pop_front();
1771  DPRINTF(UFSHostDevice, "UTP handled\n");
1772 
1775 
1776  DPRINTF(UFSHostDevice, "activeDoorbells: %d, pendingDoorbells: %d,"
1777  " garbage: %d, TransferEvent: %d\n", activeDoorbells,
1778  pendingDoorbells, garbage.size(), transferEventQueue.size());
1779 
1781  if (!UFSDevice[lun_id]->SCSIInfoQueue.empty())
1782  SCSIResume(lun_id);
1783 }
1784 
1788 void
1790 {
1791  DPRINTF(UFSHostDevice, "Read done start\n");
1792  --readPendingNum;
1793 
1795  if (garbage.size() > 0) {
1796  delete garbage.front();
1797  garbage.pop_front();
1798  }
1799 
1801  if (!(UFSHCIMem.ORInterruptStatus & 0x01)) {
1804  }
1805 
1806 
1807  if (!readDoneEvent.empty()) {
1808  readDoneEvent.pop_front();
1809  }
1810 }
1811 
1816 void
1818 {
1820  countInt++;
1821 
1824  pendingDoorbells = 0;
1825  DPRINTF(UFSHostDevice, "Clear doorbell %X\n", UFSHCIMem.TRUTRLDBR);
1826 
1827  checkDrain();
1828 
1830  gic->sendInt(intNum);
1831  DPRINTF(UFSHostDevice, "Send interrupt @ transaction: 0x%8x!\n",
1832  countInt);
1833 }
1834 
1839 void
1841 {
1842  gic->clearInt(intNum);
1843  DPRINTF(UFSHostDevice, "Clear interrupt: 0x%8x!\n", countInt);
1844 
1845  checkDrain();
1846 
1847  if (!(UFSHCIMem.TRUTRLDBR)) {
1848  idlePhaseStart = curTick();
1849  }
1851 }
1852 
1877 void
1878 UFSHostDevice::writeDevice(Event* additional_action, bool toDisk, Addr
1879  start, int size, uint8_t* destination, uint64_t
1880  SCSIDiskOffset, uint32_t lun_id)
1881 {
1882  DPRINTF(UFSHostDevice, "Write transaction Start: 0x%8x; Size: %d\n",
1883  start, size);
1884 
1886  if (toDisk) {
1887  ++writePendingNum;
1888 
1889  while (!writeDoneEvent.empty() && (writeDoneEvent.front().when()
1890  < curTick()))
1891  writeDoneEvent.pop_front();
1892 
1893  writeDoneEvent.push_back(this);
1894  assert(!writeDoneEvent.back().scheduled());
1895 
1897  struct transferInfo new_transfer;
1898  new_transfer.offset = SCSIDiskOffset;
1899  new_transfer.size = size;
1900  new_transfer.lunID = lun_id;
1901  new_transfer.filePointer = 0;
1902  SSDWriteinfo.push_back(new_transfer);
1903 
1905  SSDWriteinfo.back().buffer.resize(size);
1906 
1908  dmaPort.dmaAction(MemCmd::ReadReq, start, size,
1909  &writeDoneEvent.back(),
1910  &SSDWriteinfo.back().buffer[0], 0);
1911  //yes, a readreq at a write device function is correct.
1912  DPRINTF(UFSHostDevice, "Write to disk scheduled\n");
1913 
1914  } else {
1915  assert(!additional_action->scheduled());
1916  dmaPort.dmaAction(MemCmd::ReadReq, start, size,
1917  additional_action, destination, 0);
1918  DPRINTF(UFSHostDevice, "Write scheduled\n");
1919  }
1920 }
1921 
1927 void
1928 UFSHostDevice::manageWriteTransfer(uint8_t LUN, uint64_t offset, uint32_t
1929  sg_table_length, struct UFSHCDSGEntry*
1930  sglist)
1931 {
1932  struct writeToDiskBurst next_packet;
1933 
1934  next_packet.SCSIDiskOffset = offset;
1935 
1936  UFSDevice[LUN]->setTotalWrite(sg_table_length);
1937 
1942  for (uint32_t count = 0; count < sg_table_length; count++) {
1943  next_packet.start = sglist[count].upperAddr;
1944  next_packet.start = (next_packet.start << 32) |
1945  (sglist[count].baseAddr & 0xFFFFFFFF);
1946  next_packet.LUN = LUN;
1947  DPRINTF(UFSHostDevice, "Write data DMA start: 0x%8x\n",
1948  next_packet.start);
1949  DPRINTF(UFSHostDevice, "Write data DMA size: 0x%8x\n",
1950  (sglist[count].size + 1));
1951  assert(sglist[count].size > 0);
1952 
1953  if (count != 0)
1954  next_packet.SCSIDiskOffset = next_packet.SCSIDiskOffset +
1955  (sglist[count - 1].size + 1);
1956 
1957  next_packet.size = sglist[count].size + 1;
1958 
1960  if (dmaWriteInfo.empty())
1961  writeDevice(NULL, true, next_packet.start, next_packet.size,
1962  NULL, next_packet.SCSIDiskOffset, next_packet.LUN);
1963  else
1964  DPRINTF(UFSHostDevice, "Write not initiated queue: %d\n",
1965  dmaWriteInfo.size());
1966 
1967  dmaWriteInfo.push_back(next_packet);
1968  DPRINTF(UFSHostDevice, "Write Location: 0x%8x\n",
1969  next_packet.SCSIDiskOffset);
1970 
1971  DPRINTF(UFSHostDevice, "Write transfer #: 0x%8x\n", count + 1);
1972 
1974  stats.totalWrittenSSD += (sglist[count].size + 1);
1975  }
1976 
1979 }
1980 
1986 void
1988 {
1990  assert(dmaWriteInfo.size() > 0);
1991  dmaWriteInfo.pop_front();
1992  assert(SSDWriteinfo.size() > 0);
1993  uint32_t lun = SSDWriteinfo.front().lunID;
1994 
1996  DPRINTF(UFSHostDevice, "Write done entered, queue: %d\n",
1997  UFSDevice[lun]->SSDWriteDoneInfo.size());
1999  UFSDevice[lun]->writeFlash(&SSDWriteinfo.front().buffer[0],
2000  SSDWriteinfo.front().offset,
2001  SSDWriteinfo.front().size);
2002 
2008  UFSDevice[lun]->SSDWriteDoneInfo.push_back(SSDWriteinfo.front());
2009  SSDWriteinfo.pop_front();
2010 
2011  --writePendingNum;
2013  UFSDevice[lun]->SSDWriteStart();
2014 
2016  stats.currentWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size();
2017  stats.averageWriteSSDQueue = UFSDevice[lun]->SSDWriteDoneInfo.size();
2019 
2021  if (!dmaWriteInfo.empty())
2022  writeDevice(NULL, true, dmaWriteInfo.front().start,
2023  dmaWriteInfo.front().size, NULL,
2024  dmaWriteInfo.front().SCSIDiskOffset,
2025  dmaWriteInfo.front().LUN);
2026  DPRINTF(UFSHostDevice, "Write done end\n");
2027 }
2028 
2032 void
2034 {
2035  assert(SSDWriteDoneInfo.size() > 0);
2036  flashDevice->writeMemory(
2037  SSDWriteDoneInfo.front().offset,
2038  SSDWriteDoneInfo.front().size, memWriteCallback);
2039 
2040  SSDWriteDoneInfo.pop_front();
2041 
2042  DPRINTF(UFSHostDevice, "Write is started; left in queue: %d\n",
2043  SSDWriteDoneInfo.size());
2044 }
2045 
2046 
2051 void
2053 {
2054  DPRINTF(UFSHostDevice, "Write disk, aiming for %d messages, %d so far\n",
2055  totalWrite, amountOfWriteTransfers);
2056 
2057  //we have done one extra transfer
2058  ++amountOfWriteTransfers;
2059 
2061  assert(totalWrite >= amountOfWriteTransfers && totalWrite != 0);
2062 
2064  if (totalWrite == amountOfWriteTransfers) {
2065  DPRINTF(UFSHostDevice, "Write transactions finished\n");
2066  totalWrite = 0;
2067  amountOfWriteTransfers = 0;
2068 
2069  //Callback UFS Host
2070  setSignal();
2071  signalDone->process();
2072  }
2073 
2074 }
2075 
2081 void
2082 UFSHostDevice::readDevice(bool lastTransfer, Addr start, uint32_t size,
2083  uint8_t* destination, bool no_cache, Event*
2084  additional_action)
2085 {
2086  DPRINTF(UFSHostDevice, "Read start: 0x%8x; Size: %d, data[0]: 0x%8x\n",
2087  start, size, (reinterpret_cast<uint32_t *>(destination))[0]);
2088 
2090  if (lastTransfer) {
2091  ++readPendingNum;
2092  readDoneEvent.push_back(this);
2093  assert(!readDoneEvent.back().scheduled());
2094  dmaPort.dmaAction(MemCmd::WriteReq, start, size,
2095  &readDoneEvent.back(), destination, 0);
2096  //yes, a writereq at a read device function is correct.
2097 
2098  } else {
2099  if (additional_action != NULL)
2100  assert(!additional_action->scheduled());
2101 
2102  dmaPort.dmaAction(MemCmd::WriteReq, start, size,
2103  additional_action, destination, 0);
2104 
2105  }
2106 
2107 }
2108 
2114 void
2115 UFSHostDevice::manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t
2116  offset, uint32_t sg_table_length,
2117  struct UFSHCDSGEntry* sglist)
2118 {
2119  uint32_t size_accum = 0;
2120 
2121  DPRINTF(UFSHostDevice, "Data READ size: %d\n", size);
2122 
2127  for (uint32_t count = 0; count < sg_table_length; count++) {
2128  struct transferInfo new_transfer;
2129  new_transfer.offset = sglist[count].upperAddr;
2130  new_transfer.offset = (new_transfer.offset << 32) |
2131  (sglist[count].baseAddr & 0xFFFFFFFF);
2132  new_transfer.filePointer = offset + size_accum;
2133  new_transfer.size = (sglist[count].size + 1);
2134  new_transfer.lunID = LUN;
2135 
2136  DPRINTF(UFSHostDevice, "Data READ start: 0x%8x; size: %d\n",
2137  new_transfer.offset, new_transfer.size);
2138 
2139  UFSDevice[LUN]->SSDReadInfo.push_back(new_transfer);
2140  UFSDevice[LUN]->SSDReadInfo.back().buffer.resize(sglist[count].size
2141  + 1);
2142 
2148  UFSDevice[LUN]->readFlash(&UFSDevice[LUN]->
2149  SSDReadInfo.back().buffer[0],
2150  offset + size_accum,
2151  sglist[count].size + 1);
2152 
2153  size_accum += (sglist[count].size + 1);
2154 
2155  DPRINTF(UFSHostDevice, "Transfer %d; Remaining: 0x%8x, Accumulated:"
2156  " 0x%8x\n", (count + 1), (size-size_accum), size_accum);
2157 
2159  stats.totalReadSSD += (sglist[count].size + 1);
2160  stats.currentReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size();
2161  stats.averageReadSSDQueue = UFSDevice[LUN]->SSDReadInfo.size();
2162  }
2163 
2164  UFSDevice[LUN]->SSDReadStart(sg_table_length);
2165 
2168 
2169 }
2170 
2171 
2172 
2179 void
2181 {
2182  totalRead = total_read;
2183  for (uint32_t number_handled = 0; number_handled < SSDReadInfo.size();
2184  number_handled++) {
2189  flashDevice->readMemory(SSDReadInfo.front().filePointer,
2190  SSDReadInfo.front().size, memReadCallback);
2191  }
2192 
2193 }
2194 
2195 
2200 void
2202 {
2203  DPRINTF(UFSHostDevice, "SSD read done at lun %d, Aiming for %d messages,"
2204  " %d so far\n", lunID, totalRead, amountOfReadTransfers);
2205 
2206  if (totalRead == amountOfReadTransfers) {
2207  totalRead = 0;
2208  amountOfReadTransfers = 0;
2209 
2211  setSignal();
2212  signalDone->process();
2213  }
2214 
2215 }
2216 
2221 void
2223 {
2224  ++amountOfReadTransfers;
2225 
2229  setReadSignal();
2230  deviceReadCallback->process();
2231 
2232  //Are we done yet?
2233  SSDReadDone();
2234 }
2235 
2241 void
2243 {
2244  DPRINTF(UFSHostDevice, "Read Callback\n");
2245  uint8_t this_lun = 0;
2246 
2247  //while we haven't found the right lun, keep searching
2248  while ((this_lun < lunAvail) && !UFSDevice[this_lun]->finishedRead())
2249  ++this_lun;
2250 
2251  DPRINTF(UFSHostDevice, "Found LUN %d messages pending for clean: %d\n",
2252  this_lun, SSDReadPending.size());
2253 
2254  if (this_lun < lunAvail) {
2255  //Clear signal.
2256  UFSDevice[this_lun]->clearReadSignal();
2257  SSDReadPending.push_back(UFSDevice[this_lun]->SSDReadInfo.front());
2258  UFSDevice[this_lun]->SSDReadInfo.pop_front();
2259  readGarbageEventQueue.push_back(this);
2260 
2261  //make sure the queue is popped a the end of the dma transaction
2262  readDevice(false, SSDReadPending.front().offset,
2263  SSDReadPending.front().size,
2264  &SSDReadPending.front().buffer[0], false,
2265  &readGarbageEventQueue.back());
2266 
2269  }
2270  else
2271  panic("no read finished in tick %d\n", curTick());
2272 }
2273 
2278 void
2280 {
2281  DPRINTF(UFSHostDevice, "Clean read data, %d\n", SSDReadPending.size());
2282  SSDReadPending.pop_front();
2283  readGarbageEventQueue.pop_front();
2284 }
2285 
2290 void
2292 {
2294 
2295  const uint8_t* temp_HCI_mem = reinterpret_cast<const uint8_t*>(&UFSHCIMem);
2296  SERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem));
2297 
2298  uint32_t lun_avail = lunAvail;
2299  SERIALIZE_SCALAR(lun_avail);
2300 }
2301 
2302 
2307 void
2309 {
2311  uint8_t* temp_HCI_mem = reinterpret_cast<uint8_t*>(&UFSHCIMem);
2312  UNSERIALIZE_ARRAY(temp_HCI_mem, sizeof(HCIMem));
2313 
2314  uint32_t lun_avail;
2315  UNSERIALIZE_SCALAR(lun_avail);
2316  assert(lunAvail == lun_avail);
2317 }
2318 
2319 
2324 DrainState
2326 {
2327  if (UFSHCIMem.TRUTRLDBR) {
2328  DPRINTF(UFSHostDevice, "UFSDevice is draining...\n");
2329  return DrainState::Draining;
2330  } else {
2331  DPRINTF(UFSHostDevice, "UFSDevice drained\n");
2332  return DrainState::Drained;
2333  }
2334 }
2335 
2340 void
2342 {
2344  return;
2345 
2346  if (UFSHCIMem.TRUTRLDBR) {
2347  DPRINTF(UFSHostDevice, "UFSDevice is still draining; with %d active"
2348  " doorbells\n", activeDoorbells);
2349  } else {
2350  DPRINTF(UFSHostDevice, "UFSDevice is done draining\n");
2351  signalDrainDone();
2352  }
2353 }
count
Definition: misc.hh:704
Stats::Scalar currentSCSIQueue
Queue lengths.
Definition: ufs_device.hh:497
Counter value() const
Return the current value of this stat as its base type.
Definition: statistics.hh:677
const uint32_t lunAvail
Definition: ufs_device.hh:1001
std::deque< struct transferInfo > SSDReadPending
Information from the Disk, waiting to be pushed to the DMA.
Definition: ufs_device.hh:1111
#define DPRINTF(x,...)
Definition: trace.hh:212
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:398
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition: info.hh:51
struct SCSIResumeInfo SCSIInfo
SCSI resume info information structure for SCSI resume.
Definition: ufs_device.hh:1075
void generateInterrupt()
set interrupt and sort out the doorbell register.
Definition: ufs_device.cc:1817
void SSDReadStart(uint32_t total_read)
Start the transactions to (and from) the disk The host will queue all the transactions.
Definition: ufs_device.cc:2180
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
Callback * transferDoneCallback
Callbacks for the logic units.
Definition: ufs_device.hh:1142
for(int i=0;i< p->texture_features.size();i++) idRegs[TEXTURE_FEATURES_REG(i)]
int findLsbSet(uint64_t val)
Returns the bit position of the LSB that is set in the input.
Definition: bitfield.hh:180
std::deque< struct taskStart > taskInfo
When a task/transfer is started it needs information about the task/transfer it is about to perform...
Definition: ufs_device.hh:1095
Generic callback class.
Definition: callback.hh:41
virtual void clearInt(uint32_t num)=0
Clear an interrupt from a device that is connected to the GIC.
AddrRangeList getAddrRanges() const override
Address range functions.
Definition: ufs_device.cc:916
void unserialize(CheckpointIn &cp) override
Unserialize; needed to restore from checkpoints.
Definition: ufs_device.cc:2308
DrainState
Object drain/handover states.
Definition: drain.hh:71
#define panic(...)
Definition: misc.hh:153
Running normally.
void setValues()
Initialization function.
Definition: ufs_device.cc:889
std::deque< struct transferStart > transferStartInfo
Definition: ufs_device.hh:1096
Tick transactionStart[32]
Helper for latency stats These variables keep track of the latency for every doorbell.
Definition: ufs_device.hh:1052
uint32_t ORInterruptStatus
Operation and runtime registers.
Definition: ufs_device.hh:201
void finalUTP()
final UTP, sends the last acknowledge data structure to the system; prepares the clean up functions...
Definition: ufs_device.cc:1743
Stats::Scalar totalReadSSD
Amount of data read/written.
Definition: ufs_device.hh:502
void transferStart()
Transfer Start function.
Definition: ufs_device.cc:1362
struct UTPUPIURSP - Response UPIU structure header: UPIU header DW-0 to DW-2 residualTransferCount: R...
Definition: ufs_device.hh:271
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...
Definition: ufs_device.cc:1928
void writeFlash(uint8_t *writeaddr, uint64_t offset, uint32_t size)
Write flash.
Definition: ufs_device.cc:706
struct UTPTransferReqDesc - UTRD structure header: UTRD header DW-0 to DW-3 commandDescBaseAddrLo: UC...
Definition: ufs_device.hh:342
void SSDWriteDone()
SSD Write Done; This is the callback function for the memory model.
Definition: ufs_device.cc:2052
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:381
UFS command flow state machine digraph CommandFlow{ node [fontsize=10]; IDLE -> transferHandler [ lab...
Definition: ufs_device.hh:170
UFSHostDevice(const UFSHostDeviceParams *p)
Constructor for the UFS Host device.
Definition: ufs_device.cc:719
struct UTPUPIUHeader header
Definition: ufs_device.hh:288
uint32_t ORInterruptEnable
Definition: ufs_device.hh:202
std::deque< EventWrapper< UFSHostDevice,&UFSHostDevice::readGarbage > > readGarbageEventQueue
Event after a read to clean up the UTP data structures.
Definition: ufs_device.hh:1166
Bitfield< 23, 0 > offset
Definition: types.hh:149
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2560
void regStats() override
register statistics
Definition: ufs_device.cc:775
Stats::Scalar totalWriteDiskTransactions
Definition: ufs_device.hh:505
uint8_t pendingDoorbells
Definition: ufs_device.hh:1025
struct UTPUPIUTaskReq - Task request UPIU structure header - UPIU header structure DW0 to DW-2 inputP...
Definition: ufs_device.hh:287
Tick write(PacketPtr pkt) override
UFSHCD write function.
Definition: ufs_device.cc:1067
struct UFSHostDeviceStats stats
RequestHandler stats.
Definition: ufs_device.hh:1121
std::deque< struct transferStart > transferEnd
To finish the transaction one needs information about the original message.
Definition: ufs_device.hh:1084
struct UFSHostDevice::UTPTransferReqDesc::RequestDescHeader header
uint32_t ORHostControllerEnable
Definition: ufs_device.hh:204
std::deque< EventWrapper< UFSHostDevice,&UFSHostDevice::writeDone > > writeDoneEvent
Definition: ufs_device.hh:1135
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Definition: statistics.hh:311
Tick read(PacketPtr pkt) override
register access functions
Definition: ufs_device.cc:929
void readFlash(uint8_t *readaddr, uint64_t offset, uint32_t size)
Disk access functions.
Definition: ufs_device.cc:692
Stats::Formula simSeconds
Definition: stat_control.cc:64
void statusCheck(uint8_t status, uint8_t *sensecodelist)
Status of SCSI.
Definition: ufs_device.cc:675
This is a base class for UFS devices The UFS interface consists out of one host controller which conn...
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
const char data[]
Definition: circlebuf.cc:43
int readPendingNum
Track number of DMA transactions in progress.
Definition: ufs_device.hh:1012
const Addr pioAddr
Host controller information.
Definition: ufs_device.hh:996
void readCallback()
Read callback Call back function for the logic units to indicate the completion of a read action...
Definition: ufs_device.cc:2242
std::deque< struct UTPTransferReqDesc * > garbage
garbage queue, ensure clearing of the allocated memory
Definition: ufs_device.hh:1116
void unserialize(CheckpointIn &cp) override
Unserialize an object.
#define warn(...)
Definition: misc.hh:219
Bitfield< 5, 0 > status
Definition: miscregs.hh:1604
void commandHandler()
Command handler function.
Definition: ufs_device.cc:1382
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
const int intNum
Definition: ufs_device.hh:999
Tick curTick()
The current simulated tick.
Definition: core.hh:47
uint32_t HCCAP
Specify the host capabilities.
Definition: ufs_device.hh:193
uint8_t activeDoorbells
Statistics helper variables Active doorbells indicates how many doorbells are in teh process of being...
Definition: ufs_device.hh:1024
Callback * memReadCallback
Callbacks between Device and Memory.
Definition: ufs_device.hh:729
Stats::Average averageSCSIQueue
Average Queue lengths.
Definition: ufs_device.hh:514
SCSI reply structure.
Definition: ufs_device.hh:375
uint32_t ORHostControllerStatus
Definition: ufs_device.hh:203
virtual void sendInt(uint32_t num)=0
Post an interrupt from a device that is connected to the GIC.
uint64_t Tick
Tick count type.
Definition: types.hh:63
void clearInterrupt()
Interrupt control functions.
Definition: ufs_device.cc:1840
void SSDReadDone()
SSD Read done; Determines if the final callback of the transaction should be made at the end of a rea...
Definition: ufs_device.cc:2201
void serialize(CheckpointOut &cp) const override
Serialize an object.
std::vector< uint8_t > destination
Definition: ufs_device.hh:477
void taskStart()
Task Start function.
Definition: ufs_device.cc:1348
void readDevice(bool lastTransfer, Addr SCSIStart, uint32_t SCSISize, uint8_t *SCSIDestination, bool no_cache, Event *additional_action)
Dma transaction function: read device.
Definition: ufs_device.cc:2082
#define fatal(...)
Definition: misc.hh:163
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:158
#define SectorSize
Definition: disk_image.hh:46
void serialize(CheckpointOut &cp) const override
Serialize; needed to make checkpoints.
Definition: ufs_device.cc:2291
virtual void initializeMemory(uint64_t disk_size, uint32_t sector_size)=0
Initialize Memory.
HCIMem UFSHCIMem
Host controller memory.
Definition: ufs_device.hh:1007
BaseGic * gic
Definition: ufs_device.hh:1000
Stats::Formula curDoorbell
Number of doorbells rung.
Definition: ufs_device.hh:519
void LUNSignal()
LU callback function to indicate that the action has completed.
Definition: ufs_device.cc:1672
DrainState drain() override
Drain; needed to enable checkpoints.
Definition: ufs_device.cc:2325
const FlagsType none
Nothing extra to print.
Definition: info.hh:43
std::deque< struct writeToDiskBurst > dmaWriteInfo
Information to get a DMA transaction.
Definition: ufs_device.hh:1101
static const unsigned int cachingPage[5]
Definition: ufs_device.hh:748
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
uint32_t TMUTMRLBA
Task control registers.
Definition: ufs_device.hh:229
void transferHandler(struct UTPTransferReqDesc *request_in, int req_pos, Addr finaladdress, uint32_t finalsize, uint32_t done)
Transfer handler function.
Definition: ufs_device.cc:1432
Draining buffers pending serialization/handover.
void SCSIStart()
Transfer SCSI function.
Definition: ufs_device.cc:1475
UFSSCSIDevice(const UFSHostDeviceParams *p, uint32_t lun_id, Callback *transfer_cb, Callback *read_cb)
Constructor and destructor.
Definition: ufs_device.cc:77
void readGarbage()
Read garbage A read from disk data structure can vary in size and is therefor allocated on creation...
Definition: ufs_device.cc:2279
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
uint32_t CMDUICCMDR
Command registers.
Definition: ufs_device.hh:238
void readCallback()
Functions to indicate that the action to the SSD has completed.
Definition: ufs_device.cc:2222
Callback * signalDone
Callbacks between Host and Device.
Definition: ufs_device.hh:723
static const unsigned int UTPTaskREQCOMPL
Definition: ufs_device.hh:1182
RequestPtr dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, uint8_t *data, Tick delay, Request::Flags flag=0)
Definition: dma_device.cc:149
void manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t offset, uint32_t sg_table_length, struct UFSHCDSGEntry *sglist)
Manage read transfer.
Definition: ufs_device.cc:2115
struct UTPTransferReqDesc * destination
Definition: ufs_device.hh:449
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
struct UTPUPIUHeader header
Definition: ufs_device.hh:326
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:161
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:254
static const unsigned int recoveryPage[3]
Definition: ufs_device.hh:747
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:845
Task start information.
Definition: ufs_device.hh:460
device layer: This is your Logic unit This layer implements the SCSI functionality of the UFS Device ...
Definition: ufs_device.hh:533
int size()
Definition: pagetable.hh:146
struct UTPTransferReqDesc * RequestIn
Definition: ufs_device.hh:473
virtual const std::string name() const
Definition: sim_object.hh:117
std::deque< EventWrapper< UFSHostDevice,&UFSHostDevice::transferStart > > transferEventQueue
Definition: ufs_device.hh:1176
void readDone()
Read done Started at the end of a transaction after the last read action.
Definition: ufs_device.cc:1789
const Addr pioSize
Definition: ufs_device.hh:997
std::ostream CheckpointOut
Definition: serialize.hh:67
static const unsigned int UTPTransferREQCOMPL
Bits of interest within UFS data packages.
Definition: ufs_device.hh:1181
Stats::Formula averageReadSSDBW
Average bandwidth for reads and writes.
Definition: ufs_device.hh:510
Host Controller Interface This is a set of registers that allow the driver to control the transaction...
Definition: ufs_device.hh:189
void writeDone()
Write done After a DMA write with data intended for the disk, this function is called.
Definition: ufs_device.cc:1987
Different events, and scenarios require different types of information.
Definition: ufs_device.hh:422
Definition: eventq.hh:185
const Tick pioDelay
Definition: ufs_device.hh:998
struct UPIUMessage message
Definition: ufs_device.hh:379
uint32_t TRUTRLBA
Transfer control registers.
Definition: ufs_device.hh:220
EventWrapper< UFSHostDevice,&UFSHostDevice::SCSIStart > SCSIResumeEvent
The events that control the functionality.
Definition: ufs_device.hh:1155
struct SCSIReply request_out_datain
SCSI reply structure, used for direct answering.
Definition: ufs_device.hh:1067
uint32_t taskCommandTrack
Definition: ufs_device.hh:1045
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:267
std::deque< struct transferInfo > SSDWriteinfo
Information from DMA transaction to disk.
Definition: ufs_device.hh:1106
Stats::Histogram transactionLatency
Histogram of latencies.
Definition: ufs_device.hh:524
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:282
Transfer start information.
Definition: ufs_device.hh:448
T betoh(T value)
Definition: byteswap.hh:154
struct UFSHCDSGEntry - UFSHCI PRD Entry baseAddr: Lower 32bit physical address DW-0 upperAddr: Upper ...
Definition: ufs_device.hh:302
static const unsigned int controlPage[3]
These pages are SCSI specific.
Definition: ufs_device.hh:746
Callback * memReadCallback
Definition: ufs_device.hh:1143
Bitfield< 3, 0 > mask
Definition: types.hh:64
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:287
void taskHandler(struct UTPUPIUTaskReq *request_in, uint32_t req_pos, Addr finaladdress, uint32_t finalsize)
Task handler function.
Definition: ufs_device.cc:1396
uint8_t length
Definition: inet.hh:334
uint32_t transferTrack
Track the transfer This is allows the driver to "group" certain transfers together by using a tag in ...
Definition: ufs_device.hh:1044
std::vector< uint32_t > dataMsg
Definition: ufs_device.hh:329
Disk transfer burst information.
Definition: ufs_device.hh:485
DmaPort dmaPort
Definition: dma_device.hh:157
unsigned getSize() const
Definition: packet.hh:649
Helper template class to turn a simple class member function into a callback.
Definition: callback.hh:64
std::vector< UFSSCSIDevice * > UFSDevice
logic units connected to the UFS Host device Note again that the "device" as such is represented by o...
Definition: ufs_device.hh:1060
struct LUNInfo lunInfo
Logic unit info; needed for SCSI Info messages and LU identification.
Definition: ufs_device.hh:697
void SSDWriteStart()
SSD write start.
Definition: ufs_device.cc:2033
EventWrapper< UFSHostDevice,&UFSHostDevice::finalUTP > UTPEvent
Wait for the moment where we can send the last frame.
Definition: ufs_device.hh:1160
uint32_t countInt
interrupt verification This keeps track of the number of interrupts generated.
Definition: ufs_device.hh:1034
std::deque< EventWrapper< UFSHostDevice,&UFSHostDevice::taskStart > > taskEventQueue
Multiple tasks transfers can be scheduled at once for the device, the only thing we know for sure abo...
Definition: ufs_device.hh:1174
#define inform(...)
Definition: misc.hh:221
struct SCSIReply SCSICMDHandle(uint32_t *SCSI_msg)
SCSI command handle function; determines what the command is and returns a reply structure that allow...
Definition: ufs_device.cc:161
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:57
Bitfield< 0 > p
std::deque< EventWrapper< UFSHostDevice,&UFSHostDevice::readDone > > readDoneEvent
Transfer flow events Basically these events form two queues, one from memory to UFS device (DMA) and ...
Definition: ufs_device.hh:1133
const uint8_t UFSSlots
Definition: ufs_device.hh:1002
void requestHandler()
Handler functions.
Definition: ufs_device.cc:1231
void checkDrain()
Checkdrain; needed to enable checkpoints.
Definition: ufs_device.cc:2341
void SCSIResume(uint32_t lun_id)
Starts the scsi handling function in the apropriate Logic unit, prepares the right data transfer sche...
Definition: ufs_device.cc:1520
void regStats() override
Register statistics for this object.
Abstract superclass for simulation objects.
Definition: sim_object.hh:94
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.
Definition: ufs_device.cc:1704
static const unsigned int UICCommandCOMPL
Definition: ufs_device.hh:1183
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1869
if(it_gpu==gpuTypeMap.end())
Definition: gpu_nomali.cc:75
static const unsigned int UICCommandReady
Definition: ufs_device.hh:1184
Addr getAddr() const
Definition: packet.hh:639
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...
Definition: ufs_device.cc:1878

Generated on Fri Jun 9 2017 13:03:45 for gem5 by doxygen 1.8.6