1
/* $Id: dlpi.c,v 1.2 2002/01/17 06:13:02 srittau Exp $
8
#include <sys/stream.h>
10
#include <sys/modctl.h>
11
#include <sys/cmn_err.h>
13
#include <sys/socket.h>
14
#include <sys/sockio.h>
16
#include <sys/ethernet.h>
17
#include <sys/byteorder.h>
18
#include <sys/sunddi.h>
22
#include <netatalk/phase2.h>
23
#include <netatalk/at.h>
28
u_char at_multicastaddr[ ETHERADDRL ] = {
29
0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
31
u_char at_org_code[ 3 ] = {
34
u_char aarp_org_code[ 3 ] = {
39
dlpi_open( queue_t *q, dev_t *dev, int oflag, int sflag, cred_t *cred )
41
struct atif_data *aid;
44
if (( err = drv_priv( cred )) != 0 ) {
47
if (( aid = if_alloc( q )) == NULL ) {
50
q->q_ptr = (void *)aid;
57
dlpi_close( queue_t *q, int oflag, cred_t *cred )
59
struct atif_data *aid = (struct atif_data *)q->q_ptr;
67
dl_bind_req( queue_t *q, ulong sap )
69
union DL_primitives *dl;
72
if (( m = allocb( DL_BIND_REQ_SIZE, BPRI_HI )) == NULL ) {
75
m->b_wptr = m->b_rptr + DL_BIND_REQ_SIZE;
76
m->b_datap->db_type = M_PROTO;
78
dl = (union DL_primitives *)m->b_rptr;
79
dl->dl_primitive = DL_BIND_REQ;
80
dl->bind_req.dl_sap = sap;
81
dl->bind_req.dl_max_conind = 0;
82
dl->bind_req.dl_service_mode = DL_CLDLS;
83
dl->bind_req.dl_conn_mgmt = 0;
84
dl->bind_req.dl_xidtest_flg = 0; /* XXX */
90
dl_attach_req( queue_t *q, ulong ppa )
92
union DL_primitives *dl;
95
if (( m = allocb( DL_ATTACH_REQ_SIZE, BPRI_HI )) == NULL ) {
98
m->b_wptr = m->b_rptr + DL_ATTACH_REQ_SIZE;
99
m->b_datap->db_type = M_PROTO;
101
dl = (union DL_primitives *)m->b_rptr;
102
dl->dl_primitive = DL_ATTACH_REQ;
103
dl->attach_req.dl_ppa = ppa;
109
dl_enabmulti_req( queue_t *q, caddr_t addr )
111
union DL_primitives *dl;
114
if (( m = allocb( DL_ENABMULTI_REQ_SIZE + ETHERADDRL, BPRI_HI )) == NULL ) {
117
m->b_wptr = m->b_rptr + DL_ENABMULTI_REQ_SIZE;
118
m->b_datap->db_type = M_PROTO;
120
dl = (union DL_primitives *)m->b_rptr;
121
dl->dl_primitive = DL_ENABMULTI_REQ;
122
dl->enabmulti_req.dl_addr_length = ETHERADDRL;
123
dl->enabmulti_req.dl_addr_offset = m->b_wptr - m->b_rptr;
124
bcopy( addr, m->b_wptr, ETHERADDRL );
125
m->b_wptr += ETHERADDRL;
131
dl_unitdata_req( queue_t *q, mblk_t *m0, ushort type, caddr_t addr )
133
union DL_primitives *dl;
138
/* len = msgdsize( m0 ) + sizeof( struct llc ); */
140
if (( m1 = allocb( sizeof( struct llc ), BPRI_HI )) == NULL ) {
141
cmn_err( CE_NOTE, "dl_unitdate_req NOMEM 1\n" );
144
m1->b_wptr = m1->b_rptr + sizeof( struct llc );
145
m1->b_datap->db_type = M_DATA;
146
llc = (struct llc *)m1->b_rptr;
148
llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
149
llc->llc_control = LLC_UI;
150
if ( type == ETHERTYPE_AARP ) {
151
bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
152
} else if ( type == ETHERTYPE_AT ) {
153
bcopy( at_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
155
cmn_err( CE_NOTE, "dl_unitdate_req type %X\n", type );
158
llc->llc_ether_type = htons( type );
161
if (( m = allocb( DL_UNITDATA_REQ_SIZE + ETHERADDRL + sizeof( ushort ),
162
BPRI_HI )) == NULL ) {
163
cmn_err( CE_NOTE, "dl_unitdate_req NOMEM 2\n" );
166
m->b_wptr = m->b_rptr + DL_UNITDATA_REQ_SIZE;
167
m->b_datap->db_type = M_PROTO;
170
dl = (union DL_primitives *)m->b_rptr;
171
dl->dl_primitive = DL_UNITDATA_REQ;
172
dl->unitdata_req.dl_dest_addr_length = ETHERADDRL + sizeof ( ushort );
173
dl->unitdata_req.dl_dest_addr_offset = m->b_wptr - m->b_rptr;
175
bcopy(addr, m->b_wptr, ETHERADDRL );
176
m->b_wptr += ETHERADDRL;
178
bcopy( &len, m->b_wptr, sizeof( ushort ));
179
m->b_wptr += sizeof( ushort );
185
dlpi_rput( queue_t *q, mblk_t *m )
187
struct atif_data *aid = (struct atif_data *)q->q_ptr;
188
union DL_primitives *dl;
192
switch ( m->b_datap->db_type ) {
199
if ( m->b_wptr - m->b_rptr < sizeof( dl->dl_primitive )) {
202
dl = (union DL_primitives *)m->b_rptr;
203
switch ( dl->dl_primitive ) {
204
case DL_UNITDATA_IND :
205
if ( m->b_wptr - m->b_rptr < sizeof( DL_UNITDATA_IND_SIZE )) {
208
if (( m0 = unlinkb( m )) == NULL ) {
211
if ( m0->b_wptr - m0->b_rptr < sizeof( struct llc )) {
215
llc = (struct llc *)m0->b_rptr;
216
if ( llc->llc_dsap != LLC_SNAP_LSAP ||
217
llc->llc_ssap != LLC_SNAP_LSAP ||
218
llc->llc_control != LLC_UI ) {
223
if ( bcmp( llc->llc_org_code, at_org_code,
224
sizeof( at_org_code )) == 0 &&
225
ntohs( llc->llc_ether_type ) == ETHERTYPE_AT ) {
226
adjmsg( m0, sizeof( struct llc ));
228
} else if ( bcmp( llc->llc_org_code, aarp_org_code,
229
sizeof( aarp_org_code )) == 0 &&
230
ntohs( llc->llc_ether_type ) == ETHERTYPE_AARP ) {
231
adjmsg( m0, sizeof( struct llc ));
239
if ( m->b_wptr - m->b_rptr < sizeof( DL_OK_ACK_SIZE )) {
242
switch ( dl->ok_ack.dl_correct_primitive ) {
244
if ( aid->aid_state != DL_ATTACH_PENDING ) {
245
cmn_err( CE_NOTE, "dlpi_rput DL_OK_ACK attach state %d\n",
249
if ( aid->aid_c.c_type != IF_UNITSEL ) {
250
cmn_err( CE_NOTE, "dlpi_rput DL_OK_ACK attach context %x\n",
255
if ( WR(q)->q_next == NULL || WR(q)->q_next->q_qinfo == NULL ||
256
WR(q)->q_next->q_qinfo->qi_minfo == NULL ||
257
WR(q)->q_next->q_qinfo->qi_minfo->mi_idname == NULL ) {
258
cmn_err( CE_NOTE, "dlpi_rput can't get interface name\n" );
262
if_name( aid, WR(q)->q_next->q_qinfo->qi_minfo->mi_idname,
263
aid->aid_c.c_u.u_unit.uu_ppa );
265
aid->aid_state = DL_BIND_PENDING;
269
* As of Solaris 7 (nice name), the i386 arch needs to be
270
* bound as 0 to receive 802 frames. However, in the same
271
* OS, Sparcs must be bound as ETHERMTU (or at least not 0)
272
* to receive the same frames. A bug? In the Solaris 7
273
* (nice name) kernel?
275
dl_bind_req( WR( q ), 0 );
277
dl_bind_req( WR( q ), ETHERMTU );
281
case DL_ENABMULTI_REQ :
282
if ( aid->aid_c.c_type != SIOCADDMULTI ) {
284
"dlpi_rput DL_OK_ACK enabmulti context %x\n",
289
ioc_ok_ack( aid->aid_c.c_u.u_multi.um_q,
290
aid->aid_c.c_u.u_multi.um_m, 0 );
291
aid->aid_c.c_type = 0;
292
aid->aid_c.c_u.u_multi.um_q = NULL;
293
aid->aid_c.c_u.u_multi.um_m = 0;
297
cmn_err( CE_CONT, "!dlpi_rput DL_OK_ACK unhandled %d\n",
298
dl->ok_ack.dl_correct_primitive );
304
if ( m->b_wptr - m->b_rptr < sizeof( DL_BIND_ACK_SIZE )) {
307
if ( aid->aid_state != DL_BIND_PENDING ) {
310
if ( aid->aid_c.c_type != IF_UNITSEL ) {
313
bcopy( m->b_rptr + dl->bind_ack.dl_addr_offset, aid->aid_hwaddr,
314
dl->bind_ack.dl_addr_length );
315
aid->aid_state = DL_IDLE;
316
ioc_ok_ack( WR(q), aid->aid_c.c_u.u_unit.uu_m, 0 );
317
aid->aid_c.c_type = 0;
318
aid->aid_c.c_u.u_unit.uu_m = NULL;
319
aid->aid_c.c_u.u_unit.uu_ppa = 0;
323
if ( m->b_wptr - m->b_rptr < sizeof( DL_ERROR_ACK_SIZE )) {
327
switch ( aid->aid_c.c_type ) {
329
if ( dl->error_ack.dl_errno == DL_SYSERR ) {
330
ioc_error_ack( WR(q), aid->aid_c.c_u.u_unit.uu_m,
331
dl->error_ack.dl_unix_errno );
333
cmn_err( CE_CONT, "dlpi_rput DL_ERROR_ACK 0x%x\n",
334
dl->error_ack.dl_errno );
335
ioc_error_ack( WR(q), aid->aid_c.c_u.u_unit.uu_m, EINVAL );
337
aid->aid_c.c_type = 0;
338
aid->aid_c.c_u.u_unit.uu_m = NULL;
339
aid->aid_c.c_u.u_unit.uu_ppa = 0;
343
cmn_err( CE_NOTE, "dlpi_rput DL_ERROR_ACK unhandled %d %d %d\n",
344
dl->error_ack.dl_error_primitive,
345
dl->error_ack.dl_errno, dl->error_ack.dl_unix_errno );
351
cmn_err( CE_NOTE, "dlpi_rput M_PCPROTO 0x%x\n", dl->dl_primitive );
357
cmn_err( CE_NOTE, "dlpi_rput 0x%X\n", m->b_datap->db_type );
366
dlpi_wput( queue_t *q, mblk_t *m )
368
struct atif_data *aid = (struct atif_data *)RD(q)->q_ptr;
372
switch ( m->b_datap->db_type ) {
374
if ( m->b_wptr - m->b_rptr < sizeof( struct iocblk )) {
378
ioc = (struct iocblk *)m->b_rptr;
379
switch ( ioc->ioc_cmd ) {
381
if ( ioc->ioc_count != TRANSPARENT ) {
382
cmn_err( CE_NOTE, "dlpi_wput IF_UNITSEL non-TRANSPARENT\n" );
383
ioc_error_ack( q, m, EINVAL );
386
if ( m->b_cont == NULL ) {
387
cmn_err( CE_NOTE, "dlpi_wput IF_UNITSEL no arg\n" );
388
ioc_error_ack( q, m, EINVAL );
391
if ( aid->aid_state != DL_UNATTACHED ) {
392
cmn_err( CE_NOTE, "dlpi_wput IF_UNITSEL already attached\n" );
393
ioc_error_ack( q, m, EINVAL );
396
if ( aid->aid_c.c_type != 0 ) {
397
cmn_err( CE_NOTE, "dlpi_wput IF_UNITSEL context %x\n",
399
ioc_error_ack( q, m, EINVAL );
403
aid->aid_state = DL_ATTACH_PENDING;
404
aid->aid_c.c_type = IF_UNITSEL;
405
aid->aid_c.c_u.u_unit.uu_m = m;
406
aid->aid_c.c_u.u_unit.uu_ppa = *(ulong *)m->b_cont->b_rptr;
407
if (( rc = dl_attach_req( q, aid->aid_c.c_u.u_unit.uu_ppa )) < 0 ) {
408
ioc_error_ack( q, m, rc );
414
cmn_err( CE_NOTE, "dlpi_wput M_IOCTL 0x%X\n", ioc->ioc_cmd );
421
cmn_err( CE_NOTE, "dlpi_wput 0x%X\n", m->b_datap->db_type );
429
static struct module_info dlpi_info = {
438
static struct qinit dlpi_rinit = {
439
dlpi_rput, /* qi_putp */
441
dlpi_open, /* qi_qopen */
442
dlpi_close, /* qi_qclose */
444
&dlpi_info, /* qi_minfo */
448
static struct qinit dlpi_winit = {
449
dlpi_wput, /* qi_putp */
452
NULL, /* qi_qclose */
454
&dlpi_info, /* qi_minfo */
458
static struct streamtab dlpi_stream = {
465
static struct fmodsw dlpi_fmodsw = {
468
D_NEW | D_MP | D_MTPERMOD
472
* DDP Streams module. This module is pushed on DLPI drivers by atalkd.
474
struct modlstrmod dlpi_lstrmod = {
476
"DDP Streams module",