ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/ether.cpp
Revision: 1.2
Committed: 2004-01-12T15:37:18Z (20 years, 4 months ago) by cebix
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
Happy New Year! :)

File Contents

# Content
1 /*
2 * ether.cpp - SheepShaver Ethernet Device Driver (DLPI)
3 *
4 * SheepShaver (C) 1997-2004 Marc Hellwig and Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * TODO
23 * - 802.2 TEST/XID
24 * - MIB statistics
25 */
26
27 #include <string.h>
28
29 #include "sysdeps.h"
30 #include "ether.h"
31 #include "ether_defs.h"
32 #include "macos_util.h"
33 #include "cpu_emulation.h"
34 #include "emul_op.h"
35 #include "main.h"
36
37 #define DEBUG 0
38 #include "debug.h"
39
40
41 // Packet types
42 enum {
43 kPktDIX = 0,
44 kPkt8022SAP = 1,
45 kPkt8022GroupSAP = 2,
46 kPkt8022SNAP = 3,
47 kPktIPX = 4,
48 kPktUnknown = 5
49 };
50
51
52 /*
53 * Stream private data structure
54 */
55
56 static const int kGroupSAPMapSize = 128/32; // Number of 32-bit values we need for 128 bits
57 static const int kGSshift = 6;
58 static const int kGSmask = 0x1F;
59
60 struct multicast_node {
61 multicast_node *next;
62 uint8 addr[kEnetPhysicalAddressLength];
63 };
64
65 struct DLPIStream {
66 void SetGroupSAP(uint8 sap)
67 {
68 group_sap[sap >> kGSshift] |= (1L << ((sap >> 1) & kGSmask));
69 }
70
71 void ClearGroupSAP(uint8 sap)
72 {
73 group_sap[sap >> kGSshift] &= ~(1L << ((sap >> 1) & kGSmask));
74 }
75
76 void ClearAllGroupSAPs(void)
77 {
78 for (int i=0; i<kGroupSAPMapSize; i++)
79 group_sap[i] = 0;
80 }
81
82 bool TestGroupSAP(uint8 sap)
83 {
84 return group_sap[sap >> kGSshift] & (1L << ((sap >> 1) & kGSmask));
85 }
86
87 void AddMulticast(uint8 *addr)
88 {
89 multicast_node *n = new multicast_node;
90 memcpy(n->addr, addr, kEnetPhysicalAddressLength);
91 n->next = multicast_list;
92 multicast_list = n;
93 }
94
95 void RemoveMulticast(uint8 *addr)
96 {
97 multicast_node *p = multicast_list;
98 while (p) {
99 if (memcmp(addr, p->addr, kEnetPhysicalAddressLength) == 0)
100 goto found;
101 p = p->next;
102 }
103 return;
104 found:
105 multicast_node *q = (multicast_node *)&multicast_list;
106 while (q) {
107 if (q->next == p) {
108 q->next = p->next;
109 delete p;
110 return;
111 }
112 q = q->next;
113 }
114 }
115
116 uint8 *IsMulticastRegistered(uint8 *addr)
117 {
118 multicast_node *n = multicast_list;
119 while (n) {
120 if (memcmp(addr, n->addr, kEnetPhysicalAddressLength) == 0)
121 return n->addr;
122 n = n->next;
123 }
124 return NULL;
125 }
126
127 uint32 minor_num; // Minor device number of this stream
128 uint32 dlpi_state; // DLPI state of this stream
129 uint32 flags; // Flags
130 uint16 dlsap; // SAP bound to this stream
131 bool framing_8022; // Using 802.2 framing? This is only used to report the MAC type for DL_INFO_ACK and can be set with an ioctl() call
132 queue_t *rdq; // Read queue for this stream
133 uint32 group_sap[kGroupSAPMapSize]; // Map of bound group SAPs
134 uint8 snap[k8022SNAPLength]; // SNAP bound to this stream
135 multicast_node *multicast_list; // List of enabled multicast addresses
136 };
137
138 // Stream flags
139 enum {
140 kSnapStream = 0x00000001,
141 kAcceptMulticasts = 0x00000002,
142 kAcceptAll8022Packets = 0x00000004,
143 kFastPathMode = 0x00000008
144 };
145
146 // List of opened streams (used internally by OpenTransport)
147 static DLPIStream *dlpi_stream_list = NULL;
148
149 // Are we open?
150 bool ether_driver_opened = false;
151
152 // Our ethernet hardware address
153 static uint8 hardware_address[6] = {0, 0, 0, 0, 0, 0};
154
155 // Statistics
156 int32 num_wput = 0;
157 int32 num_error_acks = 0;
158 int32 num_tx_packets = 0;
159 int32 num_tx_raw_packets = 0;
160 int32 num_tx_normal_packets = 0;
161 int32 num_tx_buffer_full = 0;
162 int32 num_rx_packets = 0;
163 int32 num_ether_irq = 0;
164 int32 num_unitdata_ind = 0;
165 int32 num_rx_fastpath = 0;
166 int32 num_rx_no_mem = 0;
167 int32 num_rx_dropped = 0;
168 int32 num_rx_stream_not_ready = 0;
169 int32 num_rx_no_unitdata_mem = 0;
170
171
172 // Function pointers of imported functions
173 typedef mblk_t *(*allocb_ptr)(size_t size, int pri);
174 static uint32 allocb_tvect = 0;
175 mblk_t *allocb(size_t arg1, int arg2)
176 {
177 return (mblk_t *)CallMacOS2(allocb_ptr, allocb_tvect, arg1, arg2);
178 }
179 typedef void (*freeb_ptr)(mblk_t *);
180 static uint32 freeb_tvect = 0;
181 static inline void freeb(mblk_t *arg1)
182 {
183 CallMacOS1(freeb_ptr, freeb_tvect, arg1);
184 }
185 typedef int16 (*freemsg_ptr)(mblk_t *);
186 static uint32 freemsg_tvect = 0;
187 static inline int16 freemsg(mblk_t *arg1)
188 {
189 return (int16)CallMacOS1(freemsg_ptr, freemsg_tvect, arg1);
190 }
191 typedef mblk_t *(*copyb_ptr)(mblk_t *);
192 static uint32 copyb_tvect = 0;
193 static inline mblk_t *copyb(mblk_t *arg1)
194 {
195 return (mblk_t *)CallMacOS1(copyb_ptr, copyb_tvect, arg1);
196 }
197 typedef mblk_t *(*dupmsg_ptr)(mblk_t *);
198 static uint32 dupmsg_tvect = 0;
199 static inline mblk_t *dupmsg(mblk_t *arg1)
200 {
201 return (mblk_t *)CallMacOS1(dupmsg_ptr, dupmsg_tvect, arg1);
202 }
203 typedef mblk_t *(*getq_ptr)(queue_t *);
204 static uint32 getq_tvect = 0;
205 static inline mblk_t *getq(queue_t *arg1)
206 {
207 return (mblk_t *)CallMacOS1(getq_ptr, getq_tvect, arg1);
208 }
209 typedef int (*putq_ptr)(queue_t *, mblk_t *);
210 static uint32 putq_tvect = 0;
211 static inline int putq(queue_t *arg1, mblk_t *arg2)
212 {
213 return (int)CallMacOS2(putq_ptr, putq_tvect, arg1, arg2);
214 }
215 typedef int (*putnext_ptr)(queue_t *, mblk_t *);
216 static uint32 putnext_tvect = 0;
217 static inline int putnext(queue_t *arg1, mblk_t *arg2)
218 {
219 return (int)CallMacOS2(putnext_ptr, putnext_tvect, arg1, arg2);
220 }
221 typedef int (*putnextctl1_ptr)(queue_t *, int type, int c);
222 static uint32 putnextctl1_tvect = 0;
223 static inline int putnextctl1(queue_t *arg1, int arg2, int arg3)
224 {
225 return (int)CallMacOS3(putnextctl1_ptr, putnextctl1_tvect, arg1, arg2, arg3);
226 }
227 typedef int (*canputnext_ptr)(queue_t *);
228 static uint32 canputnext_tvect = 0;
229 static inline int canputnext(queue_t *arg1)
230 {
231 return (int)CallMacOS1(canputnext_ptr, canputnext_tvect, arg1);
232 }
233 typedef int (*qreply_ptr)(queue_t *, mblk_t *);
234 static uint32 qreply_tvect = 0;
235 static inline int qreply(queue_t *arg1, mblk_t *arg2)
236 {
237 return (int)CallMacOS2(qreply_ptr, qreply_tvect, arg1, arg2);
238 }
239 typedef void (*flushq_ptr)(queue_t *, int flag);
240 static uint32 flushq_tvect = 0;
241 static inline void flushq(queue_t *arg1, int arg2)
242 {
243 CallMacOS2(flushq_ptr, flushq_tvect, arg1, arg2);
244 }
245 typedef int (*msgdsize_ptr)(const mblk_t *);
246 static uint32 msgdsize_tvect = 0;
247 static inline int msgdsize(const mblk_t *arg1)
248 {
249 return (int)CallMacOS1(msgdsize_ptr, msgdsize_tvect, arg1);
250 }
251 typedef void (*otenterint_ptr)(void);
252 static uint32 otenterint_tvect = 0;
253 void OTEnterInterrupt(void)
254 {
255 CallMacOS(otenterint_ptr, otenterint_tvect);
256 }
257 typedef void (*otleaveint_ptr)(void);
258 static uint32 otleaveint_tvect = 0;
259 void OTLeaveInterrupt(void)
260 {
261 CallMacOS(otleaveint_ptr, otleaveint_tvect);
262 }
263 typedef int (*mi_open_comm_ptr)(DLPIStream **mi_opp_orig, size_t size, queue_t *q, void *dev, int flag, int sflag, void *credp);
264 static uint32 mi_open_comm_tvect = 0;
265 static inline int mi_open_comm(DLPIStream **arg1, size_t arg2, queue_t *arg3, void *arg4, int arg5, int arg6, void *arg7)
266 {
267 return (int)CallMacOS7(mi_open_comm_ptr, mi_open_comm_tvect, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
268 }
269 typedef int (*mi_close_comm_ptr)(DLPIStream **mi_opp_orig, queue_t *q);
270 static uint32 mi_close_comm_tvect = 0;
271 static inline int mi_close_comm(DLPIStream **arg1, queue_t *arg2)
272 {
273 return (int)CallMacOS2(mi_close_comm_ptr, mi_close_comm_tvect, arg1, arg2);
274 }
275 typedef DLPIStream *(*mi_next_ptr_ptr)(DLPIStream *);
276 static uint32 mi_next_ptr_tvect = 0;
277 static inline DLPIStream *mi_next_ptr(DLPIStream *arg1)
278 {
279 return (DLPIStream *)CallMacOS1(mi_next_ptr_ptr, mi_next_ptr_tvect, arg1);
280 }
281
282
283 // Prototypes
284 static void ether_ioctl(DLPIStream *the_stream, queue_t* q, mblk_t* mp);
285 static void ether_flush(queue_t* q, mblk_t* mp);
286 static mblk_t *build_tx_packet_header(DLPIStream *the_stream, mblk_t *mp, bool fast_path);
287 static void transmit_packet(mblk_t *mp);
288 static void DLPI_error_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim, uint32 err, uint32 uerr);
289 static void DLPI_ok_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim);
290 static void DLPI_info(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
291 static void DLPI_phys_addr(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
292 static void DLPI_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
293 static void DLPI_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
294 static void DLPI_subs_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
295 static void DLPI_subs_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
296 static void DLPI_enable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
297 static void DLPI_disable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
298 static void DLPI_unit_data(DLPIStream *the_stream, queue_t *q, mblk_t *mp);
299
300
301 /*
302 * Initialize ethernet stream module
303 */
304
305 uint8 InitStreamModule(void *theID)
306 {
307 D(bug("InitStreamModule\n"));
308
309 // Don't re-open if already open
310 if (ether_driver_opened)
311 return true;
312 ether_driver_opened = false;
313
314 // Import functions from OTKernelLib
315 allocb_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\006allocb");
316 D(bug("allocb TVECT at %08lx\n", allocb_tvect));
317 if (allocb_tvect == 0)
318 return false;
319 freeb_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\005freeb");
320 D(bug("freeb TVECT at %08lx\n", freeb_tvect));
321 if (freeb_tvect == 0)
322 return false;
323 freemsg_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\007freemsg");
324 D(bug("freemsg TVECT at %08lx\n", freemsg_tvect));
325 if (freemsg_tvect == 0)
326 return false;
327 copyb_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\005copyb");
328 D(bug("copyb TVECT at %08lx\n", copyb_tvect));
329 if (copyb_tvect == 0)
330 return false;
331 dupmsg_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\006dupmsg");
332 D(bug("dupmsg TVECT at %08lx\n", dupmsg_tvect));
333 if (dupmsg_tvect == 0)
334 return false;
335 getq_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\004getq");
336 D(bug("getq TVECT at %08lx\n", getq_tvect));
337 if (getq_tvect == 0)
338 return false;
339 putq_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\004putq");
340 D(bug("putq TVECT at %08lx\n", putq_tvect));
341 if (putq_tvect == 0)
342 return false;
343 putnext_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\007putnext");
344 D(bug("putnext TVECT at %08lx\n", putnext_tvect));
345 if (putnext_tvect == 0)
346 return false;
347 putnextctl1_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\013putnextctl1");
348 D(bug("putnextctl1 TVECT at %08lx\n", putnextctl1_tvect));
349 if (putnextctl1_tvect == 0)
350 return false;
351 canputnext_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\012canputnext");
352 D(bug("canputnext TVECT at %08lx\n", canputnext_tvect));
353 if (canputnext_tvect == 0)
354 return false;
355 qreply_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\006qreply");
356 D(bug("qreply TVECT at %08lx\n", qreply_tvect));
357 if (qreply_tvect == 0)
358 return false;
359 flushq_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\006flushq");
360 D(bug("flushq TVECT at %08lx\n", flushq_tvect));
361 if (flushq_tvect == 0)
362 return false;
363 msgdsize_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\010msgdsize");
364 D(bug("msgdsize TVECT at %08lx\n", msgdsize_tvect));
365 if (msgdsize_tvect == 0)
366 return false;
367 otenterint_tvect = (uint32)FindLibSymbol("\017OTKernelUtilLib", "\020OTEnterInterrupt");
368 D(bug("OTEnterInterrupt TVECT at %08lx\n", otenterint_tvect));
369 if (otenterint_tvect == 0)
370 return false;
371 otleaveint_tvect = (uint32)FindLibSymbol("\017OTKernelUtilLib", "\020OTLeaveInterrupt");
372 D(bug("OTLeaveInterrupt TVECT at %08lx\n", otleaveint_tvect));
373 if (otleaveint_tvect == 0)
374 return false;
375 mi_open_comm_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\014mi_open_comm");
376 D(bug("mi_open_comm TVECT at %08lx\n", mi_open_comm_tvect));
377 if (mi_open_comm_tvect == 0)
378 return false;
379 mi_close_comm_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\015mi_close_comm");
380 D(bug("mi_close_comm TVECT at %08lx\n", mi_close_comm_tvect));
381 if (mi_close_comm_tvect == 0)
382 return false;
383 mi_next_ptr_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\013mi_next_ptr");
384 D(bug("mi_next_ptr TVECT at %08lx\n", mi_next_ptr_tvect));
385 if (mi_next_ptr_tvect == 0)
386 return false;
387
388 // Initialize stream list (which might be leftover)
389 dlpi_stream_list = NULL;
390
391 // Ask add-on for ethernet hardware address
392 AO_get_ethernet_address(hardware_address);
393
394 // Yes, we're open
395 ether_driver_opened = true;
396 return true;
397 }
398
399
400 /*
401 * Terminate ethernet stream module
402 */
403
404 void TerminateStreamModule(void)
405 {
406 D(bug("TerminateStreamModule\n"));
407
408 // This happens sometimes. I don't know why.
409 if (dlpi_stream_list != NULL)
410 printf("FATAL: TerminateStreamModule() called, but streams still open\n");
411
412 // Sorry, we're closed
413 ether_driver_opened = false;
414 }
415
416
417 /*
418 * Open new stream
419 */
420
421 int ether_open(queue_t *rdq, void *dev, int flag, int sflag, void *creds)
422 {
423 D(bug("ether_open(%p,%p,%d,%d,%p)\n", rdq, dev, flag, sflag, creds));
424
425 // Return if driver was closed
426 if (!ether_driver_opened) {
427 printf("FATAL: ether_open(): Ethernet driver not opened\n");
428 return MAC_ENXIO;
429 }
430
431 // If we're being reopened, just return
432 if (rdq->q_ptr != NULL)
433 return 0;
434
435 // Allocate DLPIStream structure
436 int err = mi_open_comm(&dlpi_stream_list, sizeof(DLPIStream), rdq, dev, flag, sflag, creds);
437 if (err)
438 return err;
439 DLPIStream *the_stream = (DLPIStream *)rdq->q_ptr;
440 the_stream->rdq = rdq;
441 the_stream->dlpi_state = DL_UNBOUND;
442 the_stream->flags = 0;
443 the_stream->dlsap = 0;
444 the_stream->framing_8022 = false;
445 the_stream->multicast_list = NULL;
446 return 0;
447 }
448
449
450 /*
451 * Close stream
452 */
453
454 int ether_close(queue_t *rdq, int flag, void *creds)
455 {
456 D(bug("ether_close(%p,%d,%p)\n", rdq, flag, creds));
457
458 // Return if driver was closed
459 if (!ether_driver_opened) {
460 printf("FATAL: ether_close(): Ethernet driver not opened\n");
461 return MAC_ENXIO;
462 }
463
464 // Get stream
465 DLPIStream *the_stream = (DLPIStream *)rdq->q_ptr;
466
467 // Don't close if never opened
468 if (the_stream == NULL)
469 return 0;
470
471 // Disable all registered multicast addresses
472 while (the_stream->multicast_list) {
473 AO_disable_multicast(the_stream->multicast_list->addr);
474 the_stream->RemoveMulticast(the_stream->multicast_list->addr);
475 }
476 the_stream->multicast_list = NULL;
477
478 // Delete the DLPIStream
479 return mi_close_comm(&dlpi_stream_list, rdq);
480 }
481
482
483 /*
484 * Put something on the write queue
485 */
486
487 int ether_wput(queue_t *q, mblk_t *mp)
488 {
489 D(bug("ether_wput(%p,%p)\n", q, mp));
490
491 // Return if driver was closed
492 if (!ether_driver_opened) {
493 printf("FATAL: ether_wput(): Ethernet driver not opened\n");
494 return MAC_ENXIO;
495 }
496
497 // Get stream
498 DLPIStream *the_stream = (DLPIStream *)q->q_ptr;
499 if (the_stream == NULL)
500 return MAC_ENXIO;
501
502 D(bug(" db_type %d\n", mp->b_datap->db_type));
503 switch (mp->b_datap->db_type) {
504
505 case M_DATA:
506 // Transmit raw packet
507 D(bug(" raw packet\n"));
508 num_tx_raw_packets++;
509 transmit_packet(mp);
510 break;
511
512 case M_PROTO:
513 case M_PCPROTO: {
514 union DL_primitives *dlp = (union DL_primitives *)mp->b_rptr;
515 uint32 prim = dlp->dl_primitive;
516 D(bug(" dl_primitive %d\n", prim));
517 switch (prim) {
518 case DL_UNITDATA_REQ:
519 // Transmit normal packet
520 num_tx_normal_packets++;
521 DLPI_unit_data(the_stream, q, mp);
522 break;
523
524 case DL_INFO_REQ:
525 DLPI_info(the_stream, q, mp);
526 break;
527
528 case DL_PHYS_ADDR_REQ:
529 DLPI_phys_addr(the_stream, q, mp);
530 break;
531
532 case DL_BIND_REQ:
533 DLPI_bind(the_stream, q, mp);
534 break;
535
536 case DL_UNBIND_REQ:
537 DLPI_unbind(the_stream, q, mp);
538 break;
539
540 case DL_SUBS_BIND_REQ:
541 DLPI_subs_bind(the_stream, q, mp);
542 break;
543
544 case DL_SUBS_UNBIND_REQ:
545 DLPI_subs_unbind(the_stream, q, mp);
546 break;
547
548 case DL_ENABMULTI_REQ:
549 DLPI_enable_multi(the_stream, q, mp);
550 break;
551
552 case DL_DISABMULTI_REQ:
553 DLPI_disable_multi(the_stream, q, mp);
554 break;
555
556 default:
557 D(bug("WARNING: ether_wsrv(): Unknown primitive\n"));
558 DLPI_error_ack(the_stream, q, mp, prim, DL_NOTSUPPORTED, 0);
559 break;
560 }
561 break;
562 }
563
564 case M_IOCTL:
565 ether_ioctl(the_stream, q, mp);
566 break;
567
568 case M_FLUSH:
569 ether_flush(q, mp);
570 break;
571
572 default:
573 D(bug("WARNING: ether_wput(): Unknown message type\n"));
574 freemsg(mp);
575 break;
576 }
577 num_wput++;
578 return 0;
579 }
580
581
582 /*
583 * Dequeue and process messages from the read queue
584 */
585
586 int ether_rsrv(queue_t *q)
587 {
588 mblk_t *mp;
589 while ((mp = getq(q)) != NULL) {
590 if (canputnext(q))
591 putnext(q, mp);
592 else {
593 freemsg(mp);
594 flushq(q, FLUSHDATA);
595 break;
596 }
597 }
598 return 0;
599 }
600
601
602 /*
603 * Handle ioctl calls
604 */
605
606 static void ether_ioctl(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
607 {
608 struct iocblk *ioc = (struct iocblk *)mp->b_rptr;
609 D(bug(" ether_ioctl(%p,%p) cmd %d\n", q, mp, ioc->ioc_cmd));
610
611 switch (ioc->ioc_cmd) {
612
613 case I_OTSetFramingType: { // Toggles what the general info primitive returns for dl_mac_type in dl_info_ack_t structure
614 mblk_t *info_mp = mp->b_cont;
615 if (info_mp == NULL || ((info_mp->b_wptr - info_mp->b_rptr) != sizeof(uint32))) {
616 ioc->ioc_error = MAC_EINVAL;
617 goto ioctl_error;
618 }
619 uint32 framing_type = *(uint32 *)info_mp->b_rptr;
620 D(bug(" I_OTSetFramingType type %d\n", framing_type));
621 if (framing_type != kOTGetFramingValue)
622 the_stream->framing_8022 = (framing_type == kOTFraming8022);
623 mp->b_cont = NULL;
624 freemsg(info_mp);
625 if (the_stream->framing_8022)
626 ioc->ioc_rval = kOTFraming8022;
627 else
628 ioc->ioc_rval = kOTFramingEthernet;
629 goto ioctl_ok;
630 }
631
632 case DL_IOC_HDR_INFO: { // Special Mentat call, for fast transmits
633 D(bug(" DL_IOC_HDR_INFO\n"));
634 mblk_t *info_mp = mp->b_cont;
635
636 // Copy DL_UNITDATA_REQ block
637 mblk_t *unitdata_mp = copyb(info_mp);
638 if (unitdata_mp == NULL) {
639 ioc->ioc_error = MAC_ENOMEM;
640 goto ioctl_error;
641 }
642 unitdata_mp->b_datap->db_type = M_PROTO;
643
644 // Construct header (converts DL_UNITDATA_REQ -> M_DATA)
645 mblk_t *header_mp = build_tx_packet_header(the_stream, unitdata_mp, true);
646
647 if (header_mp == NULL) {
648 // Could not allocate a message block large enough
649 ioc->ioc_error = MAC_ENOMEM;
650 goto ioctl_error;
651 }
652
653 // Attach header block at the end
654 mp->b_cont->b_cont = header_mp;
655 the_stream->flags |= kFastPathMode;
656 goto ioctl_ok;
657 }
658
659 case I_OTSetRawMode: {
660 mblk_t *info_mp = mp->b_cont;
661 dl_recv_control_t *dlrc;
662 if (info_mp == NULL || ((info_mp->b_wptr - info_mp->b_rptr) != sizeof(dlrc->dl_primitive))) {
663 ioc->ioc_error = MAC_EINVAL;
664 goto ioctl_error;
665 }
666 dlrc = (dl_recv_control_t *)info_mp->b_rptr;
667 D(bug(" I_OTSetRawMode primitive %d\n", dlrc->dl_primitive));
668 ioc->ioc_error = MAC_EINVAL;
669 goto ioctl_error;
670 }
671
672 default:
673 D(bug("WARNING: Unknown ether_ioctl() call\n"));
674 ioc->ioc_error = MAC_EINVAL;
675 goto ioctl_error;
676 }
677
678 ioctl_ok:
679 ioc->ioc_count = 0;
680 for (mblk_t *mp1 = mp; (mp1 = mp1->b_cont) != NULL;)
681 ioc->ioc_count += mp1->b_wptr - mp1->b_rptr;
682 ioc->ioc_error = 0;
683 mp->b_datap->db_type = M_IOCACK;
684 qreply(q, mp);
685 return;
686
687 ioctl_error:
688 mp->b_datap->db_type = M_IOCNAK;
689 qreply(q, mp);
690 return;
691 }
692
693
694 /*
695 * Flush call, send it up to the read side of the stream
696 */
697
698 static void ether_flush(queue_t* q, mblk_t* mp)
699 {
700 D(bug(" ether_flush(%p,%p)\n", q, mp));
701
702 uint8 *rptr = mp->b_rptr;
703 if (*rptr & FLUSHW)
704 flushq(q, FLUSHALL);
705 if (*rptr & FLUSHR) {
706 flushq(RD(q), FLUSHALL);
707 *rptr &= ~FLUSHW;
708 qreply(q, mp);
709 } else
710 freemsg(mp);
711 }
712
713
714 /*
715 * Classify packet into the different types of protocols
716 */
717
718 static uint16 classify_packet_type(uint16 primarySAP, uint16 secondarySAP)
719 {
720 if (primarySAP >= kMinDIXSAP)
721 return kPktDIX;
722
723 if ((primarySAP == kIPXSAP) && (secondarySAP == kIPXSAP))
724 return kPktIPX;
725
726 if (primarySAP == kSNAPSAP)
727 return kPkt8022SNAP;
728
729 if (primarySAP <= k8022GlobalSAP)
730 return kPkt8022SAP;
731
732 return kPktUnknown;
733 }
734
735
736 /*
737 * Check if the address is a multicast, broadcast or standard address
738 */
739
740 static int32 get_address_type(uint8 *addr)
741 {
742 if (addr[0] & 1) { // Multicast/broadcast flag
743 if (OTIs48BitBroadcastAddress(addr))
744 return keaBroadcast;
745 else
746 return keaMulticast;
747 } else
748 return keaStandardAddress;
749 }
750
751
752 /*
753 * Reuse a message block, make room for more data
754 */
755
756 static mblk_t *reuse_message_block(mblk_t *mp, uint16 needed_size)
757 {
758 mblk_t *nmp;
759
760 if ((mp->b_datap->db_ref == 1) && ((mp->b_datap->db_lim - mp->b_datap->db_base) >= needed_size)) {
761 mp->b_datap->db_type = M_DATA;
762 mp->b_rptr = mp->b_datap->db_base;
763 mp->b_wptr = mp->b_datap->db_base + needed_size;
764 } else {
765 nmp = mp->b_cont; // Grab the M_DATA blocks
766 mp->b_cont = NULL; // Detach the M_(PC)PROTO
767 freemsg(mp); // Free the M_(PC)PROTO
768 mp = nmp; // Point to the M_DATA blocks
769
770 // Try to get space on the first M_DATA block
771 if (mp && (mp->b_datap->db_ref == 1) && ((mp->b_rptr - mp->b_datap->db_base) >= needed_size))
772 mp->b_rptr -= needed_size;
773 else {
774 // Try to allocate a new message
775 if ((nmp = allocb(needed_size, BPRI_HI)) == NULL) {
776 // Could not get a new message block so lets forget about the message altogether
777 freemsg(mp); // Free the original M_DATA portion of the message
778 mp = NULL; // Indicates the reuse failed
779 } else {
780 nmp->b_cont = mp; // Attach the new message block as the head
781 nmp->b_wptr += needed_size;
782 mp = nmp;
783 }
784 }
785 }
786
787 return mp;
788 }
789
790
791 /*
792 * Built header for packet to be transmitted (convert DL_UNITDATA_REQ -> M_DATA)
793 * The passed-in message has the header info in the first message block and the data
794 * in the following blocks
795 */
796
797 static mblk_t *build_tx_packet_header(DLPIStream *the_stream, mblk_t *mp, bool fast_path)
798 {
799 // Only handle unit_data requests
800 dl_unitdata_req_t *req = (dl_unitdata_req_t *)mp->b_rptr;
801 if (req->dl_primitive != DL_UNITDATA_REQ) {
802 freemsg(mp);
803 return NULL;
804 }
805
806 // Extract destination address and its length
807 uint8 *destAddrOrig = ((uint8 *)req) + req->dl_dest_addr_offset;
808 uint32 destAddrLen = req->dl_dest_addr_length;
809 uint8 ctrl = 0x03;
810
811 // Extract DLSAP
812 uint16 dlsap;
813 switch (destAddrLen) {
814 case kEnetPhysicalAddressLength:
815 dlsap = the_stream->dlsap;
816 break;
817 case kEnetAndSAPAddressLength:
818 dlsap = *(uint16 *)(destAddrOrig + kEnetPhysicalAddressLength);
819 break;
820 case kEnetPhysicalAddressLength + k8022DLSAPLength + k8022SNAPLength: // SNAP SAP
821 dlsap = *(uint16 *)(destAddrOrig + kEnetPhysicalAddressLength);
822 break;
823 default:
824 dlsap = the_stream->dlsap;
825 break;
826 }
827
828 // Extract data size (excluding header info) and packet type
829 uint16 datasize = msgdsize(mp);
830 uint16 packetType = classify_packet_type(the_stream->dlsap, dlsap);
831
832 // Calculate header size and protocol type/size field
833 uint16 hdrsize, proto;
834 switch (packetType) {
835 case kPktDIX:
836 hdrsize = kEnetPacketHeaderLength;
837 proto = dlsap;
838 break;
839 case kPkt8022SAP:
840 hdrsize = kEnetPacketHeaderLength + k8022BasicHeaderLength;
841 if (fast_path)
842 proto = 0;
843 else
844 proto = datasize + k8022BasicHeaderLength;
845 break;
846 case kPkt8022SNAP:
847 hdrsize = kEnetPacketHeaderLength + k8022SNAPHeaderLength;
848 if (fast_path)
849 proto = 0;
850 else
851 proto = datasize + k8022SNAPHeaderLength;
852 break;
853 case kPktIPX:
854 hdrsize = kEnetPacketHeaderLength;
855 if (fast_path)
856 proto = 0;
857 else
858 proto = datasize;
859 break;
860 default:
861 hdrsize = kEnetPacketHeaderLength;
862 proto = dlsap;
863 break;
864 }
865
866 // We need to copy the dest address info in the message before we can reuse it
867 uint8 destAddrCopy[kMaxBoundAddrLength];
868 memcpy(destAddrCopy, destAddrOrig, destAddrLen);
869
870 // Resize header info in message block
871 if ((mp = reuse_message_block(mp, hdrsize)) == NULL)
872 return NULL;
873 struct T8022FullPacketHeader *packetHeader = (struct T8022FullPacketHeader *)mp->b_rptr;
874
875 // Set protocol type/size field
876 packetHeader->fEnetPart.fProto = proto;
877
878 // Set destination ethernet address
879 OTCopy48BitAddress(destAddrCopy, packetHeader->fEnetPart.fDestAddr);
880
881 // Set other header fields
882 switch (packetType) {
883 case kPkt8022SAP:
884 packetHeader->f8022Part.fDSAP = (uint8)dlsap;
885 packetHeader->f8022Part.fSSAP = (uint8)the_stream->dlsap;
886 packetHeader->f8022Part.fCtrl = ctrl;
887 break;
888 case kPkt8022SNAP: {
889 uint8 *snapStart;
890 packetHeader->f8022Part.fDSAP = (uint8)dlsap;
891 packetHeader->f8022Part.fSSAP = (uint8)the_stream->dlsap;
892 packetHeader->f8022Part.fCtrl = ctrl;
893 if (destAddrLen >= kEnetAndSAPAddressLength + k8022SNAPLength)
894 snapStart = destAddrCopy + kEnetAndSAPAddressLength;
895 else
896 snapStart = the_stream->snap;
897 OTCopy8022SNAP(snapStart, packetHeader->f8022Part.fSNAP);
898 break;
899 }
900 }
901
902 // Return updated message
903 return mp;
904 }
905
906
907 /*
908 * Transmit packet
909 */
910
911 static void transmit_packet(mblk_t *mp)
912 {
913 EnetPacketHeader *enetHeader = (EnetPacketHeader *)mp->b_rptr;
914
915 // Fill in length in 802.3 packets
916 if (enetHeader->fProto == 0)
917 enetHeader->fProto = msgdsize(mp) - sizeof(EnetPacketHeader);
918
919 // Fill in ethernet source address
920 OTCopy48BitAddress(hardware_address, enetHeader->fSourceAddr);
921
922 // Tell add-on to transmit packet
923 AO_transmit_packet(mp);
924 freemsg(mp);
925 }
926
927
928 /*
929 * Handle incoming packet (one stream), construct DL_UNITDATA_IND message
930 */
931
932 static void handle_received_packet(DLPIStream *the_stream, mblk_t *mp, uint16 packet_type, int32 dest_addr_type)
933 {
934 // Find address and header length
935 uint32 addr_len;
936 uint32 header_len;
937 switch (packet_type) {
938 case kPkt8022SAP:
939 addr_len = kEnetAndSAPAddressLength;
940 header_len = kEnetPacketHeaderLength + k8022BasicHeaderLength;
941 break;
942 case kPkt8022SNAP:
943 addr_len = kEnetAndSAPAddressLength + k8022SNAPLength;
944 header_len = kEnetPacketHeaderLength + k8022SNAPHeaderLength;
945 break;
946 default: // DIX and IPX
947 addr_len = kEnetAndSAPAddressLength;
948 header_len = kEnetPacketHeaderLength;
949 break;
950 }
951
952 // In Fast Path mode, don't send DL_UNITDATA_IND messages for unicast packets
953 if ((the_stream->flags & kFastPathMode) && dest_addr_type == keaStandardAddress) {
954 mp->b_rptr += header_len;
955 num_rx_fastpath++;
956 putq(the_stream->rdq, mp);
957 return;
958 }
959
960 // Allocate the dl_unitdata_ind_t message
961 mblk_t *nmp;
962 if ((nmp = allocb(sizeof(dl_unitdata_ind_t) + 2*addr_len, BPRI_HI)) == NULL) {
963 freemsg(mp);
964 num_rx_no_unitdata_mem++;
965 return;
966 }
967
968 // Set message type
969 nmp->b_datap->db_type = M_PROTO;
970 dl_unitdata_ind_t *ind = (dl_unitdata_ind_t*)nmp->b_rptr;
971 ind->dl_primitive = DL_UNITDATA_IND;
972 nmp->b_wptr += (sizeof(dl_unitdata_ind_t) + 2*addr_len);
973
974 // Link M_DATA block
975 nmp->b_cont = mp;
976
977 // Set address fields
978 ind->dl_dest_addr_length = addr_len;
979 ind->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
980 ind->dl_src_addr_length = addr_len;
981 ind->dl_src_addr_offset = sizeof(dl_unitdata_ind_t) + addr_len;
982
983 // Set address type
984 ind->dl_group_address = dest_addr_type;
985
986 // Set address fields
987 T8022FullPacketHeader *packetHeader = (T8022FullPacketHeader *)mp->b_rptr;
988 T8022AddressStruct *destAddr = ((T8022AddressStruct*)(nmp->b_rptr + ind->dl_dest_addr_offset));
989 T8022AddressStruct *srcAddr = ((T8022AddressStruct*)(nmp->b_rptr + ind->dl_src_addr_offset));
990
991 OTCopy48BitAddress(packetHeader->fEnetPart.fDestAddr, destAddr->fHWAddr);
992 OTCopy48BitAddress(packetHeader->fEnetPart.fSourceAddr, srcAddr->fHWAddr);
993
994 destAddr->fSAP = packetHeader->f8022Part.fDSAP;
995 srcAddr->fSAP = packetHeader->f8022Part.fSSAP;
996
997 if (packet_type == kPkt8022SNAP) {
998 OTCopy8022SNAP(packetHeader->f8022Part.fSNAP, destAddr->fSNAP);
999 OTCopy8022SNAP(packetHeader->f8022Part.fSNAP, srcAddr->fSNAP);
1000 }
1001
1002 // "Hide" the ethernet and protocol header(s)
1003 mp->b_rptr += header_len;
1004
1005 // Pass message up the stream
1006 num_unitdata_ind++;
1007 putq(the_stream->rdq, nmp);
1008 return;
1009 }
1010
1011
1012 /*
1013 * Packet received, distribute it to the streams that want it
1014 */
1015
1016 void ether_packet_received(mblk_t *mp)
1017 {
1018 // Extract address and types
1019 EnetPacketHeader *pkt = (EnetPacketHeader *)mp->b_rptr;
1020 T8022FullPacketHeader *fullpkt = (T8022FullPacketHeader *)pkt;
1021 uint16 sourceSAP, destSAP;
1022 destSAP = fullpkt->fEnetPart.fProto;
1023 if (destSAP >= kMinDIXSAP) {
1024 // Classic ethernet
1025 sourceSAP = destSAP;
1026 } else {
1027 destSAP = fullpkt->f8022Part.fDSAP;
1028 sourceSAP = fullpkt->f8022Part.fSSAP;
1029 }
1030 uint16 packetType = classify_packet_type(sourceSAP, destSAP);
1031 int32 destAddressType = get_address_type(pkt->fDestAddr);
1032
1033 // Look which streams want it
1034 DLPIStream *the_stream, *found_stream = NULL;
1035 uint16 found_packetType = 0;
1036 int32 found_destAddressType = 0;
1037 for (the_stream = dlpi_stream_list; the_stream != NULL; the_stream = mi_next_ptr(the_stream)) {
1038
1039 // Don't send to unbound streams
1040 if (the_stream->dlpi_state == DL_UNBOUND)
1041 continue;
1042
1043 // Does this stream want all 802.2 packets?
1044 if ((the_stream->flags & kAcceptAll8022Packets) && (destSAP <= 0xff))
1045 goto type_found;
1046
1047 // No, check SAP/SNAP
1048 if (destSAP == the_stream->dlsap) {
1049 if (the_stream->flags & kSnapStream) {
1050 // Check SNAPs if necessary
1051 uint8 sum = fullpkt->f8022Part.fSNAP[0] ^ the_stream->snap[0];
1052 sum |= fullpkt->f8022Part.fSNAP[1] ^ the_stream->snap[1];
1053 sum |= fullpkt->f8022Part.fSNAP[2] ^ the_stream->snap[2];
1054 sum |= fullpkt->f8022Part.fSNAP[3] ^ the_stream->snap[3];
1055 sum |= fullpkt->f8022Part.fSNAP[4] ^ the_stream->snap[4];
1056 if (sum == 0)
1057 goto type_found;
1058 } else {
1059 // No SNAP, found a match since saps match
1060 goto type_found;
1061 }
1062 } else {
1063 // Check for an 802.3 Group/Global (odd)
1064 if (((packetType == kPkt8022SAP) || (packetType == kPkt8022SNAP)) && (destSAP & 1) && the_stream->TestGroupSAP(destSAP))
1065 goto type_found;
1066 }
1067
1068 // No stream for this SAP/SNAP found
1069 continue;
1070
1071 type_found:
1072 // If it's a multicast packet, it must be in the stream's multicast list
1073 if ((destAddressType == keaMulticast) && (the_stream->flags & kAcceptMulticasts) && (!the_stream->IsMulticastRegistered(pkt->fDestAddr)))
1074 continue;
1075
1076 // Send packet to stream
1077 // found_stream keeps a pointer to the previously found stream, so that only the last
1078 // stream gets the original message, the other ones get duplicates
1079 if (found_stream)
1080 handle_received_packet(found_stream, dupmsg(mp), found_packetType, found_destAddressType);
1081 found_stream = the_stream;
1082 found_packetType = packetType;
1083 found_destAddressType = destAddressType;
1084 }
1085
1086 // Send original message to last found stream
1087 if (found_stream)
1088 handle_received_packet(found_stream, mp, found_packetType, found_destAddressType);
1089 else {
1090 freemsg(mp); // Nobody wants it *snief*
1091 num_rx_dropped++;
1092 }
1093 }
1094
1095
1096 /*
1097 * Build and send an error acknowledge
1098 */
1099
1100 static void DLPI_error_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim, uint32 err, uint32 uerr)
1101 {
1102 D(bug(" DLPI_error_ack(%p,%p) prim %d, err %d, uerr %d\n", the_stream, ack_mp, prim, err, uerr));
1103 num_error_acks++;
1104
1105 if (ack_mp != NULL)
1106 freemsg(ack_mp);
1107 if ((ack_mp = allocb(sizeof(dl_error_ack_t), BPRI_HI)) == NULL)
1108 return;
1109
1110 ack_mp->b_datap->db_type = M_PCPROTO;
1111 dl_error_ack_t *errp = (dl_error_ack_t *)ack_mp->b_wptr;
1112 errp->dl_primitive = DL_ERROR_ACK;
1113 errp->dl_error_primitive = prim;
1114 errp->dl_errno = err;
1115 errp->dl_unix_errno = uerr;
1116 ack_mp->b_wptr += sizeof(dl_error_ack_t);
1117 qreply(q, ack_mp);
1118 }
1119
1120
1121 /*
1122 * Build and send an OK acknowledge
1123 */
1124
1125 static void DLPI_ok_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim)
1126 {
1127 if (ack_mp->b_datap->db_ref != 1) {
1128 // Message already in use, create a new one
1129 freemsg(ack_mp);
1130 if ((ack_mp = allocb(sizeof(dl_error_ack_t), BPRI_HI)) == NULL)
1131 return;
1132 } else {
1133 // Message free
1134 if (ack_mp->b_cont != NULL) {
1135 freemsg(ack_mp->b_cont);
1136 ack_mp->b_cont = NULL;
1137 }
1138 }
1139
1140 ack_mp->b_datap->db_type = M_PCPROTO;
1141 dl_ok_ack_t *ackp = (dl_ok_ack_t *)ack_mp->b_rptr;
1142 ackp->dl_primitive = DL_OK_ACK;
1143 ackp->dl_correct_primitive = prim;
1144 ack_mp->b_wptr = ack_mp->b_rptr + sizeof(dl_ok_ack_t);
1145 qreply(q, ack_mp);
1146 }
1147
1148
1149 /*
1150 * Handle DL_INFO_REQ (report general information)
1151 */
1152
1153 static void DLPI_info(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1154 {
1155 D(bug(" DLPI_info(%p)\n", the_stream));
1156 uint32 saplen = 0;
1157 uint32 addrlen = kEnetPhysicalAddressLength;
1158 uint32 bcastlen = kEnetPhysicalAddressLength;
1159 uint32 hdrlen = kEnetPacketHeaderLength;
1160
1161 // Calculate header length
1162 if (the_stream->dlpi_state != DL_UNBOUND) {
1163 saplen = (the_stream->flags & kSnapStream) ? k8022DLSAPLength+k8022SNAPLength : k8022DLSAPLength;
1164 if (the_stream->dlsap == kSNAPSAP)
1165 hdrlen = kEnetPacketHeaderLength + k8022SNAPHeaderLength; // SNAP address
1166 else if ((the_stream->dlsap <= kMax8022SAP) || (the_stream->dlsap == kIPXSAP))
1167 hdrlen = kEnetPacketHeaderLength + k8022BasicHeaderLength; // SAP or IPX
1168 else
1169 hdrlen = kEnetPacketHeaderLength; // Basic Ethernet
1170 }
1171
1172 // Allocate message block for reply
1173 mblk_t *ack_mp;
1174 if ((ack_mp = allocb(sizeof(dl_info_ack_t) + addrlen + saplen + bcastlen, BPRI_LO)) == NULL) {
1175 DLPI_error_ack(the_stream, q, mp, DL_INFO_REQ, DL_SYSERR, MAC_ENOMEM);
1176 return;
1177 }
1178
1179 // Set up message type
1180 ack_mp->b_datap->db_type = M_PCPROTO;
1181 dl_info_ack_t *ackp = (dl_info_ack_t *)ack_mp->b_rptr;
1182 ackp->dl_primitive = DL_INFO_ACK;
1183
1184 // Info/version fields
1185 ackp->dl_service_mode = DL_CLDLS;
1186 ackp->dl_provider_style = DL_STYLE1;
1187 ackp->dl_version = DL_VERSION_2;
1188 ackp->dl_current_state = the_stream->dlpi_state;
1189 ackp->dl_mac_type = the_stream->framing_8022 ? DL_CSMACD : DL_ETHER;
1190 ackp->dl_reserved = 0;
1191 ackp->dl_qos_length = 0;
1192 ackp->dl_qos_offset = (uint32)DL_UNKNOWN;
1193 ackp->dl_qos_range_length = 0;
1194 ackp->dl_qos_range_offset = (uint32)DL_UNKNOWN;
1195 ackp->dl_growth = 0;
1196 ackp->dl_min_sdu = 1;
1197 ackp->dl_max_sdu = kEnetTSDU - hdrlen;
1198
1199 // Address fields
1200 ackp->dl_sap_length = -saplen; // Negative to indicate sap follows physical address
1201 ackp->dl_addr_length = addrlen + saplen;
1202 ackp->dl_addr_offset = sizeof(dl_info_ack_t);
1203 T8022AddressStruct *boundAddr = ((T8022AddressStruct *)(ack_mp->b_rptr + ackp->dl_addr_offset));
1204 OTCopy48BitAddress(hardware_address, boundAddr->fHWAddr);
1205 if (saplen) {
1206 boundAddr->fSAP = the_stream->dlsap;
1207 if (the_stream->flags & kSnapStream)
1208 OTCopy8022SNAP(the_stream->snap, boundAddr->fSNAP);
1209 }
1210 ackp->dl_brdcst_addr_length = bcastlen;
1211 ackp->dl_brdcst_addr_offset = sizeof(dl_info_ack_t) + addrlen + saplen;
1212 OTSet48BitBroadcastAddress(ack_mp->b_rptr + ackp->dl_brdcst_addr_offset);
1213
1214 // Advance write pointer
1215 ack_mp->b_wptr += sizeof(dl_info_ack_t) + addrlen + saplen + bcastlen;
1216
1217 // Free request
1218 freemsg(mp);
1219
1220 // Send reply
1221 qreply(q, ack_mp);
1222 return;
1223 }
1224
1225
1226 /*
1227 * Handle DL_PHYS_ADDR_REQ (report physical address)
1228 */
1229
1230 static void DLPI_phys_addr(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1231 {
1232 D(bug(" DLPI_phys_addr(%p,%p)\n", the_stream, mp));
1233 dl_phys_addr_req_t *req = (dl_phys_addr_req_t *)mp->b_rptr;
1234
1235 // Allocate message block for reply
1236 mblk_t *ack_mp;
1237 if ((ack_mp = allocb(sizeof(dl_phys_addr_ack_t) + kEnetPhysicalAddressLength, BPRI_HI)) == NULL) {
1238 DLPI_error_ack(the_stream, q, mp, DL_PHYS_ADDR_REQ, DL_SYSERR, MAC_ENOMEM);
1239 return;
1240 }
1241
1242 // Set up message type
1243 ack_mp->b_datap->db_type = M_PCPROTO;
1244 dl_phys_addr_ack_t *ackp = (dl_phys_addr_ack_t *)ack_mp->b_wptr;
1245 ackp->dl_primitive = DL_PHYS_ADDR_ACK;
1246
1247 // Fill in address
1248 ackp->dl_addr_length = kEnetPhysicalAddressLength;
1249 ackp->dl_addr_offset = sizeof(dl_phys_addr_ack_t);
1250 ack_mp->b_wptr += sizeof(dl_phys_addr_ack_t) + kEnetPhysicalAddressLength;
1251 if (req->dl_addr_type == DL_CURR_PHYS_ADDR || req->dl_addr_type == DL_FACT_PHYS_ADDR)
1252 OTCopy48BitAddress(hardware_address, ack_mp->b_rptr + ackp->dl_addr_offset);
1253 else {
1254 DLPI_error_ack(the_stream, q, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0);
1255 return;
1256 }
1257
1258 // Free request
1259 freemsg(mp);
1260
1261 // Send reply
1262 qreply(q, ack_mp);
1263 return;
1264 }
1265
1266
1267 /*
1268 * Handle DL_BIND_REQ (bind a stream)
1269 */
1270
1271 static void DLPI_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1272 {
1273 dl_bind_req_t *req = (dl_bind_req_t *)mp->b_rptr;
1274 uint32 sap = req->dl_sap;
1275 D(bug(" DLPI_bind(%p,%p) SAP %04x\n", the_stream, mp, sap));
1276
1277 // Stream must be unbound
1278 if (the_stream->dlpi_state != DL_UNBOUND) {
1279 DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
1280 return;
1281 }
1282
1283 // We only support connectionless data link services
1284 if (req->dl_service_mode != DL_CLDLS || req->dl_max_conind != 0) {
1285 DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0);
1286 return;
1287 }
1288
1289 // Don't bind to 802.2 group saps, can't check 802.2 global sap (0xFF)
1290 // because it looks like IPX
1291 if ((sap <= kMax8022SAP) && (sap & 1)) {
1292 DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_BADADDR, 0);
1293 return;
1294 }
1295
1296 if (classify_packet_type(sap, sap) == kPktUnknown) {
1297 DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_BADADDR, 0);
1298 return;
1299 }
1300
1301 // Allocate message block for reply
1302 mblk_t *ack_mp;
1303 if ((ack_mp = allocb(sizeof(dl_bind_ack_t) + kEnetAndSAPAddressLength, BPRI_HI)) == NULL) {
1304 DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_SYSERR, MAC_ENOMEM);
1305 return;
1306 }
1307
1308 // Set up message type
1309 ack_mp->b_datap->db_type = M_PCPROTO;
1310 dl_bind_ack_t *ackp = (dl_bind_ack_t *)ack_mp->b_rptr;
1311 ackp->dl_primitive = DL_BIND_ACK;
1312
1313 // Fill in other fields
1314 ackp->dl_sap = sap;
1315 ackp->dl_addr_length = kEnetAndSAPAddressLength;
1316 ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
1317 ackp->dl_max_conind = 0;
1318 ackp->dl_xidtest_flg = 0;
1319
1320 T8022AddressStruct *addrInfo = (T8022AddressStruct *)(ack_mp->b_rptr + sizeof(dl_bind_ack_t));
1321 OTCopy48BitAddress(hardware_address, addrInfo->fHWAddr);
1322 addrInfo->fSAP = sap;
1323
1324 // Must move b_wptr past the address info data
1325 ack_mp->b_wptr = ack_mp->b_rptr + sizeof(dl_bind_ack_t) + kEnetAndSAPAddressLength;
1326
1327 // Set group SAP if necessary
1328 the_stream->ClearAllGroupSAPs();
1329 if (sap <= kMax8022SAP)
1330 the_stream->SetGroupSAP(k8022GlobalSAP);
1331
1332 // The stream is now bound and idle
1333 the_stream->dlpi_state = DL_IDLE;
1334 the_stream->dlsap = sap;
1335 the_stream->flags &= ~kSnapStream;
1336
1337 // Free request
1338 freemsg(mp);
1339
1340 // Send reply
1341 qreply(q, ack_mp);
1342 return;
1343 }
1344
1345
1346 /*
1347 * Handle DL_UNBIND_REQ (unbind a stream)
1348 */
1349
1350 static void DLPI_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1351 {
1352 D(bug(" DLPI_unbind(%p,%p)\n", the_stream, mp));
1353
1354 // Stream must be bound and idle
1355 if (the_stream->dlpi_state != DL_IDLE) {
1356 DLPI_error_ack(the_stream, q, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
1357 return;
1358 }
1359
1360 // Stream is now unbound
1361 the_stream->dlpi_state = DL_UNBOUND;
1362 the_stream->dlsap = 0;
1363
1364 // Flush all pending outbound messages
1365 flushq(q, FLUSHDATA);
1366
1367 // Flush all inbound messages pending on the stream
1368 flushq(RD(q), FLUSHDATA);
1369 putnextctl1(RD(q), M_FLUSH, FLUSHRW);
1370
1371 // Send reply
1372 DLPI_ok_ack(the_stream, q, mp, DL_UNBIND_REQ);
1373 return;
1374 }
1375
1376
1377 /*
1378 * Handle DL_SUBS_BIND_REQ (register 802.2 SAP group addresses and SNAPs)
1379 */
1380
1381 static void DLPI_subs_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1382 {
1383 dl_subs_bind_req_t *req = (dl_subs_bind_req_t *)mp->b_rptr;
1384 uint8 *sap = ((uint8 *)req) + req->dl_subs_sap_offset;
1385 int32 length = req->dl_subs_sap_length;
1386 uint16 theSap = *((uint16 *)sap);
1387 int32 error = 0;
1388 D(bug(" DLPI_subs_bind(%p,%p) SAP %02x%02x%02x%02x%02x\n", the_stream, mp, sap[0], sap[1], sap[2], sap[3], sap[4]));
1389
1390 // Stream must be idle
1391 if (the_stream->dlpi_state != DL_IDLE) {
1392 DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, DL_OUTSTATE, 0);
1393 return;
1394 }
1395
1396 // Check if address is valid
1397 switch (req->dl_subs_bind_class) {
1398 case DL_PEER_BIND: // Bind a group address
1399 if (the_stream->dlsap <= kMax8022SAP) {
1400 if ((theSap & 1) && (length == sizeof(theSap)))
1401 the_stream->SetGroupSAP(theSap);
1402 else
1403 if (theSap == 0x0000) // special case to receive all 802.2 packets
1404 the_stream->flags |= kAcceptAll8022Packets;
1405 else
1406 error = DL_BADADDR;
1407 } else
1408 error = DL_UNSUPPORTED;
1409 break;
1410
1411 case DL_HIERARCHICAL_BIND: // Bind an additional SNAP
1412 if (the_stream->dlsap == kSNAPSAP) {
1413 if (the_stream->flags & kSnapStream)
1414 error = DL_TOOMANY; // only one SNAP binding allowed
1415 else {
1416 OTCopy8022SNAP(sap, the_stream->snap);
1417 the_stream->flags |= kSnapStream;
1418 }
1419 } else
1420 error = DL_BADADDR;
1421 break;
1422
1423 default:
1424 error = DL_UNSUPPORTED;
1425 break;
1426 }
1427 if (error) {
1428 DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, error, 0);
1429 return;
1430 }
1431
1432 // Allocate message block for reply
1433 mblk_t *ack_mp;
1434 if ((ack_mp = allocb(sizeof(dl_subs_bind_ack_t) + length, BPRI_HI)) == NULL) {
1435 DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, DL_SYSERR, MAC_ENOMEM);
1436 return;
1437 }
1438
1439 // Set up message type
1440 ack_mp->b_datap->db_type = M_PCPROTO;
1441 dl_subs_bind_ack_t *ackp = (dl_subs_bind_ack_t *)ack_mp->b_wptr;
1442 memset(ackp, 0, sizeof(dl_subs_bind_ack_t) + length);
1443 ackp->dl_primitive = DL_SUBS_BIND_ACK;
1444
1445 // Fill in other fields
1446 ackp->dl_subs_sap_length = length;
1447 ackp->dl_subs_sap_offset = length ? sizeof(dl_subs_bind_ack_t) : 0;
1448 ack_mp->b_wptr += sizeof(dl_subs_bind_ack_t);
1449 if (length)
1450 memcpy(ack_mp->b_wptr, sap, length);
1451 ack_mp->b_wptr += length;
1452
1453 // Free request
1454 freemsg(mp);
1455
1456 // Send reply
1457 qreply(q, ack_mp);
1458 return;
1459 }
1460
1461
1462 /*
1463 * Handle DL_SUBS_UNBIND_REQ (unregister 802.2 SAP group addresses and snaps)
1464 */
1465
1466 static void DLPI_subs_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1467 {
1468 dl_subs_unbind_req_t *req = (dl_subs_unbind_req_t *)mp->b_rptr;
1469 uint8 *sap = ((uint8 *)req) + req->dl_subs_sap_offset;
1470 int32 length = req->dl_subs_sap_length;
1471 int32 error = 0;
1472 D(bug(" DLPI_subs_unbind(%p,%p) SAP %02x%02x%02x%02x%02x\n", the_stream, mp, sap[0], sap[1], sap[2], sap[3], sap[4]));
1473
1474 // Stream must be idle
1475 if (the_stream->dlpi_state != DL_IDLE) {
1476 DLPI_error_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ, DL_OUTSTATE, 0);
1477 return;
1478 }
1479
1480 // Check if we are unbinding from an address we are bound to
1481 if (length == k8022SAPLength) {
1482 if ((*sap & 1) && (*sap != kIPXSAP)) {
1483 if (the_stream->dlsap <= kMax8022SAP)
1484 the_stream->ClearGroupSAP(*sap);
1485 else
1486 error = DL_UNSUPPORTED;
1487 } else
1488 error = DL_BADADDR;
1489 } else if (length == k8022SNAPLength) {
1490 if (the_stream->dlsap == kSNAPSAP) {
1491 if (the_stream->flags & kSnapStream) {
1492 if (memcmp(the_stream->snap, sap, length) != 0)
1493 error = DL_BADADDR;
1494 } else
1495 error = DL_BADADDR;
1496 } else
1497 error = DL_UNSUPPORTED;
1498 }
1499 if (error) {
1500 DLPI_error_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ, error, 0);
1501 return;
1502 }
1503
1504 // Stream is no longer bound to SNAP
1505 the_stream->flags &= ~kSnapStream;
1506
1507 // Send reply
1508 DLPI_ok_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ);
1509 return;
1510 }
1511
1512
1513 /*
1514 * Handles DL_ENABMULTI_REQ (enable multicast address)
1515 */
1516
1517 static void DLPI_enable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1518 {
1519 dl_enabmulti_req_t* req = (dl_enabmulti_req_t*)mp->b_rptr;
1520 uint8 *reqaddr = (uint8 *)(mp->b_rptr + req->dl_addr_offset);
1521 D(bug(" DLPI_enable_multi(%p,%p) addr %02x%02x%02x%02x%02x%02x\n", the_stream, mp, reqaddr[0], reqaddr[1], reqaddr[2], reqaddr[3], reqaddr[4], reqaddr[5]));
1522
1523 // Address must be a multicast address
1524 if (get_address_type(reqaddr) != keaMulticast) {
1525 DLPI_error_ack(the_stream, q, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
1526 return;
1527 }
1528
1529 // Address already in multicast list?
1530 if (the_stream->IsMulticastRegistered(reqaddr)) {
1531 DLPI_error_ack(the_stream, q, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
1532 return;
1533 }
1534
1535 // Tell add-on to enable multicast address
1536 AO_enable_multicast(reqaddr);
1537
1538 // Add new address to multicast list
1539 uint8 *addr = new uint8[kEnetPhysicalAddressLength];
1540 OTCopy48BitAddress(reqaddr, addr);
1541 the_stream->AddMulticast(addr);
1542
1543 // On receive now check multicast packets
1544 the_stream->flags |= kAcceptMulticasts;
1545
1546 // Send reply
1547 DLPI_ok_ack(the_stream, q, mp, DL_ENABMULTI_REQ);
1548 return;
1549 }
1550
1551
1552 /*
1553 * Handles DL_DISABMULTI_REQ (disable multicast address)
1554 */
1555
1556 static void DLPI_disable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1557 {
1558 dl_disabmulti_req_t *req = (dl_disabmulti_req_t*)mp->b_rptr;
1559 uint8 *reqaddr = (uint8 *)(mp->b_rptr + req->dl_addr_offset);
1560 D(bug(" DLPI_disable_multi(%p,%p) addr %02x%02x%02x%02x%02x%02x\n", the_stream, mp, reqaddr[0], reqaddr[1], reqaddr[2], reqaddr[3], reqaddr[4], reqaddr[5]));
1561
1562 // Address must be a multicast address
1563 if (get_address_type(reqaddr) != keaMulticast) {
1564 DLPI_error_ack(the_stream, q, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0);
1565 return;
1566 }
1567
1568 // Find address in multicast list
1569 uint8 *addr = the_stream->IsMulticastRegistered(reqaddr);
1570 if (addr == NULL) {
1571 DLPI_error_ack(the_stream, q, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0);
1572 return;
1573 }
1574
1575 // Found, then remove
1576 the_stream->RemoveMulticast(addr);
1577 delete addr;
1578
1579 // Tell add-on to disable multicast address
1580 AO_disable_multicast(reqaddr);
1581
1582 // No longer check multicast packets if no multicast addresses are registered
1583 if (the_stream->multicast_list == NULL)
1584 the_stream->flags &= ~kAcceptMulticasts;
1585
1586 // Send reply
1587 DLPI_ok_ack(the_stream, q, mp, DL_DISABMULTI_REQ);
1588 return;
1589 }
1590
1591
1592 /*
1593 * Handle DL_UNITDATA_REQ (transmit packet)
1594 */
1595
1596 static void DLPI_unit_data(DLPIStream *the_stream, queue_t *q, mblk_t *mp)
1597 {
1598 D(bug(" DLPI_unit_data(%p,%p)\n", the_stream, mp));
1599 dl_unitdata_req_t *req = (dl_unitdata_req_t *)mp->b_rptr;
1600
1601 // Stream must be idle
1602 if (the_stream->dlpi_state != DL_IDLE) {
1603
1604 // Not idle, send error response
1605 dl_uderror_ind_t *errp;
1606 mblk_t *bp;
1607
1608 int i = sizeof(dl_uderror_ind_t) + req->dl_dest_addr_length;
1609 if ((bp = allocb(i, BPRI_HI)) == NULL) {
1610 freemsg(mp);
1611 return;
1612 }
1613 bp->b_datap->db_type = M_PROTO;
1614 errp = (dl_uderror_ind_t *)bp->b_wptr;
1615 errp->dl_primitive = DL_UDERROR_IND;
1616 errp->dl_errno = DL_OUTSTATE;
1617 errp->dl_unix_errno = 0;
1618 errp->dl_dest_addr_length = req->dl_dest_addr_length;
1619 errp->dl_dest_addr_offset = sizeof(dl_uderror_ind_t);
1620 bp->b_wptr += sizeof(dl_uderror_ind_t);
1621 memcpy((uint8 *)bp->b_wptr, ((uint8 *)req) + req->dl_dest_addr_offset, req->dl_dest_addr_length);
1622 bp->b_wptr += req->dl_dest_addr_length;
1623 qreply(q, bp);
1624
1625 freemsg(mp);
1626 return;
1627 }
1628
1629 // Build packet header and transmit packet
1630 if ((mp = build_tx_packet_header(the_stream, mp, false)) != NULL)
1631 transmit_packet(mp);
1632 }