home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / AmigaOS / ether_amiga.cpp < prev    next >
C/C++ Source or Header  |  1999-11-03  |  18KB  |  673 lines

  1. /*
  2.  *  ether_amiga.cpp - Ethernet device driver, AmigaOS specific stuff
  3.  *
  4.  *  Basilisk II (C) 1997-1999 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. #include <exec/types.h>
  22. #include <exec/memory.h>
  23. #include <exec/errors.h>
  24. #include <dos/dos.h>
  25. #include <dos/dosextens.h>
  26. #include <dos/dostags.h>
  27. #include <devices/sana2.h>
  28. #include <proto/exec.h>
  29. #include <proto/dos.h>
  30.  
  31. #include "sysdeps.h"
  32. #include "cpu_emulation.h"
  33. #include "main.h"
  34. #include "prefs.h"
  35. #include "user_strings.h"
  36. #include "macos_util.h"
  37. #include "ether.h"
  38. #include "ether_defs.h"
  39.  
  40. #define DEBUG 0
  41. #include "debug.h"
  42.  
  43. #define MONITOR 0
  44.  
  45.  
  46. // These messages are sent to the network process
  47. const uint32 MSG_CLEANUP = 'clea';            // Remove all protocols
  48. const uint32 MSG_ADD_MULTI = 'addm';        // Add multicast address
  49. const uint32 MSG_DEL_MULTI = 'delm';        // Add multicast address
  50. const uint32 MSG_ATTACH_PH = 'atph';        // Attach protocol handler
  51. const uint32 MSG_DETACH_PH = 'deph';        // Attach protocol handler
  52. const uint32 MSG_WRITE = 'writ';            // Write packet
  53.  
  54. struct NetMessage : public Message {
  55.     NetMessage(uint32 what_, const struct MsgPort *reply_port)
  56.     {
  57.         what = what_;
  58.         mn_ReplyPort = (struct MsgPort *)reply_port;
  59.         mn_Length = sizeof(*this);
  60.     }
  61.     uint32 what;
  62.     uint32 pointer;
  63.     uint16 type;
  64.     int16 result;
  65. };
  66.  
  67.  
  68. // List of attached protocols
  69. static const int NUM_READ_REQUESTS = 32;    // Number of read requests that are sent to device in advance
  70.  
  71. struct NetProtocol : public Node {
  72.     struct IOSana2Req read_io[NUM_READ_REQUESTS];
  73.     uint8 read_buf[NUM_READ_REQUESTS][1518];    // 14 bytes header, 1500 bytes data, 4 bytes CRC
  74.     uint16 type;
  75.     uint32 handler;
  76. };
  77.  
  78. static struct List prot_list;
  79.  
  80.  
  81. // Global variables
  82. static struct Process *net_proc = NULL;        // Network device handler process
  83. static bool proc_error;                        // Flag: process didn't initialize
  84. static struct MsgPort *proc_port = NULL;    // Message port of process, for communication with main task
  85. static struct MsgPort *reply_port = NULL;    // Reply port for communication with process
  86. static struct MsgPort *read_port = NULL;    // Reply port for read IORequests (set up and owned by network process)
  87.  
  88. static bool write_done = false;                // Flag: write request done
  89.  
  90. extern struct Task *MainTask;                // Pointer to main task (from main_amiga.cpp)
  91.  
  92.  
  93. // Prototypes
  94. static void net_func(void);
  95.  
  96.  
  97. /*
  98.  *  Send message to network process
  99.  */
  100.  
  101. static int16 send_to_proc(uint32 what, uint32 pointer = 0, uint16 type = 0)
  102. {
  103.     D(bug("sending %08lx to net_proc\n", what));
  104.     NetMessage msg(what, reply_port);
  105.     msg.pointer = pointer;
  106.     msg.type = type;
  107.     PutMsg(proc_port, &msg);
  108.     WaitPort(reply_port);
  109.     GetMsg(reply_port);
  110.     D(bug(" sent\n"));
  111.     return msg.result;
  112. }
  113.  
  114.  
  115. /*
  116.  *  Initialization
  117.  */
  118.  
  119. void EtherInit(void)
  120. {
  121.     // Do nothing if no Ethernet device specified
  122.     if (PrefsFindString("ether") == NULL)
  123.         return;
  124.  
  125.     // Initialize protocol list
  126.     NewList(&prot_list);
  127.  
  128.     // Create message port
  129.     reply_port = CreateMsgPort();
  130.     if (reply_port == NULL)
  131.         goto open_error;
  132.     D(bug("signal mask %08lx\n", 1 << reply_port->mp_SigBit));
  133.  
  134.     // Start process
  135.     proc_error = false;
  136.     SetSignal(0, SIGF_SINGLE);
  137.     net_proc = CreateNewProcTags(
  138.         NP_Entry, (ULONG)net_func,
  139.         NP_Name, (ULONG)"Basilisk II Ethernet Task",
  140.         NP_Priority, 1,
  141.         TAG_END    
  142.     );
  143.     if (net_proc == NULL)
  144.         goto open_error;
  145.  
  146.     // Wait for signal from process
  147.     Wait(SIGF_SINGLE);
  148.  
  149.     // Initialization error? Then bail out
  150.     if (proc_error)
  151.         goto open_error;
  152.  
  153.     // Everything OK
  154.     net_open = true;
  155.     return;
  156.  
  157. open_error:
  158.     net_proc = NULL;
  159.     if (reply_port) {
  160.         DeleteMsgPort(reply_port);
  161.         reply_port = NULL;
  162.     }
  163. }
  164.  
  165.  
  166. /*
  167.  *  Deinitialization
  168.  */
  169.  
  170. void EtherExit(void)
  171. {
  172.     // Stop process
  173.     if (net_proc) {
  174.         SetSignal(0, SIGF_SINGLE);
  175.         Signal(&net_proc->pr_Task, SIGBREAKF_CTRL_C);
  176.         Wait(SIGF_SINGLE);
  177.     }
  178.  
  179.     // Delete reply port
  180.     if (reply_port) {
  181.         DeleteMsgPort(reply_port);
  182.         reply_port = NULL;
  183.     }
  184. }
  185.  
  186.  
  187. /*
  188.  *  Reset
  189.  */
  190.  
  191. void EtherReset(void)
  192. {
  193.     // Remove all protocols
  194.     if (net_open)
  195.         send_to_proc(MSG_CLEANUP);
  196. }
  197.  
  198.  
  199. /*
  200.  *  Add multicast address
  201.  */
  202.  
  203. int16 ether_add_multicast(uint32 pb)
  204. {
  205.     return send_to_proc(MSG_ADD_MULTI, pb);
  206. }
  207.  
  208.  
  209. /*
  210.  *  Delete multicast address
  211.  */
  212.  
  213. int16 ether_del_multicast(uint32 pb)
  214. {
  215.     return send_to_proc(MSG_DEL_MULTI, pb);
  216. }
  217.  
  218.  
  219. /*
  220.  *  Attach protocol handler
  221.  */
  222.  
  223. int16 ether_attach_ph(uint16 type, uint32 handler)
  224. {
  225.     return send_to_proc(MSG_ATTACH_PH, handler, type);
  226. }
  227.  
  228.  
  229. /*
  230.  *  Detach protocol handler
  231.  */
  232.  
  233. int16 ether_detach_ph(uint16 type)
  234. {
  235.     return send_to_proc(MSG_DETACH_PH, type);
  236. }
  237.  
  238.  
  239. /*
  240.  *  Transmit raw ethernet packet
  241.  */
  242.  
  243. int16 ether_write(uint32 wds)
  244. {
  245.     send_to_proc(MSG_WRITE, wds);
  246.     return 1;    // Command in progress
  247. }
  248.  
  249.  
  250. /*
  251.  *  Remove protocol from protocol list
  252.  */
  253.  
  254. static void remove_protocol(NetProtocol *p)
  255. {
  256.     // Remove from list
  257.     Forbid();
  258.     Remove(p);
  259.     Permit();
  260.  
  261.     // Cancel read requests
  262.     for (int i=0; i<NUM_READ_REQUESTS; i++) {
  263.         AbortIO((struct IORequest *)(p->read_io + i));
  264.         WaitIO((struct IORequest *)(p->read_io + i));
  265.     }
  266.  
  267.     // Free protocol struct
  268.     FreeMem(p, sizeof(NetProtocol));
  269. }
  270.  
  271.  
  272. /*
  273.  *  Remove all protocols
  274.  */
  275.  
  276. static void remove_all_protocols(void)
  277. {
  278.     NetProtocol *n = (NetProtocol *)prot_list.lh_Head, *next;
  279.     while ((next = (NetProtocol *)n->ln_Succ) != NULL) {
  280.         remove_protocol(n);
  281.         n = next;
  282.     }
  283. }
  284.  
  285.  
  286. /*
  287.  *  Copy received network packet to Mac side
  288.  */
  289.  
  290. static __saveds __regargs LONG copy_to_buff(uint8 *to /*a0*/, uint8 *from /*a1*/, uint32 packet_len /*d0*/)
  291. {
  292.     D(bug("CopyToBuff to %08lx, from %08lx, size %08lx\n", to, from, packet_len));
  293.  
  294.     // It would be more efficient (and take up less memory) if we
  295.     // could invoke the packet handler from here. But we don't know
  296.     // in what context we run, so calling Execute68k() would not be
  297.     // a good idea, and even worse, we might run inside a hardware
  298.     // interrupt, so we can't even trigger a Basilisk interrupt from
  299.     // here and wait for its completion.
  300.     CopyMem(from, to, packet_len);
  301. #if MONITOR
  302.     bug("Receiving Ethernet packet:\n");
  303.     for (int i=0; i<packet_len; i++) {
  304.         bug("%02lx ", from[i]);
  305.     }
  306.     bug("\n");
  307. #endif
  308.     return 1;
  309. }
  310.  
  311.  
  312. /*
  313.  *  Copy data from Mac WDS to outgoing network packet
  314.  */
  315.  
  316. static __saveds __regargs LONG copy_from_buff(uint8 *to /*a0*/, char *wds /*a1*/, uint32 packet_len /*d0*/)
  317. {
  318.     D(bug("CopyFromBuff to %08lx, wds %08lx, size %08lx\n", to, wds, packet_len));
  319. #if MONITOR
  320.     bug("Sending Ethernet packet:\n");
  321. #endif
  322.     for (;;) {
  323.         int len = ReadMacInt16((uint32)wds);
  324.         if (len == 0)
  325.             break;
  326. #if MONITOR
  327.         uint8 *adr = Mac2HostAddr(ReadMacInt32((uint32)wds + 2));
  328.         for (int i=0; i<len; i++) {
  329.             bug("%02lx ", adr[i]);
  330.         }
  331. #endif
  332.         CopyMem(Mac2HostAddr(ReadMacInt32((uint32)wds + 2)), to, len);
  333.         to += len;
  334.         wds += 6;
  335.     }
  336. #if MONITOR
  337.     bug("\n");
  338. #endif
  339.     return 1;
  340. }
  341.  
  342.  
  343. /*
  344.  *  Process for communication with the Ethernet device
  345.  */
  346.  
  347. static __saveds void net_func(void)
  348. {
  349.     struct MsgPort *write_port = NULL, *control_port = NULL;
  350.     struct IOSana2Req *write_io = NULL, *control_io = NULL;
  351.     bool opened = false;
  352.     ULONG read_mask = 0, write_mask = 0, proc_port_mask = 0;
  353.     struct Sana2DeviceQuery query_data = {sizeof(Sana2DeviceQuery)};
  354.     ULONG buffer_tags[] = {
  355.         S2_CopyToBuff, (uint32)copy_to_buff,
  356.         S2_CopyFromBuff, (uint32)copy_from_buff,
  357.         TAG_END
  358.     };
  359.  
  360.     // Default: error occured
  361.     proc_error = true;
  362.  
  363.     // Create message port for communication with main task
  364.     proc_port = CreateMsgPort();
  365.     if (proc_port == NULL)
  366.         goto quit;
  367.     proc_port_mask = 1 << proc_port->mp_SigBit;
  368.  
  369.     // Create message ports for device I/O
  370.     read_port = CreateMsgPort();
  371.     if (read_port == NULL)
  372.         goto quit;
  373.     read_mask = 1 << read_port->mp_SigBit;
  374.     write_port = CreateMsgPort();
  375.     if (write_port == NULL)
  376.         goto quit;
  377.     write_mask = 1 << write_port->mp_SigBit;
  378.     control_port = CreateMsgPort();
  379.     if (control_port == NULL)
  380.         goto quit;
  381.  
  382.     // Create control IORequest
  383.     control_io = (struct IOSana2Req *)CreateIORequest(control_port, sizeof(struct IOSana2Req));
  384.     if (control_io == NULL)
  385.         goto quit;
  386.     control_io->ios2_Req.io_Message.mn_Node.ln_Type = 0;    // Avoid CheckIO() bug
  387.  
  388.     // Parse device name
  389.     char dev_name[256];
  390.     ULONG dev_unit;
  391.     if (sscanf(PrefsFindString("ether"), "%[^/]/%ld", dev_name, &dev_unit) < 2)
  392.         goto quit;
  393.  
  394.     // Open device
  395.     control_io->ios2_BufferManagement = buffer_tags;
  396.     if (OpenDevice((UBYTE *)dev_name, dev_unit, (struct IORequest *)control_io, 0) || control_io->ios2_Req.io_Device == 0)
  397.         goto quit;
  398.     opened = true;
  399.  
  400.     // Is it Ethernet?
  401.     control_io->ios2_Req.io_Command = S2_DEVICEQUERY;
  402.     control_io->ios2_StatData = (void *)&query_data;
  403.     DoIO((struct IORequest *)control_io);
  404.     if (control_io->ios2_Req.io_Error)
  405.         goto quit;
  406.     if (query_data.HardwareType != S2WireType_Ethernet) {
  407.         WarningAlert(GetString(STR_NOT_ETHERNET_WARN));
  408.         goto quit;
  409.     }
  410.  
  411.     // Yes, create IORequest for writing
  412.     write_io = (struct IOSana2Req *)CreateIORequest(write_port, sizeof(struct IOSana2Req));
  413.     if (write_io == NULL)
  414.         goto quit;
  415.     memcpy(write_io, control_io, sizeof(struct IOSana2Req));
  416.     write_io->ios2_Req.io_Message.mn_Node.ln_Type = 0;    // Avoid CheckIO() bug
  417.     write_io->ios2_Req.io_Message.mn_ReplyPort = write_port;
  418.  
  419.     // Configure Ethernet
  420.     control_io->ios2_Req.io_Command = S2_GETSTATIONADDRESS;
  421.     DoIO((struct IORequest *)control_io);
  422.     memcpy(ether_addr, control_io->ios2_DstAddr, 6);
  423.     memcpy(control_io->ios2_SrcAddr, control_io->ios2_DstAddr, 6);
  424.     control_io->ios2_Req.io_Command = S2_CONFIGINTERFACE;
  425.     DoIO((struct IORequest *)control_io);
  426.     D(bug("Ethernet address %08lx %08lx\n", *(uint32 *)ether_addr, *(uint16 *)(ether_addr + 4)));
  427.  
  428.     // Initialization went well, inform main task
  429.     proc_error = false;
  430.     Signal(MainTask, SIGF_SINGLE);
  431.  
  432.     // Main loop
  433.     for (;;) {
  434.  
  435.         // Wait for I/O and messages (CTRL_C is used for quitting the task)
  436.         ULONG sig = Wait(proc_port_mask | read_mask | write_mask | SIGBREAKF_CTRL_C);
  437.  
  438.         // Main task wants to quit us
  439.         if (sig & SIGBREAKF_CTRL_C)
  440.             break;
  441.  
  442.         // Main task sent a command to us
  443.         if (sig & proc_port_mask) {
  444.             struct NetMessage *msg;
  445.             while (msg = (NetMessage *)GetMsg(proc_port)) {
  446.                 D(bug("net_proc received %08lx\n", msg->what));
  447.                 switch (msg->what) {
  448.                     case MSG_CLEANUP:
  449.                         remove_all_protocols();
  450.                         break;
  451.  
  452.                     case MSG_ADD_MULTI:
  453.                         control_io->ios2_Req.io_Command = S2_ADDMULTICASTADDRESS;
  454.                         Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6);
  455.                         DoIO((struct IORequest *)control_io);
  456.                         if (control_io->ios2_Req.io_Error == S2ERR_NOT_SUPPORTED) {
  457.                             WarningAlert(GetString(STR_NO_MULTICAST_WARN));
  458.                             msg->result = noErr;
  459.                         } else if (control_io->ios2_Req.io_Error)
  460.                             msg->result = eMultiErr;
  461.                         else
  462.                             msg->result = noErr;
  463.                         break;
  464.  
  465.                     case MSG_DEL_MULTI:
  466.                         control_io->ios2_Req.io_Command = S2_DELMULTICASTADDRESS;
  467.                         Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6);
  468.                         DoIO((struct IORequest *)control_io);
  469.                         if (control_io->ios2_Req.io_Error)
  470.                             msg->result = eMultiErr;
  471.                         else
  472.                             msg->result = noErr;
  473.                         break;
  474.  
  475.                     case MSG_ATTACH_PH: {
  476.                         uint16 type = msg->type;
  477.                         uint32 handler = msg->pointer;
  478.  
  479.                         // Protocol of that type already installed?
  480.                         NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next;
  481.                         while ((next = (NetProtocol *)p->ln_Succ) != NULL) {
  482.                             if (p->type == type) {
  483.                                 msg->result = lapProtErr;
  484.                                 goto reply;
  485.                             }
  486.                             p = next;
  487.                         }
  488.  
  489.                         // Allocate NetProtocol, set type and handler
  490.                         p = (NetProtocol *)AllocMem(sizeof(NetProtocol), MEMF_PUBLIC);
  491.                         if (p == NULL) {
  492.                             msg->result = lapProtErr;
  493.                             goto reply;
  494.                         }
  495.                         p->type = type;
  496.                         p->handler = handler;
  497.  
  498.                         // Set up and submit read requests
  499.                         for (int i=0; i<NUM_READ_REQUESTS; i++) {
  500.                             memcpy(p->read_io + i, control_io, sizeof(struct IOSana2Req));
  501.                             p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Name = (char *)p;    // Hide pointer to NetProtocol in node name
  502.                             p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Type = 0;            // Avoid CheckIO() bug
  503.                             p->read_io[i].ios2_Req.io_Message.mn_ReplyPort = read_port;
  504.                             p->read_io[i].ios2_Req.io_Command = CMD_READ;
  505.                             p->read_io[i].ios2_PacketType = type;
  506.                             p->read_io[i].ios2_Data = p->read_buf[i];
  507.                             p->read_io[i].ios2_Req.io_Flags = SANA2IOF_RAW;
  508.                             BeginIO((struct IORequest *)(p->read_io + i));
  509.                         }
  510.  
  511.                         // Add protocol to list
  512.                         AddTail(&prot_list, p);
  513.  
  514.                         // Everything OK
  515.                         msg->result = noErr;
  516.                         break;
  517.                     }
  518.  
  519.                     case MSG_DETACH_PH: {
  520.                         uint16 type = msg->type;
  521.                         msg->result = lapProtErr;
  522.                         NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next;
  523.                         while ((next = (NetProtocol *)p->ln_Succ) != NULL) {
  524.                             if (p->type == type) {
  525.                                 remove_protocol(p);
  526.                                 msg->result = noErr;
  527.                                 break;
  528.                             }
  529.                             p = next;
  530.                         }
  531.                         break;
  532.                     }
  533.  
  534.                     case MSG_WRITE: {
  535.                         // Get pointer to Write Data Structure
  536.                         uint32 wds = msg->pointer;
  537.                         write_io->ios2_Data = (void *)wds;
  538.  
  539.                         // Calculate total packet length
  540.                         long len = 0;
  541.                         uint32 tmp = wds;
  542.                         for (;;) {
  543.                             int16 w = ReadMacInt16(tmp);
  544.                             if (w == 0)
  545.                                 break;
  546.                             len += w;
  547.                             tmp += 6;
  548.                         }
  549.                         write_io->ios2_DataLength = len;
  550.  
  551.                         // Get destination address, set source address
  552.                         uint32 hdr = ReadMacInt32(wds + 2);
  553.                         Mac2Host_memcpy(write_io->ios2_DstAddr, hdr, 6);
  554.                         Host2Mac_memcpy(hdr + 6, ether_addr, 6);
  555.  
  556.                         // Get packet type
  557.                         uint32 type = ReadMacInt16(hdr + 12);
  558.                         if (type <= 1500)
  559.                             type = 0;        // 802.3 packet
  560.                         write_io->ios2_PacketType = type;
  561.  
  562.                         // Multicast/broadcard packet?
  563.                         if (write_io->ios2_DstAddr[0] & 1) {
  564.                             if (*(uint32 *)(write_io->ios2_DstAddr) == 0xffffffff && *(uint16 *)(write_io->ios2_DstAddr + 4) == 0xffff)
  565.                                 write_io->ios2_Req.io_Command = S2_BROADCAST;
  566.                             else
  567.                                 write_io->ios2_Req.io_Command = S2_MULTICAST;
  568.                         } else
  569.                             write_io->ios2_Req.io_Command = CMD_WRITE;
  570.  
  571.                         // Send packet
  572.                         write_done = false;
  573.                         write_io->ios2_Req.io_Flags = SANA2IOF_RAW;
  574.                         BeginIO((IORequest *)write_io);
  575.                         break;
  576.                     }
  577.                 }
  578. reply:            D(bug(" net_proc replying\n"));
  579.                 ReplyMsg(msg);
  580.             }
  581.         }
  582.  
  583.         // Packet received
  584.         if (sig & read_mask) {
  585.             D(bug(" packet received, triggering Ethernet interrupt\n"));
  586.             SetInterruptFlag(INTFLAG_ETHER);
  587.             TriggerInterrupt();
  588.         }
  589.  
  590.         // Packet write completed
  591.         if (sig & write_mask) {
  592.             GetMsg(write_port);
  593.             WriteMacInt32(ether_data + ed_Result, write_io->ios2_Req.io_Error ? excessCollsns : 0);
  594.             write_done = true;
  595.             D(bug(" packet write done, triggering Ethernet interrupt\n"));
  596.             SetInterruptFlag(INTFLAG_ETHER);
  597.             TriggerInterrupt();
  598.         }
  599.     }
  600. quit:
  601.  
  602.     // Close everything
  603.     remove_all_protocols();
  604.     if (opened) {
  605.         if (CheckIO((struct IORequest *)write_io) == 0) {
  606.             AbortIO((struct IORequest *)write_io);
  607.             WaitIO((struct IORequest *)write_io);
  608.         }
  609.         CloseDevice((struct IORequest *)control_io);
  610.     }
  611.     if (write_io)
  612.         DeleteIORequest(write_io);
  613.     if (control_io)
  614.         DeleteIORequest(control_io);
  615.     if (control_port)
  616.         DeleteMsgPort(control_port);
  617.     if (write_port)
  618.         DeleteMsgPort(write_port);
  619.     if (read_port)
  620.         DeleteMsgPort(read_port);
  621.  
  622.     // Send signal to main task to confirm termination
  623.     Forbid();
  624.     Signal(MainTask, SIGF_SINGLE);
  625. }
  626.  
  627.  
  628. /*
  629.  *  Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers
  630.  */
  631.  
  632. void EtherInterrupt(void)
  633. {
  634.     D(bug("EtherIRQ\n"));
  635.  
  636.     // Packet write done, enqueue DT to call IODone
  637.     if (write_done) {
  638.         EnqueueMac(ether_data + ed_DeferredTask, 0xd92);
  639.         write_done = false;
  640.     }
  641.  
  642.     // Call protocol handler for received packets
  643.     IOSana2Req *io;
  644.     while (io = (struct IOSana2Req *)GetMsg(read_port)) {
  645.  
  646.         // Get pointer to NetProtocol (hidden in node name)
  647.         NetProtocol *p = (NetProtocol *)io->ios2_Req.io_Message.mn_Node.ln_Name;
  648.  
  649.         // No default handler
  650.         if (p->handler == 0)
  651.             continue;
  652.  
  653.         // Copy header to RHA
  654.         Host2Mac_memcpy(ether_data + ed_RHA, io->ios2_Data, 14);
  655.         D(bug(" header %08lx%04lx %08lx%04lx %04lx\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12)));
  656.  
  657.         // Call protocol handler
  658.         M68kRegisters r;
  659.         r.d[0] = *(uint16 *)((uint32)io->ios2_Data + 12);    // Packet type
  660.         r.d[1] = io->ios2_DataLength - 18;                    // Remaining packet length (without header, for ReadPacket) (-18 because the CRC is also included)
  661.         r.a[0] = (uint32)io->ios2_Data + 14;                // Pointer to packet (host address, for ReadPacket)
  662.         r.a[3] = ether_data + ed_RHA + 14;                    // Pointer behind header in RHA
  663.         r.a[4] = ether_data + ed_ReadPacket;                // Pointer to ReadPacket/ReadRest routines
  664.         D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", p->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
  665.         Execute68k(p->handler, &r);
  666.  
  667.         // Resend IORequest
  668.         io->ios2_Req.io_Flags = SANA2IOF_RAW;
  669.         BeginIO((struct IORequest *)io);
  670.     }
  671.     D(bug(" EtherIRQ done\n"));
  672. }
  673.