3 #include <sys/stream.h>
5 #include <sys/modctl.h>
6 #include <sys/cmn_err.h>
8 #include <sys/socket.h>
9 #include <sys/sockio.h>
11 #include <sys/ethernet.h>
12 #include <sys/byteorder.h>
13 #include <sys/sunddi.h>
17 #include <netatalk/phase2.h>
18 #include <netatalk/at.h>
23 u_char at_multicastaddr[ ETHERADDRL ] = {
24 0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
26 u_char at_org_code[ 3 ] = {
29 u_char aarp_org_code[ 3 ] = {
34 dlpi_open( queue_t *q, dev_t *dev, int oflag, int sflag, cred_t *cred )
36 struct atif_data *aid;
39 if (( err = drv_priv( cred )) != 0 ) {
42 if (( aid = if_alloc( q )) == NULL ) {
45 q->q_ptr = (void *)aid;
52 dlpi_close( queue_t *q, int oflag, cred_t *cred )
54 struct atif_data *aid = (struct atif_data *)q->q_ptr;
62 dl_bind_req( queue_t *q, ulong sap )
64 union DL_primitives *dl;
67 if (( m = allocb( DL_BIND_REQ_SIZE, BPRI_HI )) == NULL ) {
70 m->b_wptr = m->b_rptr + DL_BIND_REQ_SIZE;
71 m->b_datap->db_type = M_PROTO;
73 dl = (union DL_primitives *)m->b_rptr;
74 dl->dl_primitive = DL_BIND_REQ;
75 dl->bind_req.dl_sap = sap;
76 dl->bind_req.dl_max_conind = 0;
77 dl->bind_req.dl_service_mode = DL_CLDLS;
78 dl->bind_req.dl_conn_mgmt = 0;
79 dl->bind_req.dl_xidtest_flg = 0; /* XXX */
85 dl_attach_req( queue_t *q, ulong ppa )
87 union DL_primitives *dl;
90 if (( m = allocb( DL_ATTACH_REQ_SIZE, BPRI_HI )) == NULL ) {
93 m->b_wptr = m->b_rptr + DL_ATTACH_REQ_SIZE;
94 m->b_datap->db_type = M_PROTO;
96 dl = (union DL_primitives *)m->b_rptr;
97 dl->dl_primitive = DL_ATTACH_REQ;
98 dl->attach_req.dl_ppa = ppa;
104 dl_enabmulti_req( queue_t *q, caddr_t addr )
106 union DL_primitives *dl;
109 if (( m = allocb( DL_ENABMULTI_REQ_SIZE + ETHERADDRL, BPRI_HI )) == NULL ) {
112 m->b_wptr = m->b_rptr + DL_ENABMULTI_REQ_SIZE;
113 m->b_datap->db_type = M_PROTO;
115 dl = (union DL_primitives *)m->b_rptr;
116 dl->dl_primitive = DL_ENABMULTI_REQ;
117 dl->enabmulti_req.dl_addr_length = ETHERADDRL;
118 dl->enabmulti_req.dl_addr_offset = m->b_wptr - m->b_rptr;
119 bcopy( addr, m->b_wptr, ETHERADDRL );
120 m->b_wptr += ETHERADDRL;
126 dl_unitdata_req( queue_t *q, mblk_t *m0, ushort type, caddr_t addr )
128 union DL_primitives *dl;
133 /* len = msgdsize( m0 ) + sizeof( struct llc ); */
135 if (( m1 = allocb( sizeof( struct llc ), BPRI_HI )) == NULL ) {
136 cmn_err( CE_NOTE, "dl_unitdate_req NOMEM 1\n" );
139 m1->b_wptr = m1->b_rptr + sizeof( struct llc );
140 m1->b_datap->db_type = M_DATA;
141 llc = (struct llc *)m1->b_rptr;
143 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
144 llc->llc_control = LLC_UI;
145 if ( type == ETHERTYPE_AARP ) {
146 bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
147 } else if ( type == ETHERTYPE_AT ) {
148 bcopy( at_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
150 cmn_err( CE_NOTE, "dl_unitdate_req type %X\n", type );
153 llc->llc_ether_type = htons( type );
156 if (( m = allocb( DL_UNITDATA_REQ_SIZE + ETHERADDRL + sizeof( ushort ),
157 BPRI_HI )) == NULL ) {
158 cmn_err( CE_NOTE, "dl_unitdate_req NOMEM 2\n" );
161 m->b_wptr = m->b_rptr + DL_UNITDATA_REQ_SIZE;
162 m->b_datap->db_type = M_PROTO;
165 dl = (union DL_primitives *)m->b_rptr;
166 dl->dl_primitive = DL_UNITDATA_REQ;
167 dl->unitdata_req.dl_dest_addr_length = ETHERADDRL + sizeof ( ushort );
168 dl->unitdata_req.dl_dest_addr_offset = m->b_wptr - m->b_rptr;
170 bcopy(addr, m->b_wptr, ETHERADDRL );
171 m->b_wptr += ETHERADDRL;
173 bcopy( &len, m->b_wptr, sizeof( ushort ));
174 m->b_wptr += sizeof( ushort );
180 dlpi_rput( queue_t *q, mblk_t *m )
182 struct atif_data *aid = (struct atif_data *)q->q_ptr;
183 union DL_primitives *dl;
187 switch ( m->b_datap->db_type ) {
194 if ( m->b_wptr - m->b_rptr < sizeof( dl->dl_primitive )) {
197 dl = (union DL_primitives *)m->b_rptr;
198 switch ( dl->dl_primitive ) {
199 case DL_UNITDATA_IND :
200 if ( m->b_wptr - m->b_rptr < sizeof( DL_UNITDATA_IND_SIZE )) {
203 if (( m0 = unlinkb( m )) == NULL ) {
206 if ( m0->b_wptr - m0->b_rptr < sizeof( struct llc )) {
210 llc = (struct llc *)m0->b_rptr;
211 if ( llc->llc_dsap != LLC_SNAP_LSAP ||
212 llc->llc_ssap != LLC_SNAP_LSAP ||
213 llc->llc_control != LLC_UI ) {
218 if ( bcmp( llc->llc_org_code, at_org_code,
219 sizeof( at_org_code )) == 0 &&
220 ntohs( llc->llc_ether_type ) == ETHERTYPE_AT ) {
221 adjmsg( m0, sizeof( struct llc ));
223 } else if ( bcmp( llc->llc_org_code, aarp_org_code,
224 sizeof( aarp_org_code )) == 0 &&
225 ntohs( llc->llc_ether_type ) == ETHERTYPE_AARP ) {
226 adjmsg( m0, sizeof( struct llc ));
234 if ( m->b_wptr - m->b_rptr < sizeof( DL_OK_ACK_SIZE )) {
237 switch ( dl->ok_ack.dl_correct_primitive ) {
239 if ( aid->aid_state != DL_ATTACH_PENDING ) {
240 cmn_err( CE_NOTE, "dlpi_rput DL_OK_ACK attach state %d\n",
244 if ( aid->aid_c.c_type != IF_UNITSEL ) {
245 cmn_err( CE_NOTE, "dlpi_rput DL_OK_ACK attach context %x\n",
250 if ( WR(q)->q_next == NULL || WR(q)->q_next->q_qinfo == NULL ||
251 WR(q)->q_next->q_qinfo->qi_minfo == NULL ||
252 WR(q)->q_next->q_qinfo->qi_minfo->mi_idname == NULL ) {
253 cmn_err( CE_NOTE, "dlpi_rput can't get interface name\n" );
257 if_name( aid, WR(q)->q_next->q_qinfo->qi_minfo->mi_idname,
258 aid->aid_c.c_u.u_unit.uu_ppa );
260 aid->aid_state = DL_BIND_PENDING;
264 * As of Solaris 7 (nice name), the i386 arch needs to be
265 * bound as 0 to receive 802 frames. However, in the same
266 * OS, Sparcs must be bound as ETHERMTU (or at least not 0)
267 * to receive the same frames. A bug? In the Solaris 7
268 * (nice name) kernel?
270 dl_bind_req( WR( q ), 0 );
272 dl_bind_req( WR( q ), ETHERMTU );
276 case DL_ENABMULTI_REQ :
277 if ( aid->aid_c.c_type != SIOCADDMULTI ) {
279 "dlpi_rput DL_OK_ACK enabmulti context %x\n",
284 ioc_ok_ack( aid->aid_c.c_u.u_multi.um_q,
285 aid->aid_c.c_u.u_multi.um_m, 0 );
286 aid->aid_c.c_type = 0;
287 aid->aid_c.c_u.u_multi.um_q = NULL;
288 aid->aid_c.c_u.u_multi.um_m = 0;
292 cmn_err( CE_CONT, "!dlpi_rput DL_OK_ACK unhandled %d\n",
293 dl->ok_ack.dl_correct_primitive );
299 if ( m->b_wptr - m->b_rptr < sizeof( DL_BIND_ACK_SIZE )) {
302 if ( aid->aid_state != DL_BIND_PENDING ) {
305 if ( aid->aid_c.c_type != IF_UNITSEL ) {
308 bcopy( m->b_rptr + dl->bind_ack.dl_addr_offset, aid->aid_hwaddr,
309 dl->bind_ack.dl_addr_length );
310 aid->aid_state = DL_IDLE;
311 ioc_ok_ack( WR(q), aid->aid_c.c_u.u_unit.uu_m, 0 );
312 aid->aid_c.c_type = 0;
313 aid->aid_c.c_u.u_unit.uu_m = NULL;
314 aid->aid_c.c_u.u_unit.uu_ppa = 0;
318 if ( m->b_wptr - m->b_rptr < sizeof( DL_ERROR_ACK_SIZE )) {
322 switch ( aid->aid_c.c_type ) {
324 if ( dl->error_ack.dl_errno == DL_SYSERR ) {
325 ioc_error_ack( WR(q), aid->aid_c.c_u.u_unit.uu_m,
326 dl->error_ack.dl_unix_errno );
328 cmn_err( CE_CONT, "dlpi_rput DL_ERROR_ACK 0x%x\n",
329 dl->error_ack.dl_errno );
330 ioc_error_ack( WR(q), aid->aid_c.c_u.u_unit.uu_m, EINVAL );
332 aid->aid_c.c_type = 0;
333 aid->aid_c.c_u.u_unit.uu_m = NULL;
334 aid->aid_c.c_u.u_unit.uu_ppa = 0;
338 cmn_err( CE_NOTE, "dlpi_rput DL_ERROR_ACK unhandled %d %d %d\n",
339 dl->error_ack.dl_error_primitive,
340 dl->error_ack.dl_errno, dl->error_ack.dl_unix_errno );
346 cmn_err( CE_NOTE, "dlpi_rput M_PCPROTO 0x%x\n", dl->dl_primitive );
352 cmn_err( CE_NOTE, "dlpi_rput 0x%X\n", m->b_datap->db_type );
361 dlpi_wput( queue_t *q, mblk_t *m )
363 struct atif_data *aid = (struct atif_data *)RD(q)->q_ptr;
367 switch ( m->b_datap->db_type ) {
369 if ( m->b_wptr - m->b_rptr < sizeof( struct iocblk )) {
373 ioc = (struct iocblk *)m->b_rptr;
374 switch ( ioc->ioc_cmd ) {
376 if ( ioc->ioc_count != TRANSPARENT ) {
377 cmn_err( CE_NOTE, "dlpi_wput IF_UNITSEL non-TRANSPARENT\n" );
378 ioc_error_ack( q, m, EINVAL );
381 if ( m->b_cont == NULL ) {
382 cmn_err( CE_NOTE, "dlpi_wput IF_UNITSEL no arg\n" );
383 ioc_error_ack( q, m, EINVAL );
386 if ( aid->aid_state != DL_UNATTACHED ) {
387 cmn_err( CE_NOTE, "dlpi_wput IF_UNITSEL already attached\n" );
388 ioc_error_ack( q, m, EINVAL );
391 if ( aid->aid_c.c_type != 0 ) {
392 cmn_err( CE_NOTE, "dlpi_wput IF_UNITSEL context %x\n",
394 ioc_error_ack( q, m, EINVAL );
398 aid->aid_state = DL_ATTACH_PENDING;
399 aid->aid_c.c_type = IF_UNITSEL;
400 aid->aid_c.c_u.u_unit.uu_m = m;
401 aid->aid_c.c_u.u_unit.uu_ppa = *(ulong *)m->b_cont->b_rptr;
402 if (( rc = dl_attach_req( q, aid->aid_c.c_u.u_unit.uu_ppa )) < 0 ) {
403 ioc_error_ack( q, m, rc );
409 cmn_err( CE_NOTE, "dlpi_wput M_IOCTL 0x%X\n", ioc->ioc_cmd );
416 cmn_err( CE_NOTE, "dlpi_wput 0x%X\n", m->b_datap->db_type );
424 static struct module_info dlpi_info = {
433 static struct qinit dlpi_rinit = {
434 dlpi_rput, /* qi_putp */
436 dlpi_open, /* qi_qopen */
437 dlpi_close, /* qi_qclose */
439 &dlpi_info, /* qi_minfo */
443 static struct qinit dlpi_winit = {
444 dlpi_wput, /* qi_putp */
447 NULL, /* qi_qclose */
449 &dlpi_info, /* qi_minfo */
453 static struct streamtab dlpi_stream = {
460 static struct fmodsw dlpi_fmodsw = {
463 D_NEW | D_MP | D_MTPERMOD
467 * DDP Streams module. This module is pushed on DLPI drivers by atalkd.
469 struct modlstrmod dlpi_lstrmod = {
471 "DDP Streams module",