17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27a5eb7107SBryan Cantrill /*
2880d5689fSPatrick Mooney  * Copyright 2017 Joyent, Inc.
29a5eb7107SBryan Cantrill  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * av1394 asynchronous module
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate #include <sys/stat.h>
357c478bd9Sstevel@tonic-gate #include <sys/file.h>
367c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
377c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
387c478bd9Sstevel@tonic-gate #include <sys/1394/targets/av1394/av1394_impl.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /* configuration routines */
417c478bd9Sstevel@tonic-gate static void	av1394_async_cleanup(av1394_inst_t *, int);
427c478bd9Sstevel@tonic-gate static int	av1394_async_create_minor_node(av1394_inst_t *);
437c478bd9Sstevel@tonic-gate static void	av1394_async_remove_minor_node(av1394_inst_t *);
447c478bd9Sstevel@tonic-gate static int	av1394_async_update_targetinfo(av1394_inst_t *);
457c478bd9Sstevel@tonic-gate static int	av1394_async_db2arq_type(int);
467c478bd9Sstevel@tonic-gate static void	av1394_async_putbq(av1394_queue_t *, mblk_t *);
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate static int	av1394_ioctl_arq_get_ibuf_size(av1394_inst_t *, void *, int);
497c478bd9Sstevel@tonic-gate static int	av1394_ioctl_arq_set_ibuf_size(av1394_inst_t *, void *, int);
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /* tunables */
527c478bd9Sstevel@tonic-gate int av1394_ibuf_size_default = 64 * 1024;	/* default ibuf size */
537c478bd9Sstevel@tonic-gate int av1394_ibuf_size_max = 1024 * 1024;		/* max ibuf size */
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * --- configuration entry points
587c478bd9Sstevel@tonic-gate  *
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate int
av1394_async_attach(av1394_inst_t * avp)617c478bd9Sstevel@tonic-gate av1394_async_attach(av1394_inst_t *avp)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
647c478bd9Sstevel@tonic-gate 	ddi_iblock_cookie_t ibc = avp->av_attachinfo.iblock_cookie;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	mutex_init(&ap->a_mutex, NULL, MUTEX_DRIVER, ibc);
677c478bd9Sstevel@tonic-gate 	av1394_initq(&ap->a_rq, ibc, av1394_ibuf_size_default);
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	if (av1394_fcp_attach(avp) != DDI_SUCCESS) {
707c478bd9Sstevel@tonic-gate 		av1394_async_cleanup(avp, 1);
717c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
727c478bd9Sstevel@tonic-gate 	}
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	if (av1394_cfgrom_init(avp) != DDI_SUCCESS) {
757c478bd9Sstevel@tonic-gate 		av1394_async_cleanup(avp, 2);
767c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
777c478bd9Sstevel@tonic-gate 	}
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	if (av1394_async_create_minor_node(avp) != DDI_SUCCESS) {
807c478bd9Sstevel@tonic-gate 		av1394_async_cleanup(avp, 3);
817c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (av1394_async_update_targetinfo(avp) != DDI_SUCCESS) {
857c478bd9Sstevel@tonic-gate 		av1394_async_cleanup(avp, 4);
867c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
877c478bd9Sstevel@tonic-gate 	}
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate void
av1394_async_detach(av1394_inst_t * avp)937c478bd9Sstevel@tonic-gate av1394_async_detach(av1394_inst_t *avp)
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	av1394_async_cleanup(avp, AV1394_CLEANUP_LEVEL_MAX);
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate void
av1394_async_bus_reset(av1394_inst_t * avp)997c478bd9Sstevel@tonic-gate av1394_async_bus_reset(av1394_inst_t *avp)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
1027c478bd9Sstevel@tonic-gate 	mblk_t		*bp;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	(void) av1394_async_update_targetinfo(avp);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	mutex_enter(&ap->a_mutex);
1077c478bd9Sstevel@tonic-gate 	if (ap->a_nopen > 0) {
1087c478bd9Sstevel@tonic-gate 		mutex_exit(&ap->a_mutex);
1097c478bd9Sstevel@tonic-gate 		return;
1107c478bd9Sstevel@tonic-gate 	}
1117c478bd9Sstevel@tonic-gate 	mutex_exit(&ap->a_mutex);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/* queue up a bus reset message */
114*2570281cSToomas Soome 	if ((bp = allocb(1, BPRI_HI)) != NULL) {
1157c478bd9Sstevel@tonic-gate 		DB_TYPE(bp) = AV1394_M_BUS_RESET;
1167c478bd9Sstevel@tonic-gate 		av1394_async_putq_rq(avp, bp);
1177c478bd9Sstevel@tonic-gate 	}
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate int
av1394_async_cpr_resume(av1394_inst_t * avp)1217c478bd9Sstevel@tonic-gate av1394_async_cpr_resume(av1394_inst_t *avp)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	int	ret;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	ret = av1394_async_update_targetinfo(avp);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	return (ret);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate void
av1394_async_reconnect(av1394_inst_t * avp)1317c478bd9Sstevel@tonic-gate av1394_async_reconnect(av1394_inst_t *avp)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	(void) av1394_async_update_targetinfo(avp);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate int
av1394_async_open(av1394_inst_t * avp,int flag)1377c478bd9Sstevel@tonic-gate av1394_async_open(av1394_inst_t *avp, int flag)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	mutex_enter(&ap->a_mutex);
1427c478bd9Sstevel@tonic-gate 	if (ap->a_nopen == 0) {
1437c478bd9Sstevel@tonic-gate 		ap->a_pollevents = 0;
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 	ap->a_nopen++;
1467c478bd9Sstevel@tonic-gate 	ap->a_oflag = flag;
1477c478bd9Sstevel@tonic-gate 	mutex_exit(&ap->a_mutex);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	return (0);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1537c478bd9Sstevel@tonic-gate int
av1394_async_close(av1394_inst_t * avp,int flag)1547c478bd9Sstevel@tonic-gate av1394_async_close(av1394_inst_t *avp, int flag)
1557c478bd9Sstevel@tonic-gate {
1567c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	av1394_cfgrom_close(avp);
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	av1394_flushq(&ap->a_rq);
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	mutex_enter(&ap->a_mutex);
1637c478bd9Sstevel@tonic-gate 	ap->a_nopen = 0;
1647c478bd9Sstevel@tonic-gate 	ap->a_pollevents = 0;
1657c478bd9Sstevel@tonic-gate 	mutex_exit(&ap->a_mutex);
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	return (0);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate int
av1394_async_read(av1394_inst_t * avp,struct uio * uiop)1717c478bd9Sstevel@tonic-gate av1394_async_read(av1394_inst_t *avp, struct uio *uiop)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
1747c478bd9Sstevel@tonic-gate 	av1394_queue_t	*q = &ap->a_rq;
1757c478bd9Sstevel@tonic-gate 	iec61883_arq_t	arq;
1767c478bd9Sstevel@tonic-gate 	int		ret = 0;
1777c478bd9Sstevel@tonic-gate 	mblk_t		*mp;
1787c478bd9Sstevel@tonic-gate 	int		dbtype;
1797c478bd9Sstevel@tonic-gate 	int		len;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	/* copyout as much as we can */
1827c478bd9Sstevel@tonic-gate 	while ((uiop->uio_resid > 0) && (ret == 0)) {
1837c478bd9Sstevel@tonic-gate 		/*
1847c478bd9Sstevel@tonic-gate 		 * if data is available, copy it out. otherwise wait until
1857c478bd9Sstevel@tonic-gate 		 * data arrives, unless opened with non-blocking flag
1867c478bd9Sstevel@tonic-gate 		 */
1877c478bd9Sstevel@tonic-gate 		if ((mp = av1394_getq(q)) == NULL) {
1887c478bd9Sstevel@tonic-gate 			if (ap->a_oflag & FNDELAY) {
1897c478bd9Sstevel@tonic-gate 				return (EAGAIN);
1907c478bd9Sstevel@tonic-gate 			}
1917c478bd9Sstevel@tonic-gate 			if (av1394_qwait_sig(q) <= 0) {
1927c478bd9Sstevel@tonic-gate 				ret = EINTR;
1937c478bd9Sstevel@tonic-gate 			}
1947c478bd9Sstevel@tonic-gate 			continue;
1957c478bd9Sstevel@tonic-gate 		}
1967c478bd9Sstevel@tonic-gate 		dbtype = AV1394_DBTYPE(mp);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 		/* generate and copyout ARQ header, if not already */
1997c478bd9Sstevel@tonic-gate 		if (!AV1394_IS_NOHDR(mp)) {
2007c478bd9Sstevel@tonic-gate 			/* headers cannot be partially read */
2017c478bd9Sstevel@tonic-gate 			if (uiop->uio_resid < sizeof (arq)) {
2027c478bd9Sstevel@tonic-gate 				av1394_async_putbq(q, mp);
2037c478bd9Sstevel@tonic-gate 				ret = EINVAL;
2047c478bd9Sstevel@tonic-gate 				break;
2057c478bd9Sstevel@tonic-gate 			}
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 			arq.arq_type = av1394_async_db2arq_type(dbtype);
2087c478bd9Sstevel@tonic-gate 			arq.arq_len = MBLKL(mp);
2097c478bd9Sstevel@tonic-gate 			arq.arq_data.octlet = 0;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 			/* copy ARQ-embedded data */
2127c478bd9Sstevel@tonic-gate 			len = min(arq.arq_len, sizeof (arq.arq_data));
2137c478bd9Sstevel@tonic-gate 			bcopy(mp->b_rptr, &arq.arq_data.buf[0], len);
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 			/* copyout the ARQ */
2167c478bd9Sstevel@tonic-gate 			ret = uiomove(&arq, sizeof (arq), UIO_READ, uiop);
2177c478bd9Sstevel@tonic-gate 			if (ret != 0) {
2187c478bd9Sstevel@tonic-gate 				av1394_async_putbq(q, mp);
2197c478bd9Sstevel@tonic-gate 				break;
2207c478bd9Sstevel@tonic-gate 			}
2217c478bd9Sstevel@tonic-gate 			mp->b_rptr += len;
2227c478bd9Sstevel@tonic-gate 			AV1394_MARK_NOHDR(mp);
2237c478bd9Sstevel@tonic-gate 		}
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 		/* any data left? */
2267c478bd9Sstevel@tonic-gate 		if (MBLKL(mp) == 0) {
2277c478bd9Sstevel@tonic-gate 			freemsg(mp);
2287c478bd9Sstevel@tonic-gate 			continue;
2297c478bd9Sstevel@tonic-gate 		}
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 		/* now we have some data and some user buffer space to fill */
2327c478bd9Sstevel@tonic-gate 		len = min(uiop->uio_resid, MBLKL(mp));
2337c478bd9Sstevel@tonic-gate 		if (len > 0) {
2347c478bd9Sstevel@tonic-gate 			ret = uiomove(mp->b_rptr, len, UIO_READ, uiop);
2357c478bd9Sstevel@tonic-gate 			if (ret != 0) {
2367c478bd9Sstevel@tonic-gate 				av1394_async_putbq(q, mp);
2377c478bd9Sstevel@tonic-gate 				break;
2387c478bd9Sstevel@tonic-gate 			}
2397c478bd9Sstevel@tonic-gate 			mp->b_rptr += len;
2407c478bd9Sstevel@tonic-gate 		}
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		/* save the rest of the data for later */
2437c478bd9Sstevel@tonic-gate 		if (MBLKL(mp) > 0) {
2447c478bd9Sstevel@tonic-gate 			av1394_async_putbq(q, mp);
2457c478bd9Sstevel@tonic-gate 		}
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	return (0);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate int
av1394_async_write(av1394_inst_t * avp,struct uio * uiop)2527c478bd9Sstevel@tonic-gate av1394_async_write(av1394_inst_t *avp, struct uio *uiop)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate 	iec61883_arq_t	arq;
2557c478bd9Sstevel@tonic-gate 	int		ret;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	/* all data should arrive in ARQ format */
2587c478bd9Sstevel@tonic-gate 	while (uiop->uio_resid >= sizeof (arq)) {
2597c478bd9Sstevel@tonic-gate 		if ((ret = uiomove(&arq, sizeof (arq), UIO_WRITE, uiop)) != 0) {
2607c478bd9Sstevel@tonic-gate 			break;
2617c478bd9Sstevel@tonic-gate 		}
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		switch (arq.arq_type) {
2647c478bd9Sstevel@tonic-gate 		case IEC61883_ARQ_FCP_CMD:
2657c478bd9Sstevel@tonic-gate 		case IEC61883_ARQ_FCP_RESP:
2667c478bd9Sstevel@tonic-gate 			ret = av1394_fcp_write(avp, &arq, uiop);
2677c478bd9Sstevel@tonic-gate 			break;
2687c478bd9Sstevel@tonic-gate 		default:
2697c478bd9Sstevel@tonic-gate 			ret = EINVAL;
2707c478bd9Sstevel@tonic-gate 		}
2717c478bd9Sstevel@tonic-gate 		if (ret != 0) {
2727c478bd9Sstevel@tonic-gate 			break;
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	return (ret);
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2807c478bd9Sstevel@tonic-gate int
av1394_async_ioctl(av1394_inst_t * avp,int cmd,intptr_t arg,int mode,int * rvalp)2817c478bd9Sstevel@tonic-gate av1394_async_ioctl(av1394_inst_t *avp, int cmd, intptr_t arg, int mode,
28280d5689fSPatrick Mooney     int *rvalp)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate 	int	ret = EINVAL;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	switch (cmd) {
2877c478bd9Sstevel@tonic-gate 	case IEC61883_ARQ_GET_IBUF_SIZE:
2887c478bd9Sstevel@tonic-gate 		ret = av1394_ioctl_arq_get_ibuf_size(avp, (void *)arg, mode);
2897c478bd9Sstevel@tonic-gate 		break;
2907c478bd9Sstevel@tonic-gate 	case IEC61883_ARQ_SET_IBUF_SIZE:
2917c478bd9Sstevel@tonic-gate 		ret = av1394_ioctl_arq_set_ibuf_size(avp, (void *)arg, mode);
2927c478bd9Sstevel@tonic-gate 		break;
2937c478bd9Sstevel@tonic-gate 	case IEC61883_NODE_GET_BUS_NAME:
2947c478bd9Sstevel@tonic-gate 		ret = av1394_ioctl_node_get_bus_name(avp, (void *)arg, mode);
2957c478bd9Sstevel@tonic-gate 		break;
2967c478bd9Sstevel@tonic-gate 	case IEC61883_NODE_GET_UID:
2977c478bd9Sstevel@tonic-gate 		ret = av1394_ioctl_node_get_uid(avp, (void *)arg, mode);
2987c478bd9Sstevel@tonic-gate 		break;
2997c478bd9Sstevel@tonic-gate 	case IEC61883_NODE_GET_TEXT_LEAF:
3007c478bd9Sstevel@tonic-gate 		ret = av1394_ioctl_node_get_text_leaf(avp, (void *)arg, mode);
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	return (ret);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate int
av1394_async_poll(av1394_inst_t * avp,short events,int anyyet,short * reventsp,struct pollhead ** phpp)3077c478bd9Sstevel@tonic-gate av1394_async_poll(av1394_inst_t *avp, short events, int anyyet, short *reventsp,
30880d5689fSPatrick Mooney     struct pollhead **phpp)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
3117c478bd9Sstevel@tonic-gate 	av1394_queue_t	*rq = &ap->a_rq;
3127c478bd9Sstevel@tonic-gate 
31380d5689fSPatrick Mooney 	if (events & (POLLIN | POLLET)) {
31480d5689fSPatrick Mooney 		if ((events & POLLIN) && av1394_peekq(rq)) {
3157c478bd9Sstevel@tonic-gate 			*reventsp |= POLLIN;
31680d5689fSPatrick Mooney 		}
317a5eb7107SBryan Cantrill 
318a5eb7107SBryan Cantrill 		if ((!*reventsp && !anyyet) || (events & POLLET)) {
3197c478bd9Sstevel@tonic-gate 			mutex_enter(&ap->a_mutex);
32080d5689fSPatrick Mooney 			if (events & POLLIN) {
32180d5689fSPatrick Mooney 				ap->a_pollevents |= POLLIN;
32280d5689fSPatrick Mooney 			}
3237c478bd9Sstevel@tonic-gate 			*phpp = &ap->a_pollhead;
3247c478bd9Sstevel@tonic-gate 			mutex_exit(&ap->a_mutex);
3257c478bd9Sstevel@tonic-gate 		}
3267c478bd9Sstevel@tonic-gate 	}
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	return (0);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate /*
3337c478bd9Sstevel@tonic-gate  * put a message on the read queue, take care of polling
3347c478bd9Sstevel@tonic-gate  */
3357c478bd9Sstevel@tonic-gate void
av1394_async_putq_rq(av1394_inst_t * avp,mblk_t * mp)3367c478bd9Sstevel@tonic-gate av1394_async_putq_rq(av1394_inst_t *avp, mblk_t *mp)
3377c478bd9Sstevel@tonic-gate {
3387c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	if (!av1394_putq(&ap->a_rq, mp)) {
3417c478bd9Sstevel@tonic-gate 		freemsg(mp);
3427c478bd9Sstevel@tonic-gate 	} else {
3437c478bd9Sstevel@tonic-gate 		mutex_enter(&ap->a_mutex);
3447c478bd9Sstevel@tonic-gate 		if (ap->a_pollevents & POLLIN) {
3457c478bd9Sstevel@tonic-gate 			ap->a_pollevents &= ~POLLIN;
3467c478bd9Sstevel@tonic-gate 			mutex_exit(&ap->a_mutex);
3477c478bd9Sstevel@tonic-gate 			pollwakeup(&ap->a_pollhead, POLLIN);
3487c478bd9Sstevel@tonic-gate 		} else {
3497c478bd9Sstevel@tonic-gate 			mutex_exit(&ap->a_mutex);
3507c478bd9Sstevel@tonic-gate 		}
3517c478bd9Sstevel@tonic-gate 	}
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate /*
3557c478bd9Sstevel@tonic-gate  *
3567c478bd9Sstevel@tonic-gate  * --- configuration routines
3577c478bd9Sstevel@tonic-gate  *
3587c478bd9Sstevel@tonic-gate  * av1394_async_cleanup()
3597c478bd9Sstevel@tonic-gate  *    Cleanup after attach
3607c478bd9Sstevel@tonic-gate  */
3617c478bd9Sstevel@tonic-gate static void
av1394_async_cleanup(av1394_inst_t * avp,int level)3627c478bd9Sstevel@tonic-gate av1394_async_cleanup(av1394_inst_t *avp, int level)
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	ASSERT((level > 0) && (level <= AV1394_CLEANUP_LEVEL_MAX));
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	switch (level) {
3697c478bd9Sstevel@tonic-gate 	default:
3707c478bd9Sstevel@tonic-gate 		av1394_async_remove_minor_node(avp);
3717c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
3727c478bd9Sstevel@tonic-gate 	case 3:
3737c478bd9Sstevel@tonic-gate 		av1394_cfgrom_fini(avp);
3747c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
3757c478bd9Sstevel@tonic-gate 	case 2:
3767c478bd9Sstevel@tonic-gate 		av1394_fcp_detach(avp);
3777c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
3787c478bd9Sstevel@tonic-gate 	case 1:
3797c478bd9Sstevel@tonic-gate 		av1394_destroyq(&ap->a_rq);
3807c478bd9Sstevel@tonic-gate 		mutex_destroy(&ap->a_mutex);
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate /*
3857c478bd9Sstevel@tonic-gate  * av1394_async_create_minor_node()
3867c478bd9Sstevel@tonic-gate  *    Create async minor node
3877c478bd9Sstevel@tonic-gate  */
3887c478bd9Sstevel@tonic-gate static int
av1394_async_create_minor_node(av1394_inst_t * avp)3897c478bd9Sstevel@tonic-gate av1394_async_create_minor_node(av1394_inst_t *avp)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	int	ret;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	ret = ddi_create_minor_node(avp->av_dip, "async",
394a5eb7107SBryan Cantrill 	    S_IFCHR, AV1394_ASYNC_INST2MINOR(avp->av_instance),
39592548b6cSToomas Soome 	    DDI_NT_AV_ASYNC, 0);
3967c478bd9Sstevel@tonic-gate 	return (ret);
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate /*
4007c478bd9Sstevel@tonic-gate  * av1394_async_remove_minor_node()
4017c478bd9Sstevel@tonic-gate  *    Remove async minor node
4027c478bd9Sstevel@tonic-gate  */
4037c478bd9Sstevel@tonic-gate static void
av1394_async_remove_minor_node(av1394_inst_t * avp)4047c478bd9Sstevel@tonic-gate av1394_async_remove_minor_node(av1394_inst_t *avp)
4057c478bd9Sstevel@tonic-gate {
4067c478bd9Sstevel@tonic-gate 	ddi_remove_minor_node(avp->av_dip, "async");
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate  * av1394_async_update_targetinfo()
4117c478bd9Sstevel@tonic-gate  *    Retrieve target info and bus generation
4127c478bd9Sstevel@tonic-gate  */
4137c478bd9Sstevel@tonic-gate static int
av1394_async_update_targetinfo(av1394_inst_t * avp)4147c478bd9Sstevel@tonic-gate av1394_async_update_targetinfo(av1394_inst_t *avp)
4157c478bd9Sstevel@tonic-gate {
4167c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
4177c478bd9Sstevel@tonic-gate 	uint_t		bg;
4187c478bd9Sstevel@tonic-gate 	int		ret;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	mutex_enter(&avp->av_mutex);
4217c478bd9Sstevel@tonic-gate 	bg = avp->av_attachinfo.localinfo.bus_generation;
4227c478bd9Sstevel@tonic-gate 	mutex_exit(&avp->av_mutex);
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	mutex_enter(&ap->a_mutex);
4257c478bd9Sstevel@tonic-gate 	ret = t1394_get_targetinfo(avp->av_t1394_hdl, bg, 0, &ap->a_targetinfo);
4267c478bd9Sstevel@tonic-gate 	ap->a_bus_generation = bg;
4277c478bd9Sstevel@tonic-gate 	mutex_exit(&ap->a_mutex);
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	return (ret);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate static int
av1394_async_db2arq_type(int dbtype)4337c478bd9Sstevel@tonic-gate av1394_async_db2arq_type(int dbtype)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	int	arq_type;
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	switch (dbtype) {
4387c478bd9Sstevel@tonic-gate 	case AV1394_M_FCP_RESP:
4397c478bd9Sstevel@tonic-gate 		arq_type = IEC61883_ARQ_FCP_RESP;
4407c478bd9Sstevel@tonic-gate 		break;
4417c478bd9Sstevel@tonic-gate 	case AV1394_M_FCP_CMD:
4427c478bd9Sstevel@tonic-gate 		arq_type = IEC61883_ARQ_FCP_CMD;
4437c478bd9Sstevel@tonic-gate 		break;
4447c478bd9Sstevel@tonic-gate 	case AV1394_M_BUS_RESET:
4457c478bd9Sstevel@tonic-gate 		arq_type = IEC61883_ARQ_BUS_RESET;
4467c478bd9Sstevel@tonic-gate 		break;
4477c478bd9Sstevel@tonic-gate 	default:
4487c478bd9Sstevel@tonic-gate 		ASSERT(0);	/* cannot happen */
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate 	return (arq_type);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate static void
av1394_async_putbq(av1394_queue_t * q,mblk_t * mp)4547c478bd9Sstevel@tonic-gate av1394_async_putbq(av1394_queue_t *q, mblk_t *mp)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate 	if (!av1394_putbq(q, mp)) {
4577c478bd9Sstevel@tonic-gate 		freemsg(mp);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4627c478bd9Sstevel@tonic-gate static int
av1394_ioctl_arq_get_ibuf_size(av1394_inst_t * avp,void * arg,int mode)4637c478bd9Sstevel@tonic-gate av1394_ioctl_arq_get_ibuf_size(av1394_inst_t *avp, void *arg, int mode)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
4667c478bd9Sstevel@tonic-gate 	int		sz;
4677c478bd9Sstevel@tonic-gate 	int		ret = 0;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	sz = av1394_getmaxq(&ap->a_rq);
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	if (ddi_copyout(&sz, arg, sizeof (sz), mode) != 0) {
4727c478bd9Sstevel@tonic-gate 		ret = EFAULT;
4737c478bd9Sstevel@tonic-gate 	}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	return (ret);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4797c478bd9Sstevel@tonic-gate static int
av1394_ioctl_arq_set_ibuf_size(av1394_inst_t * avp,void * arg,int mode)4807c478bd9Sstevel@tonic-gate av1394_ioctl_arq_set_ibuf_size(av1394_inst_t *avp, void *arg, int mode)
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
4837c478bd9Sstevel@tonic-gate 	int		sz;
4847c478bd9Sstevel@tonic-gate 	int		ret = 0;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	sz = (int)(intptr_t)arg;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	if ((sz < 0) || (sz > av1394_ibuf_size_max)) {
4897c478bd9Sstevel@tonic-gate 		ret = EINVAL;
4907c478bd9Sstevel@tonic-gate 	} else {
4917c478bd9Sstevel@tonic-gate 		av1394_setmaxq(&ap->a_rq, sz);
4927c478bd9Sstevel@tonic-gate 	}
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	return (ret);
4957c478bd9Sstevel@tonic-gate }
496