src/dev/arm/ufs_device.cc
/**
 * Handles the transfer requests that are given.
 * There can be three types of transfer. SCSI specific, Reads and writes
 * apart from the data transfer, this also generates its own reply (UPIU
 * response). Information for this reply is stored in transferInfo and will
 * be used in transferDone
 */
Handles the transfer requests that are given.
There can be three types of transfer. SCSI specific, Reads and writes
apart from the data transfer, this also generates its own reply (UPIU
response). Information for this reply is stored in transferInfo and will
be used in transferDone
Handles the transfer requests that are given . There can be three types of transfer . SCSI specific Reads and writes apart from the data transfer this also generates its own reply ( UPIU response ) . Information for this reply is stored in transferInfo and will be used in transferDone
void
UFSHostDevice::SCSIResume(uint32_t lun_id)
{
    DPRINTF(UFSHostDevice, "SCSIresume\n");
    if (UFSDevice[lun_id]->SCSIInfoQueue.empty())
        panic("No SCSI message scheduled lun:%d Doorbell: 0x%8x", lun_id,
              UFSHCIMem.TRUTRLDBR);
    struct UTPTransferReqDesc* request_in = UFSDevice[lun_id]->
        SCSIInfoQueue.front().RequestIn;
    uint32_t req_pos = UFSDevice[lun_id]->SCSIInfoQueue.front().reqPos;
    Addr finaladdress = UFSDevice[lun_id]->SCSIInfoQueue.front().
        finalAddress;
    uint32_t finalsize = UFSDevice[lun_id]->SCSIInfoQueue.front().finalSize;
    uint32_t* transfercommand = reinterpret_cast<uint32_t*>
        (&(UFSDevice[lun_id]->SCSIInfoQueue.front().destination[0]));
    DPRINTF(UFSHostDevice, "Task tag: 0x%8x\n", transfercommand[0]>>24);
    request_out_datain = UFSDevice[(transfercommand[0] & 0xFF0000) >> 16]->
        SCSICMDHandle(transfercommand);
    DPRINTF(UFSHostDevice, "LUN: %d\n", request_out_datain.LUN);
    request_in->header.dWord0 = ((request_in->header.dWord0 >> 24) == 0x21)
        ? 0x36 : 0x21;
    UFSDevice[lun_id]->transferInfo.requestOut.header.dWord0 =
        request_in->header.dWord0 | (request_out_datain.LUN << 8)
        | (transfercommand[0] & 0xFF000000);
    UFSDevice[lun_id]->transferInfo.requestOut.header.dWord1 = 0x00000000 |
        (request_out_datain.status << 24);
    UFSDevice[lun_id]->transferInfo.requestOut.header.dWord2 = 0x00000000 |
        ((request_out_datain.senseSize + 2) << 24) | 0x05;
    UFSDevice[lun_id]->transferInfo.requestOut.senseDataLen =
        request_out_datain.senseSize;
    for (uint8_t count = 0; count<request_out_datain.senseSize; count++) {
        UFSDevice[lun_id]->transferInfo.requestOut.senseData[count] =
            request_out_datain.senseCode[count + 1];
    }
    struct UFSHCDSGEntry* sglist =  reinterpret_cast<UFSHCDSGEntry*>
        (&(transfercommand[(request_in->PRDTableOffset)]));
    uint32_t length = request_in->PRDTableLength;
    DPRINTF(UFSHostDevice, "# PRDT entries: %d\n", length);
    Addr response_addr = request_in->commandDescBaseAddrHi;
    response_addr = (response_addr << 32) |
        ((request_in->commandDescBaseAddrLo +
          (request_in->responseUPIULength << 2)) & 0xffffffff);
    UFSDevice[lun_id]->transferInfo.responseStartAddr = response_addr;
    UFSDevice[lun_id]->transferInfo.reqPos = req_pos;
    UFSDevice[lun_id]->transferInfo.size = finalsize;
    UFSDevice[lun_id]->transferInfo.address = finaladdress;
    UFSDevice[lun_id]->transferInfo.destination = reinterpret_cast<uint8_t*>
        (UFSDevice[lun_id]->SCSIInfoQueue.front().RequestIn);
    UFSDevice[lun_id]->transferInfo.finished = true;
    UFSDevice[lun_id]->transferInfo.lunID = request_out_datain.LUN;
    if (request_out_datain.expectMore == 0x01) {
        manageWriteTransfer(request_out_datain.LUN, request_out_datain.offset,
                            length, sglist);
    } else if (request_out_datain.expectMore == 0x02) {
        manageReadTransfer(request_out_datain.msgSize, request_out_datain.LUN,
                           request_out_datain.offset, length, sglist);
    } else {
        uint32_t count = 0;
        uint32_t size_accum = 0;
        DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n",
                request_out_datain.msgSize);
        while ((length > count) && size_accum
               < (request_out_datain.msgSize - 1) &&
               (request_out_datain.msgSize != 0x00)) {
            Addr SCSI_start = sglist[count].upperAddr;
            SCSI_start = (SCSI_start << 32) |
                (sglist[count].baseAddr & 0xFFFFFFFF);
            DPRINTF(UFSHostDevice, "Data DMA start: 0x%8x\n", SCSI_start);
            DPRINTF(UFSHostDevice, "Data DMA size: 0x%8x\n",
                    (sglist[count].size + 1));
            uint32_t size_to_send = sglist[count].size + 1;
            if (request_out_datain.msgSize < (size_to_send + size_accum))
                size_to_send = request_out_datain.msgSize - size_accum;
            readDevice(false, SCSI_start, size_to_send,
                       reinterpret_cast<uint8_t*>
                       (&(request_out_datain.message.dataMsg[size_accum])),
                       false, NULL);
            size_accum += size_to_send;
            DPRINTF(UFSHostDevice, "Total remaining: 0x%8x,accumulated so far"
                    " : 0x%8x\n", (request_out_datain.msgSize - size_accum),
                    size_accum);
            ++count;
            DPRINTF(UFSHostDevice, "Transfer #: %d\n", count);
        }
        transferDone(response_addr, req_pos, UFSDevice[lun_id]->
                     transferInfo.requestOut, finalsize, finaladdress,
                     reinterpret_cast<uint8_t*>(request_in), true, lun_id);
    }
    DPRINTF(UFSHostDevice, "SCSI resume done\n");
}
void UFSHostDevice :: SCSIResume ( uint32_t lun_id ) { DPRINTF ( UFSHostDevice , " \n " ) ; if ( UFSDevice [ lun_id ] -> SCSIInfoQueue . empty ( ) ) panic ( " " , lun_id , UFSHCIMem . TRUTRLDBR ) ; struct UTPTransferReqDesc * request_in = UFSDevice [ lun_id ] -> SCSIInfoQueue . front ( ) . RequestIn ; uint32_t req_pos = UFSDevice [ lun_id ] -> SCSIInfoQueue . front ( ) . reqPos ; Addr finaladdress = UFSDevice [ lun_id ] -> SCSIInfoQueue . front ( ) . finalAddress ; uint32_t finalsize = UFSDevice [ lun_id ] -> SCSIInfoQueue . front ( ) . finalSize ; uint32_t * transfercommand = reinterpret_cast < uint32_t * > ( & ( UFSDevice [ lun_id ] -> SCSIInfoQueue . front ( ) . destination [ 0 ] ) ) ; DPRINTF ( UFSHostDevice , " \n " , transfercommand [ 0 ] >> 24 ) ; request_out_datain = UFSDevice [ ( transfercommand [ 0 ] & 0xFF0000 ) >> 16 ] -> SCSICMDHandle ( transfercommand ) ; DPRINTF ( UFSHostDevice , " \n " , request_out_datain . LUN ) ; request_in -> header . dWord0 = ( ( request_in -> header . dWord0 >> 24 ) == 0x21 ) ? 0x36 : 0x21 ; UFSDevice [ lun_id ] -> transferInfo . requestOut . header . dWord0 = request_in -> header . dWord0 | ( request_out_datain . LUN << 8 ) | ( transfercommand [ 0 ] & 0xFF000000 ) ; UFSDevice [ lun_id ] -> transferInfo . requestOut . header . dWord1 = 0x00000000 | ( request_out_datain . status << 24 ) ; UFSDevice [ lun_id ] -> transferInfo . requestOut . header . dWord2 = 0x00000000 | ( ( request_out_datain . senseSize + 2 ) << 24 ) | 0x05 ; UFSDevice [ lun_id ] -> transferInfo . requestOut . senseDataLen = request_out_datain . senseSize ; for ( uint8_t count = 0 ; count < request_out_datain . senseSize ; count ++ ) { UFSDevice [ lun_id ] -> transferInfo . requestOut . senseData [ count ] = request_out_datain . senseCode [ count + 1 ] ; } struct UFSHCDSGEntry * sglist = reinterpret_cast < UFSHCDSGEntry * > ( & ( transfercommand [ ( request_in -> PRDTableOffset ) ] ) ) ; uint32_t length = request_in -> PRDTableLength ; DPRINTF ( UFSHostDevice , " \n " , length ) ; Addr response_addr = request_in -> commandDescBaseAddrHi ; response_addr = ( response_addr << 32 ) | ( ( request_in -> commandDescBaseAddrLo + ( request_in -> responseUPIULength << 2 ) ) & 0xffffffff ) ; UFSDevice [ lun_id ] -> transferInfo . responseStartAddr = response_addr ; UFSDevice [ lun_id ] -> transferInfo . reqPos = req_pos ; UFSDevice [ lun_id ] -> transferInfo . size = finalsize ; UFSDevice [ lun_id ] -> transferInfo . address = finaladdress ; UFSDevice [ lun_id ] -> transferInfo . destination = reinterpret_cast < uint8_t * > ( UFSDevice [ lun_id ] -> SCSIInfoQueue . front ( ) . RequestIn ) ; UFSDevice [ lun_id ] -> transferInfo . finished = true ; UFSDevice [ lun_id ] -> transferInfo . lunID = request_out_datain . LUN ; if ( request_out_datain . expectMore == 0x01 ) { manageWriteTransfer ( request_out_datain . LUN , request_out_datain . offset , length , sglist ) ; } else if ( request_out_datain . expectMore == 0x02 ) { manageReadTransfer ( request_out_datain . msgSize , request_out_datain . LUN , request_out_datain . offset , length , sglist ) ; } else { uint32_t count = 0 ; uint32_t size_accum = 0 ; DPRINTF ( UFSHostDevice , " \n " , request_out_datain . msgSize ) ; while ( ( length > count ) && size_accum < ( request_out_datain . msgSize - 1 ) && ( request_out_datain . msgSize != 0x00 ) ) { Addr SCSI_start = sglist [ count ] . upperAddr ; SCSI_start = ( SCSI_start << 32 ) | ( sglist [ count ] . baseAddr & 0xFFFFFFFF ) ; DPRINTF ( UFSHostDevice , " \n " , SCSI_start ) ; DPRINTF ( UFSHostDevice , " \n " , ( sglist [ count ] . size + 1 ) ) ; uint32_t size_to_send = sglist [ count ] . size + 1 ; if ( request_out_datain . msgSize < ( size_to_send + size_accum ) ) size_to_send = request_out_datain . msgSize - size_accum ; readDevice ( false , SCSI_start , size_to_send , reinterpret_cast < uint8_t * > ( & ( request_out_datain . message . dataMsg [ size_accum ] ) ) , false , NULL ) ; size_accum += size_to_send ; DPRINTF ( UFSHostDevice , " " " \n " , ( request_out_datain . msgSize - size_accum ) , size_accum ) ; ++ count ; DPRINTF ( UFSHostDevice , " \n " , count ) ; } transferDone ( response_addr , req_pos , UFSDevice [ lun_id ] -> transferInfo . requestOut , finalsize , finaladdress , reinterpret_cast < uint8_t * > ( request_in ) , true , lun_id ) ; } DPRINTF ( UFSHostDevice , " \n " ) ; }
Handles the transfer requests that are given.
Handles the transfer requests that are given .
/**old info, lets form it such that we can understand it*/ /**call logic unit to handle SCSI command*/ /**
     * build response stating that it was succesful
     * command completion, Logic unit number, and Task tag
     */ /**SCSI status reply*/ /**segment size + EHS length (see UFS standard ch7)*/ /**amount of data that will follow*/ //data /*
     * At position defined by "request_in->PRDTableOffset" (counting 32 bit
     * words) in array "transfercommand" we have a scatter gather list, which
     * is usefull to us if we interpreted it as a UFSHCDSGEntry structure.
     */ /**transferdone information packet filling*/ /**
     * In this part the data that needs to be transfered will be initiated
     * and the chain of DMA (and potentially) disk transactions will be
     * started.
     */ /**write transfer*/ /**read transfer*/ /**not disk related transfer, SCSI maintanance*/ /**Transport the SCSI reponse data according to the SG list*/ /**
             * safetynet; it has been shown that sg list may be optimistic in
             * the amount of data allocated, which can potentially lead to
             * some garbage data being send over. Hence this construction
             * that finds the least amount of data that needs to be
             * transfered.
             */ /**Go to the next stage of the answering process*/