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
static int hpt_alloc_mem(PVBUS_EXT vbus_ext)
{
	PHBA hba;
	struct freelist *f;
	HPT_UINT i;
	void **p;

	for (hba = vbus_ext->hba_list; hba; hba = hba->next)
		hba->ldm_adapter.him->get_meminfo(hba->ldm_adapter.him_handle);

	ldm_get_mem_info((PVBUS)vbus_ext->vbus, 0);

	for (f=vbus_ext->freelist_head; f; f=f->next) {
		KdPrint(("%s: %d*%d=%d bytes",
			f->tag, f->count, f->size, f->count*f->size));
		for (i=0; i<f->count; i++) {
			p = (void **)malloc(f->size, M_DEVBUF, M_WAITOK);
			if (!p)	return (ENXIO);
			*p = f->head;
			f->head = p;
		}
	}

	for (f=vbus_ext->freelist_dma_head; f; f=f->next) {
		int order, size, j;

		HPT_ASSERT((f->size & (f->alignment-1))==0);

		for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1)
			;

		KdPrint(("%s: %d*%d=%d bytes, order %d",
			f->tag, f->count, f->size, f->count*f->size, order));
		HPT_ASSERT(f->alignment<=PAGE_SIZE);

		for (i=0; i<f->count;) {
			p = (void **)__get_free_pages(order);
			if (!p) return -1;
			for (j = size/f->size; j && i<f->count; i++,j--) {
				*p = f->head;
				*(BUS_ADDRESS *)(p+1) = (BUS_ADDRESS)vtophys(p);
				f->head = p;
				p = (void **)((unsigned long)p + f->size);
			}
		}
	}
	
	HPT_ASSERT(PAGE_SIZE==DMAPOOL_PAGE_SIZE);

	for (i=0; i<os_max_cache_pages; i++) {
		p = (void **)__get_free_pages(0);
		if (!p) return -1;
		HPT_ASSERT(((HPT_UPTR)p & (DMAPOOL_PAGE_SIZE-1))==0);
		dmapool_put_page((PVBUS)vbus_ext->vbus, p, (BUS_ADDRESS)vtophys(p));
	}

	return 0;
}
Exemple #3
0
void freelist_put(struct freelist * list, void *p)
{
    HPT_ASSERT(list->dma==0);
    list->count++;
    *(void **)p = list->head;
    list->head = p;
}
Exemple #4
0
static int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical)
{
	POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv;
	union ccb *ccb = ext->ccb;
	bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
	int idx;

	if(logical)	{
		if (ccb->ccb_h.flags & CAM_DATA_PHYS)
			panic("physical address unsupported");

		if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
			if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
				panic("physical address unsupported");
	
			for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
				os_set_sgptr(&pSg[idx], (HPT_U8 *)(HPT_UPTR)sgList[idx].ds_addr);
				pSg[idx].size = sgList[idx].ds_len;
				pSg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0;
			}
		}
		else {
			os_set_sgptr(pSg, (HPT_U8 *)ccb->csio.data_ptr);
			pSg->size = ccb->csio.dxfer_len;
			pSg->eot = 1;
		}
		return TRUE;
	}

	/* since we have provided physical sg, nobody will ask us to build physical sg */
	HPT_ASSERT(0);
	return FALSE;
}
Exemple #5
0
static int
hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
{
	PVDevice	pArray = ID_TO_VDEV(id);
	BOOLEAN	del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
	int i;
	PVDevice pa;

	if ((id==0) || check_VDevice_valid(pArray))
		return -1;

	if(!mIsArray(pArray)) return -1;
	
	if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
		pArray->u.array.rf_initializing)
		return -1;

	for(i=0; i<pArray->u.array.bArnMember; i++) {
		pa = pArray->u.array.pMember[i];
		if (pa && mIsArray(pa)) {
			if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying || 
				pa->u.array.rf_initializing)
				return -1;
		}
	}

	if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
	fDeleteArray(_VBUS_P pArray, del_block0);
	return 0;

}
Exemple #6
0
void freelist_put_dma(struct freelist *list, void *p, BUS_ADDRESS busaddr)
{
    HPT_ASSERT(list->dma);
    list->count++;
    *(void **)p = list->head;
    *(BUS_ADDRESS *)((void **)p+1) = busaddr;
    list->head = p;
}
Exemple #7
0
void  os_request_timer(void * osext, HPT_U32 interval)
{
	PVBUS_EXT vbus_ext = osext;

	HPT_ASSERT(vbus_ext->ext_type==EXT_TYPE_VBUS);

	callout_reset(&vbus_ext->timer, interval * hz / 1000000,
	    os_timer_for_ldm, vbus_ext);
}
Exemple #8
0
void  os_request_timer(void * osext, HPT_U32 interval)
{
	PVBUS_EXT vbus_ext = osext;

	HPT_ASSERT(vbus_ext->ext_type==EXT_TYPE_VBUS);

	callout_reset_sbt(&vbus_ext->timer, SBT_1US * interval, 0,
	    os_timer_for_ldm, vbus_ext, 0);
}
Exemple #9
0
void  os_request_timer(void * osext, HPT_U32 interval)
{
	PVBUS_EXT vbus_ext = osext;

	HPT_ASSERT(vbus_ext->ext_type==EXT_TYPE_VBUS);
	
	untimeout(os_timer_for_ldm, vbus_ext, vbus_ext->timer);
	vbus_ext->timer = timeout(os_timer_for_ldm, vbus_ext, interval * hz / 1000000);
}
Exemple #10
0
void *freelist_get_dma(struct freelist *list, BUS_ADDRESS *busaddr)
{
    void *result;
    HPT_ASSERT(list->dma);
    result = freelist_get(list);
    if (result)
        *busaddr = *(BUS_ADDRESS *)((void **)result+1);
    return result;
}
Exemple #11
0
void *freelist_get(struct freelist *list)
{
    void * result;
    if (list->count) {
        HPT_ASSERT(list->head);
        result = list->head;
        list->head = *(void **)result;
        list->count--;
        return result;
    }
    return 0;
}
Exemple #12
0
void  os_request_timer(void * osext, HPT_U32 interval)
{
	PVBUS_EXT vbus_ext = osext;

	HPT_ASSERT(vbus_ext->ext_type==EXT_TYPE_VBUS);

#if (__FreeBSD_version >= 1000510)
	callout_reset_sbt(&vbus_ext->timer, SBT_1US * interval, 0,
	    os_timer_for_ldm, vbus_ext, 0);
#else 
	untimeout(os_timer_for_ldm, vbus_ext, vbus_ext->timer);
	vbus_ext->timer = timeout(os_timer_for_ldm, vbus_ext, interval * hz / 1000000);
#endif
}
Exemple #13
0
static int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical)
{
	POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv;
	union ccb *ccb = ext->ccb;

	if (logical) {
		os_set_sgptr(pSg, (HPT_U8 *)ccb->csio.data_ptr);
		pSg->size = ccb->csio.dxfer_len;
		pSg->eot = 1;
		return TRUE;
	}

	/* since we have provided physical sg, nobody will ask us to build physical sg */
	HPT_ASSERT(0);
	return FALSE;
}
Exemple #14
0
static void hpt_flush_done(PCOMMAND pCmd)
{
	PVDEV vd = pCmd->target;

	if (mIsArray(vd->type) && vd->u.array.transform && vd!=vd->u.array.transform->target) {
		vd = vd->u.array.transform->target;
		HPT_ASSERT(vd);
		pCmd->target = vd;
		pCmd->Result = RETURN_PENDING;
		vdev_queue_cmd(pCmd);
		return;
	}

	*(int *)pCmd->priv = 1;
	wakeup(pCmd);
}
Exemple #15
0
static void hpt_free_mem(PVBUS_EXT vbus_ext)
{
	struct freelist *f;
	void *p;
	int i;
	BUS_ADDRESS bus;

	for (f=vbus_ext->freelist_head; f; f=f->next) {
#if DBG
		if (f->count!=f->reserved_count) {
			KdPrint(("memory leak for freelist %s (%d/%d)", f->tag, f->count, f->reserved_count));
		}
#endif
		while ((p=freelist_get(f)))
			free(p, M_DEVBUF);
	}

	for (i=0; i<os_max_cache_pages; i++) {
		p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus);
		HPT_ASSERT(p);
		free_pages(p, 0);
	}

	for (f=vbus_ext->freelist_dma_head; f; f=f->next) {
		int order, size;
#if DBG
		if (f->count!=f->reserved_count) {
			KdPrint(("memory leak for dma freelist %s (%d/%d)", f->tag, f->count, f->reserved_count));
		}
#endif
		for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ;

		while ((p=freelist_get_dma(f, &bus))) {
			if (order)
				free_pages(p, order);
			else {
			/* can't free immediately since other blocks in this page may still be in the list */
				if (((HPT_UPTR)p & (PAGE_SIZE-1))==0)
					dmapool_put_page((PVBUS)vbus_ext->vbus, p, bus);
			}
		}
	}
	
	while ((p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus)))
		free_pages(p, 0);
}
Exemple #16
0
void os_schedule_task(void *osext, OSM_TASK *task)
{
	PVBUS_EXT vbus_ext = osext;
	
	HPT_ASSERT(task->next==0);
	
	if (vbus_ext->tasks==0)
		vbus_ext->tasks = task;
	else {
		OSM_TASK *t = vbus_ext->tasks;
		while (t->next) t = t->next;
		t->next = task;
	}

	if (vbus_ext->worker.ta_context)
		TASK_ENQUEUE(&vbus_ext->worker);
}
Exemple #17
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 */
	{
		int error;
		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;
		pCmd->flags.physical_sg = 1;
		error = bus_dmamap_load_ccb(vbus_ext->io_dmat, 
					ext->dma_map, ccb, 
					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;
}
Exemple #18
0
static int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical)
{
	/* since we have provided physical sg, nobody will ask us to build physical sg */
	HPT_ASSERT(0);
	return FALSE;
}
Exemple #19
0
void
hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
{
    ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
    PCommand pCmd;
	UINT result;
	int needsync=0, retry=0, needdelete=0;
	void *buffer = NULL;

	_VBUS_INST(&pAdapter->VBus)

	if (pArray->u.array.rf_broken==1 ||
    	pArray->u.array.RebuildSectors>=capacity)
		return;

	mtx_lock(&pAdapter->lock);
	
	switch(flags)
	{
		case DUPLICATE:
		case REBUILD_PARITY:
			if(pArray->u.array.rf_rebuilding == 0)
			{
				pArray->u.array.rf_rebuilding = 1;
				hpt_printk(("Rebuilding started.\n"));
				ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
			}
			break;

		case INITIALIZE:
			if(pArray->u.array.rf_initializing == 0)
			{
				pArray->u.array.rf_initializing = 1;
				hpt_printk(("Initializing started.\n"));
				ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
			}
			break;

		case VERIFY:
			if(pArray->u.array.rf_verifying == 0)
			{
				pArray->u.array.rf_verifying = 1;
				hpt_printk(("Verifying started.\n"));
				ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
			}
			break;
	}
	
retry_cmd:
	pCmd = AllocateCommand(_VBUS_P0);
	HPT_ASSERT(pCmd);
	pCmd->cf_control = 1;
	End_Job = 0;

	if (pArray->VDeviceType==VD_RAID_1) 
	{
		#define MAX_REBUILD_SECTORS 0x40

		/* take care for discontinuous buffer in R1ControlSgl */
		buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
		if(!buffer) {
			FreeCommand(_VBUS_P pCmd);
			hpt_printk(("can't allocate rebuild buffer\n"));
			goto fail;
		}
		switch(flags) 
		{
			case DUPLICATE:
				pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
				break;

			case VERIFY:
				pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
				break;

			case INITIALIZE:
				pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 
				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
				break;
		}

		pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;

		if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
			pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;

		pCmd->uCmd.R1Control.Buffer = buffer;
		pCmd->pfnBuildSgl = R1ControlSgl;
	}
	else if (pArray->VDeviceType==VD_RAID_5)
	{
		switch(flags)
		{
			case DUPLICATE:
			case REBUILD_PARITY:
				pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
			case VERIFY:
				pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
			case INITIALIZE:
				pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
		}
		pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
	}
	else