xref: /illumos-gate/usr/src/uts/common/io/sundlpi.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  *  Common Sun DLPI routines.
30  */
31 
32 #include	<sys/types.h>
33 #include	<sys/sysmacros.h>
34 #include	<sys/byteorder.h>
35 #include	<sys/systm.h>
36 #include	<sys/stream.h>
37 #include	<sys/strsun.h>
38 #include	<sys/dlpi.h>
39 
40 #define		DLADDRL		(80)
41 
42 void
43 dlbindack(
44 	queue_t		*wq,
45 	mblk_t		*mp,
46 	t_scalar_t	sap,
47 	void		*addrp,
48 	t_uscalar_t	addrlen,
49 	t_uscalar_t	maxconind,
50 	t_uscalar_t	xidtest)
51 {
52 	union DL_primitives	*dlp;
53 	size_t			size;
54 
55 	size = sizeof (dl_bind_ack_t) + addrlen;
56 	if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_BIND_ACK)) == NULL)
57 		return;
58 
59 	dlp = (union DL_primitives *)mp->b_rptr;
60 	dlp->bind_ack.dl_sap = sap;
61 	dlp->bind_ack.dl_addr_length = addrlen;
62 	dlp->bind_ack.dl_addr_offset = sizeof (dl_bind_ack_t);
63 	dlp->bind_ack.dl_max_conind = maxconind;
64 	dlp->bind_ack.dl_xidtest_flg = xidtest;
65 	if (addrlen != 0)
66 		bcopy(addrp, mp->b_rptr + sizeof (dl_bind_ack_t), addrlen);
67 
68 	qreply(wq, mp);
69 }
70 
71 void
72 dlokack(
73 	queue_t		*wq,
74 	mblk_t		*mp,
75 	t_uscalar_t	correct_primitive)
76 {
77 	union DL_primitives	*dlp;
78 
79 	if ((mp = mexchange(wq, mp, sizeof (dl_ok_ack_t), M_PCPROTO,
80 	    DL_OK_ACK)) == NULL)
81 		return;
82 	dlp = (union DL_primitives *)mp->b_rptr;
83 	dlp->ok_ack.dl_correct_primitive = correct_primitive;
84 	qreply(wq, mp);
85 }
86 
87 void
88 dlerrorack(
89 	queue_t		*wq,
90 	mblk_t		*mp,
91 	t_uscalar_t	error_primitive,
92 	t_uscalar_t	error,
93 	t_uscalar_t	unix_errno)
94 {
95 	union DL_primitives	*dlp;
96 
97 	if ((mp = mexchange(wq, mp, sizeof (dl_error_ack_t), M_PCPROTO,
98 	    DL_ERROR_ACK)) == NULL)
99 		return;
100 	dlp = (union DL_primitives *)mp->b_rptr;
101 	dlp->error_ack.dl_error_primitive = error_primitive;
102 	dlp->error_ack.dl_errno = error;
103 	dlp->error_ack.dl_unix_errno = unix_errno;
104 	qreply(wq, mp);
105 }
106 
107 void
108 dluderrorind(
109 	queue_t		*wq,
110 	mblk_t		*mp,
111 	void		*addrp,
112 	t_uscalar_t	addrlen,
113 	t_uscalar_t	error,
114 	t_uscalar_t	unix_errno)
115 {
116 	union DL_primitives	*dlp;
117 	char			buf[DLADDRL];
118 	size_t			size;
119 
120 	if (addrlen > DLADDRL)
121 		addrlen = DLADDRL;
122 
123 	bcopy(addrp, buf, addrlen);
124 
125 	size = sizeof (dl_uderror_ind_t) + addrlen;
126 
127 	if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_UDERROR_IND)) == NULL)
128 		return;
129 
130 	dlp = (union DL_primitives *)mp->b_rptr;
131 	dlp->uderror_ind.dl_dest_addr_length = addrlen;
132 	dlp->uderror_ind.dl_dest_addr_offset = sizeof (dl_uderror_ind_t);
133 	dlp->uderror_ind.dl_unix_errno = unix_errno;
134 	dlp->uderror_ind.dl_errno = error;
135 	bcopy((caddr_t)buf,
136 	    (caddr_t)(mp->b_rptr + sizeof (dl_uderror_ind_t)), addrlen);
137 	qreply(wq, mp);
138 }
139 
140 void
141 dlphysaddrack(
142 	queue_t		*wq,
143 	mblk_t		*mp,
144 	void		*addrp,
145 	t_uscalar_t	len)
146 {
147 	union DL_primitives	*dlp;
148 	size_t			size;
149 
150 	size = sizeof (dl_phys_addr_ack_t) + len;
151 	if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_PHYS_ADDR_ACK)) == NULL)
152 		return;
153 	dlp = (union DL_primitives *)mp->b_rptr;
154 	dlp->physaddr_ack.dl_addr_length = len;
155 	dlp->physaddr_ack.dl_addr_offset = sizeof (dl_phys_addr_ack_t);
156 	if (len != 0)
157 		bcopy(addrp, mp->b_rptr + sizeof (dl_phys_addr_ack_t), len);
158 	qreply(wq, mp);
159 }
160 
161 void
162 dlcapabsetqid(dl_mid_t *idp, const queue_t *q)
163 {
164 #ifndef _LP64
165 	idp->mid[0] = (t_uscalar_t)q;
166 #else
167 	idp->mid[0] = (t_uscalar_t)BMASK_32((uint64_t)q);
168 	idp->mid[1] = (t_uscalar_t)BMASK_32(((uint64_t)q) >> 32);
169 #endif
170 }
171 
172 boolean_t
173 dlcapabcheckqid(const dl_mid_t *idp, const queue_t *q)
174 {
175 #ifndef _LP64
176 	return ((queue_t *)(idp->mid[0]) == q);
177 #else
178 	return ((queue_t *)
179 	    ((uint64_t)idp->mid[0] | ((uint64_t)idp->mid[1] << 32)) == q);
180 #endif
181 }
182 
183 void
184 dlnotifyack(
185 	queue_t		*wq,
186 	mblk_t		*mp,
187 	uint32_t	notifications)
188 {
189 	union DL_primitives	*dlp;
190 
191 	if ((mp = mexchange(wq, mp, sizeof (dl_notify_ack_t), M_PROTO,
192 	    DL_NOTIFY_ACK)) == NULL)
193 		return;
194 	dlp = (union DL_primitives *)mp->b_rptr;
195 	dlp->notify_ack.dl_notifications = notifications;
196 	qreply(wq, mp);
197 }
198