FreeBSD/sys/dev/mvs/mvs.c
/* Must be called with channel locked. */
Must be called with channel locked.
Must be called with channel locked .
static void
mvs_begin_transaction(device_t dev, union ccb *ccb)
{
	struct mvs_channel *ch = device_get_softc(dev);
	struct mvs_slot *slot;
	int slotn, tag;
	if (ch->pm_level > 0)
		mvs_ch_pm_wake(dev);
	if (ccb->ccb_h.func_code == XPT_ATA_IO &&
	    (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) {
		mvs_softreset(dev, ccb);
		return;
	}
	slotn = ffs(~ch->oslots) - 1;
	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
		if (ch->quirks & MVS_Q_GENIIE)
			tag = ffs(~ch->otagspd[ccb->ccb_h.target_id]) - 1;
		else
			tag = slotn;
	} else
		tag = 0;
	slot = &ch->slot[slotn];
	slot->ccb = ccb;
	slot->tag = tag;
	if (ch->numrslots == 0 && ch->pm_level > 3)
		callout_stop(&ch->pm_timer);
	ch->oslots |= (1 << slot->slot);
	ch->numrslots++;
	ch->numrslotspd[ccb->ccb_h.target_id]++;
	if (ccb->ccb_h.func_code == XPT_ATA_IO) {
		if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
			ch->otagspd[ccb->ccb_h.target_id] |= (1 << slot->tag);
			ch->numtslots++;
			ch->numtslotspd[ccb->ccb_h.target_id]++;
			ch->taggedtarget = ccb->ccb_h.target_id;
			mvs_set_edma_mode(dev, MVS_EDMA_NCQ);
		} else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) {
			ch->numdslots++;
			mvs_set_edma_mode(dev, MVS_EDMA_ON);
		} else {
			ch->numpslots++;
			mvs_set_edma_mode(dev, MVS_EDMA_OFF);
		}
		if (ccb->ataio.cmd.flags &
		    (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) {
			ch->aslots |= (1 << slot->slot);
		}
	} else {
		uint8_t *cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
		    ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes;
		ch->numpslots++;
		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
		    ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA &&
		    (ch->quirks & MVS_Q_SOC) == 0 &&
		    (cdb[0] == 0x08 ||
		     cdb[0] == 0x0a ||
		     cdb[0] == 0x28 ||
		     cdb[0] == 0x2a ||
		     cdb[0] == 0x88 ||
		     cdb[0] == 0x8a ||
		     cdb[0] == 0xa8 ||
		     cdb[0] == 0xaa ||
		     cdb[0] == 0xbe)) {
			ch->basic_dma = 1;
		}
		mvs_set_edma_mode(dev, MVS_EDMA_OFF);
	}
	if (ch->numpslots == 0 || ch->basic_dma) {
		slot->state = MVS_SLOT_LOADING;
		bus_dmamap_load_ccb(ch->dma.data_tag, slot->dma.data_map,
		    ccb, mvs_dmasetprd, slot, 0);
	} else
		mvs_legacy_execute_transaction(slot);
}
static void mvs_begin_transaction ( device_t dev , union ccb * ccb ) { struct mvs_channel * ch = device_get_softc ( dev ) ; struct mvs_slot * slot ; int slotn , tag ; if ( ch -> pm_level > 0 ) mvs_ch_pm_wake ( dev ) ; if ( ccb -> ccb_h . func_code == XPT_ATA_IO && ( ccb -> ataio . cmd . flags & CAM_ATAIO_CONTROL ) ) { mvs_softreset ( dev , ccb ) ; return ; } slotn = ffs ( ~ ch -> oslots ) - 1 ; if ( ( ccb -> ccb_h . func_code == XPT_ATA_IO ) && ( ccb -> ataio . cmd . flags & CAM_ATAIO_FPDMA ) ) { if ( ch -> quirks & MVS_Q_GENIIE ) tag = ffs ( ~ ch -> otagspd [ ccb -> ccb_h . target_id ] ) - 1 ; else tag = slotn ; } else tag = 0 ; slot = & ch -> slot [ slotn ] ; slot -> ccb = ccb ; slot -> tag = tag ; if ( ch -> numrslots == 0 && ch -> pm_level > 3 ) callout_stop ( & ch -> pm_timer ) ; ch -> oslots |= ( 1 << slot -> slot ) ; ch -> numrslots ++ ; ch -> numrslotspd [ ccb -> ccb_h . target_id ] ++ ; if ( ccb -> ccb_h . func_code == XPT_ATA_IO ) { if ( ccb -> ataio . cmd . flags & CAM_ATAIO_FPDMA ) { ch -> otagspd [ ccb -> ccb_h . target_id ] |= ( 1 << slot -> tag ) ; ch -> numtslots ++ ; ch -> numtslotspd [ ccb -> ccb_h . target_id ] ++ ; ch -> taggedtarget = ccb -> ccb_h . target_id ; mvs_set_edma_mode ( dev , MVS_EDMA_NCQ ) ; } else if ( ccb -> ataio . cmd . flags & CAM_ATAIO_DMA ) { ch -> numdslots ++ ; mvs_set_edma_mode ( dev , MVS_EDMA_ON ) ; } else { ch -> numpslots ++ ; mvs_set_edma_mode ( dev , MVS_EDMA_OFF ) ; } if ( ccb -> ataio . cmd . flags & ( CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT ) ) { ch -> aslots |= ( 1 << slot -> slot ) ; } } else { uint8_t * cdb = ( ccb -> ccb_h . flags & CAM_CDB_POINTER ) ? ccb -> csio . cdb_io . cdb_ptr : ccb -> csio . cdb_io . cdb_bytes ; ch -> numpslots ++ ; if ( ( ccb -> ccb_h . flags & CAM_DIR_MASK ) != CAM_DIR_NONE && ch -> curr [ ccb -> ccb_h . target_id ] . mode >= ATA_DMA && ( ch -> quirks & MVS_Q_SOC ) == 0 && ( cdb [ 0 ] == 0x08 || cdb [ 0 ] == 0x0a || cdb [ 0 ] == 0x28 || cdb [ 0 ] == 0x2a || cdb [ 0 ] == 0x88 || cdb [ 0 ] == 0x8a || cdb [ 0 ] == 0xa8 || cdb [ 0 ] == 0xaa || cdb [ 0 ] == 0xbe ) ) { ch -> basic_dma = 1 ; } mvs_set_edma_mode ( dev , MVS_EDMA_OFF ) ; } if ( ch -> numpslots == 0 || ch -> basic_dma ) { slot -> state = MVS_SLOT_LOADING ; bus_dmamap_load_ccb ( ch -> dma . data_tag , slot -> dma . data_map , ccb , mvs_dmasetprd , slot , 0 ) ; } else mvs_legacy_execute_transaction ( slot ) ; }
Must be called with channel locked.
Must be called with channel locked .
/* Softreset is a special case. */ /* Choose empty slot. */ /* Occupy chosen slot. */ /* Stop PM timer. */ /* Update channel stats. */ /* Use ATAPI DMA only for commands without under-/overruns. */