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