FreeBSD/sys/cam/scsi/scsi_target.c
/* Return CCBs to the user from the user queue and abort queue */
Return CCBs to the user from the user queue and abort queue
Return CCBs to the user from the user queue and abort queue
static int
targread(struct cdev *dev, struct uio *uio, int ioflag)
{
	struct descr_queue	*abort_queue;
	struct targ_cmd_descr	*user_descr;
	struct targ_softc	*softc;
	struct ccb_queue  *user_queue;
	struct ccb_hdr	  *ccb_h;
	union  ccb	  *user_ccb;
	int		   read_len, error;
	error = 0;
	read_len = 0;
	devfs_get_cdevpriv((void **)&softc);
	user_queue = &softc->user_ccb_queue;
	abort_queue = &softc->abort_queue;
	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
	cam_periph_lock(softc->periph);
	ccb_h = TAILQ_FIRST(user_queue);
	user_descr = TAILQ_FIRST(abort_queue);
	while (ccb_h == NULL && user_descr == NULL) {
		if ((ioflag & IO_NDELAY) == 0) {
			error = cam_periph_sleep(softc->periph, user_queue,
			    PRIBIO | PCATCH, "targrd", 0);
			ccb_h = TAILQ_FIRST(user_queue);
			user_descr = TAILQ_FIRST(abort_queue);
			if (error != 0) {
				if (error == ERESTART) {
					continue;
				} else {
					goto read_fail;
				}
			}
		} else {
			cam_periph_unlock(softc->periph);
			return (EAGAIN);
		}
	}
	while (ccb_h != NULL) {
		struct targ_cmd_descr *descr;
		if (uio->uio_resid < sizeof(user_ccb))
			break;
		TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe);
		descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
		user_ccb = descr->user_ccb;
		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
			  ("targread ccb %p (%p)\n", ccb_h, user_ccb));
		error = targreturnccb(softc, (union ccb *)ccb_h);
		if (error != 0)
			goto read_fail;
		cam_periph_unlock(softc->periph);
		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
		cam_periph_lock(softc->periph);
		if (error != 0)
			goto read_fail;
		read_len += sizeof(user_ccb);
		ccb_h = TAILQ_FIRST(user_queue);
	}
	while (user_descr != NULL) {
		if (uio->uio_resid < sizeof(user_ccb))
			break;
		TAILQ_REMOVE(abort_queue, user_descr, tqe);
		user_ccb = user_descr->user_ccb;
		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
			  ("targread aborted descr %p (%p)\n",
			  user_descr, user_ccb));
		suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
		cam_periph_unlock(softc->periph);
		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
		cam_periph_lock(softc->periph);
		if (error != 0)
			goto read_fail;
		read_len += sizeof(user_ccb);
		user_descr = TAILQ_FIRST(abort_queue);
	}
	if (read_len == 0 && uio->uio_resid != 0)
		error = ENOSPC;
read_fail:
	cam_periph_unlock(softc->periph);
	return (error);
}
static int targread ( struct cdev * dev , struct uio * uio , int ioflag ) { struct descr_queue * abort_queue ; struct targ_cmd_descr * user_descr ; struct targ_softc * softc ; struct ccb_queue * user_queue ; struct ccb_hdr * ccb_h ; union ccb * user_ccb ; int read_len , error ; error = 0 ; read_len = 0 ; devfs_get_cdevpriv ( ( void * * ) & softc ) ; user_queue = & softc -> user_ccb_queue ; abort_queue = & softc -> abort_queue ; CAM_DEBUG ( softc -> path , CAM_DEBUG_PERIPH , ( " \n " ) ) ; cam_periph_lock ( softc -> periph ) ; ccb_h = TAILQ_FIRST ( user_queue ) ; user_descr = TAILQ_FIRST ( abort_queue ) ; while ( ccb_h == NULL && user_descr == NULL ) { if ( ( ioflag & IO_NDELAY ) == 0 ) { error = cam_periph_sleep ( softc -> periph , user_queue , PRIBIO | PCATCH , " " , 0 ) ; ccb_h = TAILQ_FIRST ( user_queue ) ; user_descr = TAILQ_FIRST ( abort_queue ) ; if ( error != 0 ) { if ( error == ERESTART ) { continue ; } else { goto read_fail ; } } } else { cam_periph_unlock ( softc -> periph ) ; return ( EAGAIN ) ; } } while ( ccb_h != NULL ) { struct targ_cmd_descr * descr ; if ( uio -> uio_resid < sizeof ( user_ccb ) ) break ; TAILQ_REMOVE ( user_queue , ccb_h , periph_links . tqe ) ; descr = ( struct targ_cmd_descr * ) ccb_h -> targ_descr ; user_ccb = descr -> user_ccb ; CAM_DEBUG ( softc -> path , CAM_DEBUG_PERIPH , ( " \n " , ccb_h , user_ccb ) ) ; error = targreturnccb ( softc , ( union ccb * ) ccb_h ) ; if ( error != 0 ) goto read_fail ; cam_periph_unlock ( softc -> periph ) ; error = uiomove ( ( caddr_t ) & user_ccb , sizeof ( user_ccb ) , uio ) ; cam_periph_lock ( softc -> periph ) ; if ( error != 0 ) goto read_fail ; read_len += sizeof ( user_ccb ) ; ccb_h = TAILQ_FIRST ( user_queue ) ; } while ( user_descr != NULL ) { if ( uio -> uio_resid < sizeof ( user_ccb ) ) break ; TAILQ_REMOVE ( abort_queue , user_descr , tqe ) ; user_ccb = user_descr -> user_ccb ; CAM_DEBUG ( softc -> path , CAM_DEBUG_PERIPH , ( " \n " , user_descr , user_ccb ) ) ; suword ( & user_ccb -> ccb_h . status , CAM_REQ_ABORTED ) ; cam_periph_unlock ( softc -> periph ) ; error = uiomove ( ( caddr_t ) & user_ccb , sizeof ( user_ccb ) , uio ) ; cam_periph_lock ( softc -> periph ) ; if ( error != 0 ) goto read_fail ; read_len += sizeof ( user_ccb ) ; user_descr = TAILQ_FIRST ( abort_queue ) ; } if ( read_len == 0 && uio -> uio_resid != 0 ) error = ENOSPC ; read_fail : cam_periph_unlock ( softc -> periph ) ; return ( error ) ; }
Return CCBs to the user from the user queue and abort queue
Return CCBs to the user from the user queue and abort queue
/* If no data is available, wait or return immediately */ /* Data is available so fill the user's buffer */ /* Flush out any aborted descriptors */ /*
	 * If we've successfully read some amount of data, don't report an
	 * error.  If the error is persistent, it will be reported on the
	 * next read().
	 */