FreeBSD/sys/cam/scsi/scsi_target.c
/* Receive CCBs from user mode proc and send them to the HBA */
Receive CCBs from user mode proc and send them to the HBA
Receive CCBs from user mode proc and send them to the HBA
static int
targwrite(struct cdev *dev, struct uio *uio, int ioflag)
{
	union ccb *user_ccb;
	struct targ_softc *softc;
	struct targ_cmd_descr *descr;
	int write_len, error;
	int func_code, priority;
	devfs_get_cdevpriv((void **)&softc);
	write_len = error = 0;
	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
		  ("write - uio_resid %zd\n", uio->uio_resid));
	while (uio->uio_resid >= sizeof(user_ccb) && error == 0) {
		union ccb *ccb;
		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
		if (error != 0) {
			CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
				  ("write - uiomove failed (%d)\n", error));
			break;
		}
		priority = fuword32(&user_ccb->ccb_h.pinfo.priority);
		if (priority == CAM_PRIORITY_NONE) {
			error = EINVAL;
			break;
		}
		func_code = fuword32(&user_ccb->ccb_h.func_code);
		switch (func_code) {
		case XPT_ACCEPT_TARGET_IO:
		case XPT_IMMED_NOTIFY:
		case XPT_IMMEDIATE_NOTIFY:
			cam_periph_lock(softc->periph);
			ccb = targgetccb(softc, func_code, priority);
			descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
			descr->user_ccb = user_ccb;
			descr->func_code = func_code;
			CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
				  ("Sent ATIO/INOT (%p)\n", user_ccb));
			xpt_action(ccb);
			TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
					  &ccb->ccb_h,
					  periph_links.tqe);
			cam_periph_unlock(softc->periph);
			break;
		default:
			cam_periph_lock(softc->periph);
			if ((func_code & XPT_FC_QUEUED) != 0) {
				CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
					  ("Sending queued ccb %#x (%p)\n",
					  func_code, user_ccb));
				descr = targgetdescr(softc);
				descr->user_ccb = user_ccb;
				descr->priority = priority;
				descr->func_code = func_code;
				TAILQ_INSERT_TAIL(&softc->work_queue,
						  descr, tqe);
				xpt_schedule(softc->periph, priority);
			} else {
				CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
					  ("Sending inline ccb %#x (%p)\n",
					  func_code, user_ccb));
				ccb = targgetccb(softc, func_code, priority);
				descr = (struct targ_cmd_descr *)
					 ccb->ccb_h.targ_descr;
				descr->user_ccb = user_ccb;
				descr->priority = priority;
				descr->func_code = func_code;
				if (targusermerge(softc, descr, ccb) != EFAULT)
					targsendccb(softc, ccb, descr);
				targreturnccb(softc, ccb);
			}
			cam_periph_unlock(softc->periph);
			break;
		}
		write_len += sizeof(user_ccb);
	}
	if (error != 0 && write_len == 0)
		return (error);
	if (write_len == 0 && uio->uio_resid != 0)
		return (ENOSPC);
	return (0);
}
static int targwrite ( struct cdev * dev , struct uio * uio , int ioflag ) { union ccb * user_ccb ; struct targ_softc * softc ; struct targ_cmd_descr * descr ; int write_len , error ; int func_code , priority ; devfs_get_cdevpriv ( ( void * * ) & softc ) ; write_len = error = 0 ; CAM_DEBUG ( softc -> path , CAM_DEBUG_PERIPH , ( " \n " , uio -> uio_resid ) ) ; while ( uio -> uio_resid >= sizeof ( user_ccb ) && error == 0 ) { union ccb * ccb ; error = uiomove ( ( caddr_t ) & user_ccb , sizeof ( user_ccb ) , uio ) ; if ( error != 0 ) { CAM_DEBUG ( softc -> path , CAM_DEBUG_PERIPH , ( " \n " , error ) ) ; break ; } priority = fuword32 ( & user_ccb -> ccb_h . pinfo . priority ) ; if ( priority == CAM_PRIORITY_NONE ) { error = EINVAL ; break ; } func_code = fuword32 ( & user_ccb -> ccb_h . func_code ) ; switch ( func_code ) { case XPT_ACCEPT_TARGET_IO : case XPT_IMMED_NOTIFY : case XPT_IMMEDIATE_NOTIFY : cam_periph_lock ( softc -> periph ) ; ccb = targgetccb ( softc , func_code , priority ) ; descr = ( struct targ_cmd_descr * ) ccb -> ccb_h . targ_descr ; descr -> user_ccb = user_ccb ; descr -> func_code = func_code ; CAM_DEBUG ( softc -> path , CAM_DEBUG_PERIPH , ( " \n " , user_ccb ) ) ; xpt_action ( ccb ) ; TAILQ_INSERT_TAIL ( & softc -> pending_ccb_queue , & ccb -> ccb_h , periph_links . tqe ) ; cam_periph_unlock ( softc -> periph ) ; break ; default : cam_periph_lock ( softc -> periph ) ; if ( ( func_code & XPT_FC_QUEUED ) != 0 ) { CAM_DEBUG ( softc -> path , CAM_DEBUG_PERIPH , ( " \n " , func_code , user_ccb ) ) ; descr = targgetdescr ( softc ) ; descr -> user_ccb = user_ccb ; descr -> priority = priority ; descr -> func_code = func_code ; TAILQ_INSERT_TAIL ( & softc -> work_queue , descr , tqe ) ; xpt_schedule ( softc -> periph , priority ) ; } else { CAM_DEBUG ( softc -> path , CAM_DEBUG_PERIPH , ( " \n " , func_code , user_ccb ) ) ; ccb = targgetccb ( softc , func_code , priority ) ; descr = ( struct targ_cmd_descr * ) ccb -> ccb_h . targ_descr ; descr -> user_ccb = user_ccb ; descr -> priority = priority ; descr -> func_code = func_code ; if ( targusermerge ( softc , descr , ccb ) != EFAULT ) targsendccb ( softc , ccb , descr ) ; targreturnccb ( softc , ccb ) ; } cam_periph_unlock ( softc -> periph ) ; break ; } write_len += sizeof ( user_ccb ) ; } if ( error != 0 && write_len == 0 ) return ( error ) ; if ( write_len == 0 && uio -> uio_resid != 0 ) return ( ENOSPC ) ; return ( 0 ) ; }
Receive CCBs from user mode proc and send them to the HBA
Receive CCBs from user mode proc and send them to the HBA
/*
	 * If we've successfully taken in some amount of
	 * data, return success for that data first.  If
	 * an error is persistent, it will be reported
	 * on the next write.
	 */