Exemple #1
0
static void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
	PCOMMAND pCmd = (PCOMMAND)arg;
	POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv;
	PSG psg = pCmd->psg;
	int idx;
	
	HPT_ASSERT(pCmd->flags.physical_sg);
	
	if (error)
		panic("busdma error");
		
	HPT_ASSERT(nsegs<=os_max_sg_descriptors);

	if (nsegs != 0) {
		for (idx = 0; idx < nsegs; idx++, psg++) {
			psg->addr.bus = segs[idx].ds_addr;
			psg->size = segs[idx].ds_len;
			psg->eot = 0;
		}
		psg[-1].eot = 1;
	
		if (pCmd->flags.data_in) {
			bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map,
			    BUS_DMASYNC_PREREAD);
		}
		else if (pCmd->flags.data_out) {
			bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map,
			    BUS_DMASYNC_PREWRITE);
		}
	}

	callout_reset(&ext->timeout, HPT_OSM_TIMEOUT, hpt_timeout, pCmd);
	ldm_queue_cmd(pCmd);
}
Exemple #2
0
/*
 * flush a vdev (without retry).
 */
static int hpt_flush_vdev(PVBUS_EXT vbus_ext, PVDEV vd)
{
	PCOMMAND pCmd;
	int result = 0, done;
	HPT_UINT count;

	KdPrint(("flusing dev %p", vd));

	hpt_lock_vbus(vbus_ext);

	if (mIsArray(vd->type) && vd->u.array.transform)
		count = MAX(vd->u.array.transform->source->cmds_per_request,
					vd->u.array.transform->target->cmds_per_request);
	else
		count = vd->cmds_per_request;

	pCmd = ldm_alloc_cmds(vd->vbus, count);

	if (!pCmd) {
		hpt_unlock_vbus(vbus_ext);
		return -1;
	}

	pCmd->type = CMD_TYPE_FLUSH;
	pCmd->flags.hard_flush = 1;
	pCmd->target = vd;
	pCmd->done = hpt_flush_done;
	done = 0;
	pCmd->priv = &done;

	ldm_queue_cmd(pCmd);
	
	if (!done) {
		while (hpt_sleep(vbus_ext, pCmd, PPAUSE, "hptfls", HPT_OSM_TIMEOUT)) {
			ldm_reset_vbus(vd->vbus);
		}
	}

	KdPrint(("flush result %d", pCmd->Result));

	if (pCmd->Result!=RETURN_SUCCESS)
		result = -1;

	ldm_free_cmds(pCmd);

	hpt_unlock_vbus(vbus_ext);

	return result;
}
Exemple #3
0
static void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb)
{
	PVBUS vbus = (PVBUS)vbus_ext->vbus;
	PVDEV vd;
	PCOMMAND pCmd;
	POS_CMDEXT ext;
	HPT_U8 *cdb;

	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
		cdb = ccb->csio.cdb_io.cdb_ptr;
	else
		cdb = ccb->csio.cdb_io.cdb_bytes;
	
	KdPrint(("hpt_scsi_io: ccb %x id %d lun %d cdb %x-%x-%x",
		ccb,
		ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
		*(HPT_U32 *)&cdb[0], *(HPT_U32 *)&cdb[4], *(HPT_U32 *)&cdb[8]
	));

	/* ccb->ccb_h.path_id is not our bus id - don't check it */
	if (ccb->ccb_h.target_lun != 0 ||
		ccb->ccb_h.target_id >= osm_max_targets ||
		(ccb->ccb_h.flags & CAM_CDB_PHYS))
	{
		ccb->ccb_h.status = CAM_TID_INVALID;
		xpt_done(ccb);
		return;
	}

	vd = ldm_find_target(vbus, ccb->ccb_h.target_id);

	if (!vd) {
		ccb->ccb_h.status = CAM_TID_INVALID;
		xpt_done(ccb);
		return;
	}
   
	switch (cdb[0]) {
	case TEST_UNIT_READY:
	case START_STOP_UNIT:
	case SYNCHRONIZE_CACHE:
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;

	case INQUIRY:
		{
			PINQUIRYDATA inquiryData;
			memset(ccb->csio.data_ptr, 0, ccb->csio.dxfer_len);
			inquiryData = (PINQUIRYDATA)ccb->csio.data_ptr;
		
			inquiryData->AdditionalLength = 31;
			inquiryData->CommandQueue = 1;
			memcpy(&inquiryData->VendorId, "HPT     ", 8);
			memcpy(&inquiryData->ProductId, "DISK 0_0        ", 16);
	
			if (vd->target_id / 10) {
				inquiryData->ProductId[7] = (vd->target_id % 100) / 10 + '0';
				inquiryData->ProductId[8] = (vd->target_id % 100) % 10 + '0';
			}
			else
				inquiryData->ProductId[7] = (vd->target_id % 100) % 10 + '0';
	
			memcpy(&inquiryData->ProductRevisionLevel, "4.00", 4);
	
			ccb->ccb_h.status = CAM_REQ_CMP;
		}
		break;

	case READ_CAPACITY:
	{
		HPT_U8 *rbuf = ccb->csio.data_ptr;
		HPT_U32 cap;
		
		if (vd->capacity>0xfffffffful)
			cap = 0xfffffffful;
		else
			cap = vd->capacity - 1;
	
		rbuf[0] = (HPT_U8)(cap>>24);
		rbuf[1] = (HPT_U8)(cap>>16);
		rbuf[2] = (HPT_U8)(cap>>8);
		rbuf[3] = (HPT_U8)cap;
		rbuf[4] = 0;
		rbuf[5] = 0;
		rbuf[6] = 2;
		rbuf[7] = 0;

		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	
	case SERVICE_ACTION_IN: 
	{
		HPT_U8 *rbuf = ccb->csio.data_ptr;
		HPT_U64	cap = vd->capacity - 1;
		
		rbuf[0] = (HPT_U8)(cap>>56);
		rbuf[1] = (HPT_U8)(cap>>48);
		rbuf[2] = (HPT_U8)(cap>>40);
		rbuf[3] = (HPT_U8)(cap>>32);
		rbuf[4] = (HPT_U8)(cap>>24);
		rbuf[5] = (HPT_U8)(cap>>16);
		rbuf[6] = (HPT_U8)(cap>>8);
		rbuf[7] = (HPT_U8)cap;
		rbuf[8] = 0;
		rbuf[9] = 0;
		rbuf[10] = 2;
		rbuf[11] = 0;
		
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;	
	}
	
	case READ_6:
	case READ_10:
	case READ_16:
	case WRITE_6:
	case WRITE_10:
	case WRITE_16:
	case 0x13:
	case 0x2f:
	case 0x8f: /* VERIFY_16 */
	{
		pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request);
		if(!pCmd){
			KdPrint(("Failed to allocate command!"));
			ccb->ccb_h.status = CAM_BUSY;
			break;
		}

		switch (cdb[0])	{
		case READ_6:
		case WRITE_6:
		case 0x13:
			pCmd->uCmd.Ide.Lba =  ((HPT_U32)cdb[1] << 16) | ((HPT_U32)cdb[2] << 8) | (HPT_U32)cdb[3];
			pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[4];
			break;
		case READ_16:
		case WRITE_16:
		case 0x8f: /* VERIFY_16 */
		{
			HPT_U64 block =
				((HPT_U64)cdb[2]<<56) |
				((HPT_U64)cdb[3]<<48) |
				((HPT_U64)cdb[4]<<40) |
				((HPT_U64)cdb[5]<<32) |
				((HPT_U64)cdb[6]<<24) |
				((HPT_U64)cdb[7]<<16) |
				((HPT_U64)cdb[8]<<8) |
				((HPT_U64)cdb[9]);
			pCmd->uCmd.Ide.Lba = block;
			pCmd->uCmd.Ide.nSectors = (HPT_U16)cdb[13] | ((HPT_U16)cdb[12]<<8);
			break;
		}
		
		default:
			pCmd->uCmd.Ide.Lba = (HPT_U32)cdb[5] | ((HPT_U32)cdb[4] << 8) | ((HPT_U32)cdb[3] << 16) | ((HPT_U32)cdb[2] << 24);
			pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[8] | ((HPT_U16)cdb[7]<<8);
			break;
		}
		
		switch (cdb[0]) {
		case READ_6:
		case READ_10:
		case READ_16:
			pCmd->flags.data_in = 1;
			break;
		case WRITE_6:
		case WRITE_10:
		case WRITE_16:
			pCmd->flags.data_out = 1;
			break;
		}
		pCmd->priv = ext = cmdext_get(vbus_ext);
		HPT_ASSERT(ext);
		ext->ccb = ccb;
		pCmd->target = vd;
		pCmd->done = os_cmddone;
		pCmd->buildsgl = os_buildsgl;

		pCmd->psg = ext->psg;
		
		if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
			int idx;
			bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
			
			if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
				pCmd->flags.physical_sg = 1;
				
			for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
				pCmd->psg[idx].addr.bus = sgList[idx].ds_addr;
				pCmd->psg[idx].size = sgList[idx].ds_len;
				pCmd->psg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0;
			}

			ccb->ccb_h.timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT);
			ldm_queue_cmd(pCmd);
		}
		else {
			int error;
			pCmd->flags.physical_sg = 1;
			error = bus_dmamap_load(vbus_ext->io_dmat, 
						ext->dma_map, 
						ccb->csio.data_ptr, ccb->csio.dxfer_len, 
						hpt_io_dmamap_callback, pCmd,
				    	BUS_DMA_WAITOK
					);
			KdPrint(("bus_dmamap_load return %d", error));
			if (error && error!=EINPROGRESS) {
				os_printk("bus_dmamap_load error %d", error);
				cmdext_put(ext);
				ldm_free_cmds(pCmd);
				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
				xpt_done(ccb);
			}
		}
		return;
	}

	default:
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	}

	xpt_done(ccb);
	return;
}