1 |
|
/* |
2 |
|
* ether.cpp - SheepShaver Ethernet Device Driver (DLPI) |
3 |
|
* |
4 |
< |
* SheepShaver (C) 1997-2004 Marc Hellwig and Christian Bauer |
4 |
> |
* SheepShaver (C) 1997-2008 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 |
27 |
|
#include <string.h> |
28 |
|
|
29 |
|
#include "sysdeps.h" |
30 |
+ |
#include "cpu_emulation.h" |
31 |
|
#include "ether.h" |
32 |
|
#include "ether_defs.h" |
33 |
|
#include "macos_util.h" |
33 |
– |
#include "cpu_emulation.h" |
34 |
– |
#include "emul_op.h" |
35 |
– |
#include "main.h" |
34 |
|
|
35 |
|
#define DEBUG 0 |
36 |
|
#include "debug.h" |
37 |
|
|
40 |
– |
|
38 |
|
// Packet types |
39 |
|
enum { |
40 |
|
kPktDIX = 0, |
83 |
|
|
84 |
|
void AddMulticast(uint8 *addr) |
85 |
|
{ |
86 |
< |
multicast_node *n = (multicast_node *)Mac_sysalloc(sizeof(multicast_node)); |
86 |
> |
multicast_node *n = (multicast_node *)Mac2HostAddr(Mac_sysalloc(sizeof(multicast_node))); |
87 |
|
memcpy(n->addr, addr, kEnetPhysicalAddressLength); |
88 |
|
n->next = multicast_list; |
89 |
|
multicast_list = n; |
103 |
|
while (q) { |
104 |
|
if (q->next == p) { |
105 |
|
q->next = p->next; |
106 |
< |
Mac_sysfree(p); |
106 |
> |
Mac_sysfree(Host2MacAddr((uint8 *)p)); |
107 |
|
return; |
108 |
|
} |
109 |
|
q = q->next; |
177 |
|
static uint32 allocb_tvect = 0; |
178 |
|
mblk_t *allocb(size_t arg1, int arg2) |
179 |
|
{ |
180 |
< |
return (mblk_t *)Mac2HostAddr(CallMacOS2(allocb_ptr, allocb_tvect, arg1, arg2)); |
180 |
> |
return (mblk_t *)Mac2HostAddr((uint32)CallMacOS2(allocb_ptr, allocb_tvect, arg1, arg2)); |
181 |
|
} |
182 |
|
typedef void (*freeb_ptr)(mblk_t *); |
183 |
|
static uint32 freeb_tvect = 0; |
195 |
|
static uint32 copyb_tvect = 0; |
196 |
|
static inline mblk_t *copyb(mblk_t *arg1) |
197 |
|
{ |
198 |
< |
return (mblk_t *)Mac2HostAddr(CallMacOS1(copyb_ptr, copyb_tvect, arg1)); |
198 |
> |
return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(copyb_ptr, copyb_tvect, arg1)); |
199 |
|
} |
200 |
|
typedef mblk_t *(*dupmsg_ptr)(mblk_t *); |
201 |
|
static uint32 dupmsg_tvect = 0; |
202 |
|
static inline mblk_t *dupmsg(mblk_t *arg1) |
203 |
|
{ |
204 |
< |
return (mblk_t *)Mac2HostAddr(CallMacOS1(dupmsg_ptr, dupmsg_tvect, arg1)); |
204 |
> |
return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(dupmsg_ptr, dupmsg_tvect, arg1)); |
205 |
|
} |
206 |
|
typedef mblk_t *(*getq_ptr)(queue_t *); |
207 |
|
static uint32 getq_tvect = 0; |
208 |
|
static inline mblk_t *getq(queue_t *arg1) |
209 |
|
{ |
210 |
< |
return (mblk_t *)Mac2HostAddr(CallMacOS1(getq_ptr, getq_tvect, arg1)); |
210 |
> |
return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(getq_ptr, getq_tvect, arg1)); |
211 |
|
} |
212 |
|
typedef int (*putq_ptr)(queue_t *, mblk_t *); |
213 |
|
static uint32 putq_tvect = 0; |
279 |
|
static uint32 mi_next_ptr_tvect = 0; |
280 |
|
static inline DLPIStream *mi_next_ptr(DLPIStream *arg1) |
281 |
|
{ |
282 |
< |
return (DLPIStream *)Mac2HostAddr(CallMacOS1(mi_next_ptr_ptr, mi_next_ptr_tvect, arg1)); |
282 |
> |
return (DLPIStream *)Mac2HostAddr((uint32)CallMacOS1(mi_next_ptr_ptr, mi_next_ptr_tvect, arg1)); |
283 |
|
} |
284 |
< |
|
284 |
> |
#ifdef USE_ETHER_FULL_DRIVER |
285 |
> |
typedef void (*ether_dispatch_packet_ptr)(uint32 p, uint32 size); |
286 |
> |
static uint32 ether_dispatch_packet_tvect = 0; |
287 |
> |
#endif |
288 |
|
|
289 |
|
// Prototypes |
290 |
|
static void ether_ioctl(DLPIStream *the_stream, queue_t* q, mblk_t* mp); |
308 |
|
* Initialize ethernet stream module |
309 |
|
*/ |
310 |
|
|
311 |
< |
uint8 InitStreamModule(void *theID) |
311 |
> |
static uint8 InitStreamModuleImpl(void *theID) |
312 |
|
{ |
313 |
|
D(bug("InitStreamModule\n")); |
314 |
|
|
318 |
|
ether_driver_opened = false; |
319 |
|
|
320 |
|
// Import functions from OTKernelLib |
321 |
< |
allocb_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\006allocb"); |
321 |
> |
allocb_tvect = FindLibSymbol("\013OTKernelLib", "\006allocb"); |
322 |
|
D(bug("allocb TVECT at %08lx\n", allocb_tvect)); |
323 |
|
if (allocb_tvect == 0) |
324 |
|
return false; |
325 |
< |
freeb_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\005freeb"); |
325 |
> |
freeb_tvect = FindLibSymbol("\013OTKernelLib", "\005freeb"); |
326 |
|
D(bug("freeb TVECT at %08lx\n", freeb_tvect)); |
327 |
|
if (freeb_tvect == 0) |
328 |
|
return false; |
329 |
< |
freemsg_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\007freemsg"); |
329 |
> |
freemsg_tvect = FindLibSymbol("\013OTKernelLib", "\007freemsg"); |
330 |
|
D(bug("freemsg TVECT at %08lx\n", freemsg_tvect)); |
331 |
|
if (freemsg_tvect == 0) |
332 |
|
return false; |
333 |
< |
copyb_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\005copyb"); |
333 |
> |
copyb_tvect = FindLibSymbol("\013OTKernelLib", "\005copyb"); |
334 |
|
D(bug("copyb TVECT at %08lx\n", copyb_tvect)); |
335 |
|
if (copyb_tvect == 0) |
336 |
|
return false; |
337 |
< |
dupmsg_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\006dupmsg"); |
337 |
> |
dupmsg_tvect = FindLibSymbol("\013OTKernelLib", "\006dupmsg"); |
338 |
|
D(bug("dupmsg TVECT at %08lx\n", dupmsg_tvect)); |
339 |
|
if (dupmsg_tvect == 0) |
340 |
|
return false; |
341 |
< |
getq_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\004getq"); |
341 |
> |
getq_tvect = FindLibSymbol("\013OTKernelLib", "\004getq"); |
342 |
|
D(bug("getq TVECT at %08lx\n", getq_tvect)); |
343 |
|
if (getq_tvect == 0) |
344 |
|
return false; |
345 |
< |
putq_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\004putq"); |
345 |
> |
putq_tvect = FindLibSymbol("\013OTKernelLib", "\004putq"); |
346 |
|
D(bug("putq TVECT at %08lx\n", putq_tvect)); |
347 |
|
if (putq_tvect == 0) |
348 |
|
return false; |
349 |
< |
putnext_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\007putnext"); |
349 |
> |
putnext_tvect = FindLibSymbol("\013OTKernelLib", "\007putnext"); |
350 |
|
D(bug("putnext TVECT at %08lx\n", putnext_tvect)); |
351 |
|
if (putnext_tvect == 0) |
352 |
|
return false; |
353 |
< |
putnextctl1_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\013putnextctl1"); |
353 |
> |
putnextctl1_tvect = FindLibSymbol("\013OTKernelLib", "\013putnextctl1"); |
354 |
|
D(bug("putnextctl1 TVECT at %08lx\n", putnextctl1_tvect)); |
355 |
|
if (putnextctl1_tvect == 0) |
356 |
|
return false; |
357 |
< |
canputnext_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\012canputnext"); |
357 |
> |
canputnext_tvect = FindLibSymbol("\013OTKernelLib", "\012canputnext"); |
358 |
|
D(bug("canputnext TVECT at %08lx\n", canputnext_tvect)); |
359 |
|
if (canputnext_tvect == 0) |
360 |
|
return false; |
361 |
< |
qreply_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\006qreply"); |
361 |
> |
qreply_tvect = FindLibSymbol("\013OTKernelLib", "\006qreply"); |
362 |
|
D(bug("qreply TVECT at %08lx\n", qreply_tvect)); |
363 |
|
if (qreply_tvect == 0) |
364 |
|
return false; |
365 |
< |
flushq_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\006flushq"); |
365 |
> |
flushq_tvect = FindLibSymbol("\013OTKernelLib", "\006flushq"); |
366 |
|
D(bug("flushq TVECT at %08lx\n", flushq_tvect)); |
367 |
|
if (flushq_tvect == 0) |
368 |
|
return false; |
369 |
< |
msgdsize_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\010msgdsize"); |
369 |
> |
msgdsize_tvect = FindLibSymbol("\013OTKernelLib", "\010msgdsize"); |
370 |
|
D(bug("msgdsize TVECT at %08lx\n", msgdsize_tvect)); |
371 |
|
if (msgdsize_tvect == 0) |
372 |
|
return false; |
373 |
< |
otenterint_tvect = (uint32)FindLibSymbol("\017OTKernelUtilLib", "\020OTEnterInterrupt"); |
373 |
> |
otenterint_tvect = FindLibSymbol("\017OTKernelUtilLib", "\020OTEnterInterrupt"); |
374 |
|
D(bug("OTEnterInterrupt TVECT at %08lx\n", otenterint_tvect)); |
375 |
|
if (otenterint_tvect == 0) |
376 |
|
return false; |
377 |
< |
otleaveint_tvect = (uint32)FindLibSymbol("\017OTKernelUtilLib", "\020OTLeaveInterrupt"); |
377 |
> |
otleaveint_tvect = FindLibSymbol("\017OTKernelUtilLib", "\020OTLeaveInterrupt"); |
378 |
|
D(bug("OTLeaveInterrupt TVECT at %08lx\n", otleaveint_tvect)); |
379 |
|
if (otleaveint_tvect == 0) |
380 |
|
return false; |
381 |
< |
mi_open_comm_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\014mi_open_comm"); |
381 |
> |
mi_open_comm_tvect = FindLibSymbol("\013OTKernelLib", "\014mi_open_comm"); |
382 |
|
D(bug("mi_open_comm TVECT at %08lx\n", mi_open_comm_tvect)); |
383 |
|
if (mi_open_comm_tvect == 0) |
384 |
|
return false; |
385 |
< |
mi_close_comm_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\015mi_close_comm"); |
385 |
> |
mi_close_comm_tvect = FindLibSymbol("\013OTKernelLib", "\015mi_close_comm"); |
386 |
|
D(bug("mi_close_comm TVECT at %08lx\n", mi_close_comm_tvect)); |
387 |
|
if (mi_close_comm_tvect == 0) |
388 |
|
return false; |
389 |
< |
mi_next_ptr_tvect = (uint32)FindLibSymbol("\013OTKernelLib", "\013mi_next_ptr"); |
389 |
> |
mi_next_ptr_tvect = FindLibSymbol("\013OTKernelLib", "\013mi_next_ptr"); |
390 |
|
D(bug("mi_next_ptr TVECT at %08lx\n", mi_next_ptr_tvect)); |
391 |
|
if (mi_next_ptr_tvect == 0) |
392 |
|
return false; |
393 |
|
|
394 |
+ |
#ifndef USE_ETHER_FULL_DRIVER |
395 |
|
// Initialize stream list (which might be leftover) |
396 |
|
dlpi_stream_list = NULL; |
397 |
|
|
398 |
|
// Ask add-on for ethernet hardware address |
399 |
< |
AO_get_ethernet_address(hardware_address); |
399 |
> |
AO_get_ethernet_address(Host2MacAddr(hardware_address)); |
400 |
> |
#endif |
401 |
|
|
402 |
|
// Yes, we're open |
403 |
|
ether_driver_opened = true; |
404 |
|
return true; |
405 |
|
} |
406 |
|
|
407 |
+ |
uint8 InitStreamModule(void *theID) |
408 |
+ |
{ |
409 |
+ |
// Common initialization code |
410 |
+ |
bool net_open = InitStreamModuleImpl(theID); |
411 |
+ |
|
412 |
+ |
// Call InitStreamModule() in native side |
413 |
+ |
#ifdef BUILD_ETHER_FULL_DRIVER |
414 |
+ |
extern bool NativeInitStreamModule(void *); |
415 |
+ |
if (!NativeInitStreamModule((void *)ether_dispatch_packet)) |
416 |
+ |
net_open = false; |
417 |
+ |
#endif |
418 |
+ |
|
419 |
+ |
// Import functions from the Ethernet driver |
420 |
+ |
#ifdef USE_ETHER_FULL_DRIVER |
421 |
+ |
ether_dispatch_packet_tvect = (uintptr)theID; |
422 |
+ |
D(bug("ether_dispatch_packet TVECT at %08lx\n", ether_dispatch_packet_tvect)); |
423 |
+ |
if (ether_dispatch_packet_tvect == 0) |
424 |
+ |
net_open = false; |
425 |
+ |
#endif |
426 |
+ |
|
427 |
+ |
return net_open; |
428 |
+ |
} |
429 |
+ |
|
430 |
|
|
431 |
|
/* |
432 |
|
* Terminate ethernet stream module |
433 |
|
*/ |
434 |
|
|
435 |
< |
void TerminateStreamModule(void) |
435 |
> |
static void TerminateStreamModuleImpl(void) |
436 |
|
{ |
437 |
|
D(bug("TerminateStreamModule\n")); |
438 |
|
|
439 |
+ |
#ifndef USE_ETHER_FULL_DRIVER |
440 |
|
// This happens sometimes. I don't know why. |
441 |
|
if (dlpi_stream_list != NULL) |
442 |
|
printf("FATAL: TerminateStreamModule() called, but streams still open\n"); |
443 |
+ |
#endif |
444 |
|
|
445 |
|
// Sorry, we're closed |
446 |
|
ether_driver_opened = false; |
447 |
|
} |
448 |
|
|
449 |
+ |
void TerminateStreamModule(void) |
450 |
+ |
{ |
451 |
+ |
// Common termination code |
452 |
+ |
TerminateStreamModuleImpl(); |
453 |
+ |
|
454 |
+ |
// Call TerminateStreamModule() in native side |
455 |
+ |
#ifdef BUILD_ETHER_FULL_DRIVER |
456 |
+ |
extern void NativeTerminateStreamModule(void); |
457 |
+ |
NativeTerminateStreamModule(); |
458 |
+ |
#endif |
459 |
+ |
} |
460 |
+ |
|
461 |
|
|
462 |
|
/* |
463 |
|
* Open new stream |
515 |
|
|
516 |
|
// Disable all registered multicast addresses |
517 |
|
while (the_stream->multicast_list) { |
518 |
< |
AO_disable_multicast(the_stream->multicast_list->addr); |
518 |
> |
AO_disable_multicast(Host2MacAddr(the_stream->multicast_list->addr)); |
519 |
|
the_stream->RemoveMulticast(the_stream->multicast_list->addr); |
520 |
|
} |
521 |
|
the_stream->multicast_list = NULL; |
965 |
|
OTCopy48BitAddress(hardware_address, enetHeader->fSourceAddr); |
966 |
|
|
967 |
|
// Tell add-on to transmit packet |
968 |
< |
AO_transmit_packet(mp); |
968 |
> |
AO_transmit_packet(Host2MacAddr((uint8 *)mp)); |
969 |
|
freemsg(mp); |
970 |
|
} |
971 |
|
|
1137 |
|
} |
1138 |
|
} |
1139 |
|
|
1140 |
+ |
void ether_dispatch_packet(uint32 p, uint32 size) |
1141 |
+ |
{ |
1142 |
+ |
#ifdef USE_ETHER_FULL_DRIVER |
1143 |
+ |
// Call handler from the Ethernet driver |
1144 |
+ |
D(bug("ether_dispatch_packet\n")); |
1145 |
+ |
D(bug(" packet data at %p, %d bytes\n", p, size)); |
1146 |
+ |
CallMacOS2(ether_dispatch_packet_ptr, ether_dispatch_packet_tvect, p, size); |
1147 |
+ |
#else |
1148 |
+ |
// Wrap packet in message block |
1149 |
+ |
num_rx_packets++; |
1150 |
+ |
mblk_t *mp; |
1151 |
+ |
if ((mp = allocb(size, 0)) != NULL) { |
1152 |
+ |
D(bug(" packet data at %p\n", (void *)mp->b_rptr)); |
1153 |
+ |
Mac2Host_memcpy(mp->b_rptr, p, size); |
1154 |
+ |
mp->b_wptr += size; |
1155 |
+ |
ether_packet_received(mp); |
1156 |
+ |
} else { |
1157 |
+ |
D(bug("WARNING: Cannot allocate mblk for received packet\n")); |
1158 |
+ |
num_rx_no_mem++; |
1159 |
+ |
} |
1160 |
+ |
#endif |
1161 |
+ |
} |
1162 |
+ |
|
1163 |
|
|
1164 |
|
/* |
1165 |
|
* Build and send an error acknowledge |
1601 |
|
} |
1602 |
|
|
1603 |
|
// Tell add-on to enable multicast address |
1604 |
< |
AO_enable_multicast(reqaddr); |
1604 |
> |
AO_enable_multicast(Host2MacAddr((uint8 *)reqaddr)); |
1605 |
|
|
1606 |
|
// Add new address to multicast list |
1607 |
< |
uint8 *addr = (uint8 *)Mac_sysalloc(kEnetPhysicalAddressLength); |
1607 |
> |
uint8 *addr = Mac2HostAddr(Mac_sysalloc(kEnetPhysicalAddressLength)); |
1608 |
|
OTCopy48BitAddress(reqaddr, addr); |
1609 |
|
the_stream->AddMulticast(addr); |
1610 |
|
|
1642 |
|
|
1643 |
|
// Found, then remove |
1644 |
|
the_stream->RemoveMulticast(addr); |
1645 |
< |
Mac_sysfree(addr); |
1645 |
> |
Mac_sysfree(Host2MacAddr(addr)); |
1646 |
|
|
1647 |
|
// Tell add-on to disable multicast address |
1648 |
< |
AO_disable_multicast(reqaddr); |
1648 |
> |
AO_disable_multicast(Host2MacAddr((uint8 *)reqaddr)); |
1649 |
|
|
1650 |
|
// No longer check multicast packets if no multicast addresses are registered |
1651 |
|
if (the_stream->multicast_list == NULL) |
1698 |
|
if ((mp = build_tx_packet_header(the_stream, mp, false)) != NULL) |
1699 |
|
transmit_packet(mp); |
1700 |
|
} |
1701 |
+ |
|
1702 |
+ |
|
1703 |
+ |
/* |
1704 |
+ |
* Ethernet packet allocator |
1705 |
+ |
*/ |
1706 |
+ |
|
1707 |
+ |
#if SIZEOF_VOID_P != 4 || REAL_ADDRESSING == 0 |
1708 |
+ |
static uint32 ether_packet = 0; // Ethernet packet (cached allocation) |
1709 |
+ |
static uint32 n_ether_packets = 0; // Number of ethernet packets allocated so far (should be at most 1) |
1710 |
+ |
|
1711 |
+ |
EthernetPacket::EthernetPacket() |
1712 |
+ |
{ |
1713 |
+ |
++n_ether_packets; |
1714 |
+ |
if (ether_packet && n_ether_packets == 1) |
1715 |
+ |
packet = ether_packet; |
1716 |
+ |
else { |
1717 |
+ |
packet = Mac_sysalloc(1516); |
1718 |
+ |
assert(packet != 0); |
1719 |
+ |
Mac_memset(packet, 0, 1516); |
1720 |
+ |
if (ether_packet == 0) |
1721 |
+ |
ether_packet = packet; |
1722 |
+ |
} |
1723 |
+ |
} |
1724 |
+ |
|
1725 |
+ |
EthernetPacket::~EthernetPacket() |
1726 |
+ |
{ |
1727 |
+ |
--n_ether_packets; |
1728 |
+ |
if (packet != ether_packet) |
1729 |
+ |
Mac_sysfree(packet); |
1730 |
+ |
if (n_ether_packets > 0) { |
1731 |
+ |
bug("WARNING: Nested allocation of ethernet packets!\n"); |
1732 |
+ |
} |
1733 |
+ |
} |
1734 |
+ |
#endif |