Example #1
0
status_t
AHCIPort::FillPrdTable(volatile prd *prdTable, int *prdCount, int prdMax,
                       const void *data, size_t dataSize)
{
    int peMax = prdMax + 1;
    physical_entry pe[peMax];
    if (get_memory_map(data, dataSize, pe, peMax ) < B_OK) {
        TRACE("AHCIPort::FillPrdTable get_memory_map failed\n");
        return B_ERROR;
    }
    int peUsed;
    for (peUsed = 0; pe[peUsed].size; peUsed++)
        ;
    return FillPrdTable(prdTable, prdCount, prdMax, pe, peUsed, dataSize);
}
Example #2
0
status_t
AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,
	const void* data, size_t dataSize)
{
	int maxEntries = prdMax + 1;
	physical_entry entries[maxEntries];
	uint32 entriesUsed = maxEntries;

	status_t status = get_memory_map_etc(B_CURRENT_TEAM, data, dataSize,
		entries, &entriesUsed);
	if (status != B_OK) {
		TRACE("AHCIPort::FillPrdTable get_memory_map() failed: %s\n",
			strerror(status));
		return B_ERROR;
	}

	return FillPrdTable(prdTable, prdCount, prdMax, entries, entriesUsed,
		dataSize);
}
Example #3
0
void
AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
{
    FLOW("ExecuteAtaRequest port %d\n", fIndex);

    StartTransfer();

    int prdEntrys;

    if (request->ccb() && request->ccb()->data_length) {
        FillPrdTable(fPRDTable, &prdEntrys, PRD_TABLE_ENTRY_COUNT,
                     request->ccb()->sg_list, request->ccb()->sg_count,
                     request->ccb()->data_length);
    } else if (request->data() && request->size()) {
        FillPrdTable(fPRDTable, &prdEntrys, PRD_TABLE_ENTRY_COUNT,
                     request->data(), request->size());
    } else
        prdEntrys = 0;

    FLOW("prdEntrys %d\n", prdEntrys);

    fCommandList->prdtl_flags_cfl = 0;
    fCommandList->cfl = 5; // 20 bytes, length in DWORDS
    memcpy((char *)fCommandTable->cfis, request->fis(), 20);

    fTestUnitReadyActive = request->is_test_unit_ready();
    if (request->is_atapi()) {
        // ATAPI PACKET is a 12 or 16 byte SCSI command
        memset((char *)fCommandTable->acmd, 0, 32);
        memcpy((char *)fCommandTable->acmd, request->ccb()->cdb,
               request->ccb()->cdb_length);
        fCommandList->a = 1;
    }

    if (isWrite)
        fCommandList->w = 1;
    fCommandList->prdtl = prdEntrys;
    fCommandList->prdbc = 0;

    if (wait_until_clear(&fRegs->tfd, ATA_BSY | ATA_DRQ, 1000000) < B_OK) {
        TRACE("ExecuteAtaRequest port %d: device is busy\n", fIndex);
        ResetPort();
        FinishTransfer();
        request->abort();
        return;
    }

    cpu_status cpu = disable_interrupts();
    acquire_spinlock(&fSpinlock);
    fCommandsActive |= 1;
    fRegs->ci = 1;
    FlushPostedWrites();
    release_spinlock(&fSpinlock);
    restore_interrupts(cpu);

    int tfd;
    status_t status = WaitForTransfer(&tfd, 20000000);

    FLOW("tfd %#x\n", tfd);
    FLOW("prdbc %ld\n", fCommandList->prdbc);
    FLOW("ci   0x%08" B_PRIx32 "\n", fRegs->ci);
    FLOW("is   0x%08" B_PRIx32 "\n", fRegs->is);
    FLOW("serr 0x%08" B_PRIx32 "\n", fRegs->serr);

    /*
    	TRACE("ci   0x%08" B_PRIx32 "\n", fRegs->ci);
    	TRACE("ie   0x%08" B_PRIx32 "\n", fRegs->ie);
    	TRACE("is   0x%08" B_PRIx32 "\n", fRegs->is);
    	TRACE("cmd  0x%08" B_PRIx32 "\n", fRegs->cmd);
    	TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts);
    	TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl);
    	TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr);
    	TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact);
    	TRACE("tfd  0x%08" B_PRIx32 "\n", fRegs->tfd);
    */

    if (fResetPort || status == B_TIMED_OUT) {
        fResetPort = false;
        ResetPort();
    }

    size_t bytesTransfered = fCommandList->prdbc;

    FinishTransfer();

    if (status == B_TIMED_OUT) {
        TRACE("ExecuteAtaRequest port %d: device timeout\n", fIndex);
        request->abort();
    } else {
        request->finish(tfd, bytesTransfered);
    }
}