home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / amitcp / net / if_sana.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  25.6 KB  |  1,019 lines

  1. RCS_ID_C="$Id: if_sana.c,v 3.2 1994/02/03 19:12:08 ppessi Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * if_sana.c --- Generic Interface Routines for Sana II Drivers
  8.  *
  9.  * Created      : Thu Feb 11 13:41:25 1993 ppessi
  10.  * Last modified: Thu Feb  3 17:47:18 1994 ppessi
  11.  *
  12.  * HISTORY
  13.  * $Log: if_sana.c,v $
  14.  * Revision 3.2  1994/02/03  19:12:08  ppessi
  15.  * Changed ssconfig_make() arguments.
  16.  *
  17.  * Revision 3.1  1994/02/03  03:50:38  ppessi
  18.  * Initially tested interface database
  19.  *
  20.  * Revision 1.31  1993/12/21  22:13:35  jraja
  21.  * Changed sana2 tracking not to be done to an interface if configured so.
  22.  * This is to get around a bug in CBM a2060.device.
  23.  *
  24.  * Revision 1.30  1993/11/14  21:15:19  jraja
  25.  * Changed IPTOS_LOWDELAY check to bitwise and (was == including other fields).
  26.  *
  27.  * Revision 1.29  1993/11/06  23:39:15  ppessi
  28.  * Automatically puts interface up when device returns to online state.
  29.  * The LOWDELAY IP packets are given higher priority IO requests.
  30.  *
  31.  * Revision 1.28  1993/10/11  20:31:46  jraja
  32.  * Added explicit prototype for the CheckIO(), which is prototyped
  33.  * incorrectly in the <clib/exec_protos.h>.
  34.  *
  35.  */
  36.  
  37. #include <conf.h>
  38.  
  39. #include <sys/param.h>
  40. #include <sys/cdefs.h>
  41. #include <sys/malloc.h>
  42. #include <sys/mbuf.h>
  43. #include <sys/socket.h>
  44. #include <sys/errno.h>
  45. #include <sys/ioctl.h>
  46. #include <sys/systm.h>
  47. #include <sys/syslog.h>
  48.  
  49. #include <kern/amiga_includes.h>
  50.  
  51. #include <sys/synch.h>
  52. #include <sys/time.h>
  53.  
  54. #include <net/if.h>
  55. #include <net/netisr.h>
  56.  
  57. #define NDEBUG
  58. #include <assert.h>
  59.  
  60. #if INET
  61. #include <netinet/in.h>
  62. #include <netinet/in_systm.h>
  63. #include <netinet/in_var.h>
  64. #include <netinet/ip.h>
  65. #endif
  66.  
  67. #if NS
  68. #include <netns/ns.h>
  69. #include <netns/ns_if.h>
  70. #endif
  71.  
  72. #include <net/if_sana.h>
  73. #include <net/sana2arp.h>
  74.  
  75. #include <net/sana2config.h>
  76. #include <net/sana2request.h>
  77. #include <net/sana2errno.h>
  78.  
  79. #if __SASC
  80. #include <proto/dos.h>
  81. #elif __GNUC__
  82. #include <inline/dos.h>
  83. #else
  84. #error Your compiler is not supported in this release.
  85. #endif
  86.  
  87. /* Correct prototype for the CheckIO.
  88.  * (The one in clib/exec_protos.h has wrong return value type: BOOL (16 bits) 
  89.  * instead of a pointer (32 bits)!)
  90.  */
  91. struct IORequest * CheckIO(struct IORequest *req);
  92.  
  93. #define ARP_MTU (sizeof(struct s2_arppkt))
  94.  
  95. int debug_sana = 1;
  96.  
  97. /* Global port for all SANA-II network interfaces */
  98. struct MsgPort *SanaPort = NULL;
  99.  
  100. /* queue for sana network interfaces */
  101. struct sana_softc *ssq = NULL;
  102.  
  103. /* These are wire type dependant parameters of 
  104.  * Sana-II Network Interface
  105.  */
  106. extern struct wiretype_parameters wiretype_table[];
  107.  
  108. /* 
  109.  * Local prototypes
  110.  */
  111. static struct ifnet *iface_make(struct ssconfig *ifc);
  112. static void sana_run(struct sana_softc *ssc, int requests, struct ifaddr *ifa);
  113. static void sana_unrun(struct sana_softc *ssc);
  114. static void sana_up(struct sana_softc *ssc);
  115. static BOOL sana_down(struct sana_softc *ssc);
  116. static struct mbuf *
  117. sana_read(struct sana_softc *ssc, struct IOIPReq *req, 
  118.       UWORD  flags, UWORD *sent, const char *banner, size_t mtu);
  119. static void sana_ip_read(struct sana_softc *ssc, struct IOIPReq *req);
  120. static void sana_arp_read(struct sana_softc *ssc, struct IOIPReq *req);
  121. static void sana_online(struct sana_softc *ssc, struct IOIPReq *req);
  122. static void free_written_packet(struct sana_softc *ssc, struct IOIPReq *req);
  123.  
  124. /*
  125.  * Initialize Sana-II interface
  126.  *
  127.  * This routine creates needed message port for Sana-II IO
  128.  * It returns our signal mask, or 0L on an error.
  129.  */
  130. ULONG 
  131. sana_init(void)
  132. {
  133.   assert(!SanaPort);
  134.  
  135.   SanaPort = CreateMsgPort();    /* V36 function, creates a PA_SIGNAL port */
  136.  
  137.   if (SanaPort) {
  138.     SanaPort->mp_Node.ln_Name = (void *)"sana_if.port";
  139.     loattach();
  140.     return (ULONG) 1 << SanaPort->mp_SigBit;
  141.   }
  142.  
  143.   return 0L;
  144. }
  145.  
  146. /*
  147.  * Clean up Sana-II Interfaces
  148.  *
  149.  * Note: main interface queue is SNAFU after deinitializing
  150.  */
  151. void 
  152. sana_deinit(void)
  153. {
  154.   struct sana_softc *ssc; 
  155.   struct IOSana2Req *req;
  156.  
  157.   assert(SanaPort);
  158.  
  159.   while (ssq) {
  160.     sana_down(ssq);
  161.     if (ssq->ss_if.if_flags & IFF_RUNNING) {
  162.       sana_unrun(ssq);
  163.     }
  164.     ssc = ssq;
  165.     ssq = ssc->ss_next;
  166.     /* Close device */ 
  167.     req = CreateIOSana2Req(ssc);
  168.     if (req) {
  169.       CloseDevice((struct IORequest*)req);
  170.       DeleteIOSana2Req(req);
  171.     } else {
  172.       log(LOG_ERR, "sana_deinit(): Couldn't close device %s\n",
  173.       ssc->ss_name);
  174.     }
  175.   }
  176.  
  177.   if (SanaPort) {
  178.     /* Clear possible pending signals */
  179.     SetSignal(1<<SanaPort->mp_SigBit, 0L);
  180.     DeleteMsgPort(SanaPort);
  181.     SanaPort = NULL;
  182.   }
  183. }
  184.  
  185. /*
  186.  * sana_poll()
  187.  *  This routine polls SanaPort and processes replied
  188.  *  requests appropriately
  189.  */
  190. BOOL
  191. sana_poll(void)
  192. {
  193.   struct IOIPReq * io;
  194.   spl_t s = splnet();
  195.  
  196.   while (io = (struct IOIPReq *)GetMsg(SanaPort)) {
  197.     /* touch the network interface */
  198.     get_time(&io->ioip_if->ss_if.if_lastchange);
  199.     if (io->ioip_dispatch) {
  200.       (*io->ioip_dispatch)(io->ioip_if, io);
  201.      } else {
  202.        log(LOG_ERR, "No dispatch function in request for %s\n",
  203.        io->ioip_if->ss_name);
  204.      }
  205.   }
  206.  
  207.   net_poll();
  208.  
  209.   splx(s);
  210.  
  211.   return FALSE;
  212. }
  213.  
  214. #ifdef COMPAT_AMITCP2
  215. /*
  216.  * Name points to the full device name.
  217.  * Device name is a legal DOS file name,
  218.  * appended with a slash and a decimal unit number
  219.  *
  220.  * Some explanation on the device names:
  221.  * There is a DOS wrapper around Exec OpenDevice() function.
  222.  * The device is first searched from the Exec list, if that fails
  223.  * DOS tries to load the segment file with the device name. 
  224.  * If that fails too, the filename is catenated to string "DEVS:" and
  225.  * DOS tries again. 
  226.  *
  227.  * AmiTCP uses internally only the Exec device name (ie. device name
  228.  * without pathpart)
  229.  */
  230.  
  231. /*
  232.  * Map exec device name to
  233.  * interface structure pointer.
  234.  */
  235. struct ifnet *aifunit(register char *name)
  236. {
  237.   register char *cp;
  238.   register struct ifnet *ifp;
  239.   long unit;
  240.   unsigned len;
  241.   char *ep, c;
  242.  
  243.   /* AmigaTCP/IP uses the slash as unit number separator 
  244.    * because Exec device name may contain digits.
  245.    */
  246.   char *up;
  247.   cp = ep = name - 1;
  248.   /* Find pathpart */
  249.   for (up = name; *up; up++) 
  250.     if (*up == '/' || *up == ':') {
  251.       cp = ep;
  252.       ep = up;
  253.     }
  254.   /* Name is too long, or there is no unit number */
  255.   if (up >= cp + IFNAMSIZ || cp == ep)    
  256.     return ((struct ifnet *)0);
  257.   cp++;
  258.  
  259.   /*
  260.    * cp points first char in device name,
  261.    * ep to unit number separator ('/')
  262.    * and up to NUL ('\0') at the end of string
  263.    */
  264.   len = ep - cp;
  265.   c = *ep;
  266.   *ep = '\0';            /* sentinel */
  267.   for (unit = 0, up--; *up >= '0' && *up <= '9'; up--) 
  268.     unit = unit * 10 + *up - '0';
  269.   if (up != ep) {
  270.     *ep = c;
  271.     return NULL;
  272.   }
  273.  
  274.   /* Pathpart is not included in search */
  275.   for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  276.     if (bcmp(ifp->if_name, cp, len))
  277.       continue;
  278.     if (unit == ifp->if_unit)
  279.       break;
  280.   }
  281.   {
  282.     extern struct ifnet *aiface_find(char *, long unit);
  283.     *ep = '\0';            /* sentinel */
  284.     if (ifp == 0)
  285.       ifp = aiface_find(name, unit);
  286.     *ep = c;
  287.   }
  288.   return (ifp);
  289. }
  290.  
  291. struct ifnet *
  292. aiface_find(char *name, long unit)
  293. {
  294.   struct  = sana2tag_find_exec(name, unit);
  295.  
  296.   /* No alias found, use defaults */
  297.   if (sifp == NULL) {
  298.     static short sana_units = 0;
  299.     struct interface_parameters sifp[1];
  300.     const static long tag_end = TAG_END;
  301.  
  302.     sifp->ifname = "sana";
  303.     sifp->unit = sana_units++;
  304.     sifp->execname = name;
  305.     sifp->execunit = unit;
  306.     sifp->tags = (struct TagItem *)&tag_end;
  307.     return make_iface(sifp, sifp->unit);
  308.   }
  309.   return make_iface(sifp, sifp->unit);
  310. }
  311. #endif
  312.  
  313. /*
  314.  * This function strategically plugs into ifunit(), and it is called
  315.  * on a non-existant interface.  We try to look it up, and if successful
  316.  * initialize a descriptor and call if_attach() with it.
  317.  *
  318.  * Name is Unix kernel device name,
  319.  * we convert it to Exec device and unit.
  320.  */
  321. struct ifnet *
  322. iface_find(char *name, short unit)
  323. {
  324.   struct ssconfig *ifc = ssconfig_make(SSC_ALIAS, name, unit);
  325.   
  326.   if (ifc) {
  327.     struct ifnet *ifp = iface_make(ifc);
  328.     ssconfig_free(ifc);
  329.     return ifp;
  330.   }
  331.   return NULL;
  332. }
  333.  
  334. static struct ifnet *
  335. iface_make(struct ssconfig *ifc)
  336. {
  337.   register struct sana_softc *ssc = NULL;
  338.   register struct IOSana2Req *req;
  339.   struct Sana2DeviceQuery devicequery;
  340.  
  341.   /* Allocate the request for opening the device */
  342.   if ((req = CreateIOSana2Req(NULL)) == NULL) 
  343.     log(LOG_ERR, "iface_find(): CreateIOSana2Req failed\n");
  344.   else {
  345.     req->ios2_BufferManagement = buffermanagement;
  346.  
  347.     if (OpenDevice(ifc->args->a_dev, *ifc->args->a_unit, 
  348.            (struct IORequest *)req, 0L)) {
  349.       sana2perror("OpenDevice", req);
  350.     } else {
  351.       /* Ask for our type, address length, MTU
  352.        * Obl. bitch: nobody tells, WHO is supplying
  353.        * DevQueryFormat and DeviceLevel
  354.        */
  355.       req->ios2_Req.io_Command   = S2_DEVICEQUERY;
  356.       req->ios2_StatData         = &devicequery;
  357.       devicequery.SizeAvailable  = sizeof(devicequery);
  358.       devicequery.DevQueryFormat = 0L;
  359.       
  360.       DoIO((struct IORequest *)req);
  361.       if (req->ios2_Req.io_Error)
  362.     sana2perror("S2_DEVICEQUERY", req);
  363.       else {
  364.     /* Get Our Station address */
  365.     req->ios2_StatData = NULL;
  366.     req->ios2_Req.io_Command = S2_GETSTATIONADDRESS;
  367.     DoIO((struct IORequest *)req);
  368.     
  369.     if (req->ios2_Req.io_Error)
  370.       sana2perror("S2_GETSTATIONADDRESS", req);
  371.     else {
  372.       req->ios2_Req.io_Command = 0;
  373.       
  374.       /* Allocate the interface structure */
  375.       ssc = (struct sana_softc *)
  376.         bsd_malloc(sizeof(*ssc) + strlen(ifc->args->a_dev) + 1,
  377.                M_IFNET, M_WAITOK);
  378.       if (!ssc)
  379.         log(LOG_ERR, "iface_find: out of memory\n");
  380.       else {
  381.         aligned_bzero_const(ssc, sizeof(*ssc));
  382.         
  383.         /* Save request pointers */
  384.         ssc->ss_dev     = req->ios2_Req.io_Device;
  385.         ssc->ss_unit    = req->ios2_Req.io_Unit;
  386.         ssc->ss_bufmgnt = req->ios2_BufferManagement;
  387.         
  388.         /* Address must be full bytes */
  389.         ssc->ss_if.if_addrlen  = (devicequery.AddrFieldSize + 7) >> 3;
  390.         bcopy(req->ios2_DstAddr, ssc->ss_hwaddr, ssc->ss_if.if_addrlen);
  391.         ssc->ss_if.if_mtu      = devicequery.MTU;
  392.         ssc->ss_maxmtu         = devicequery.MTU;
  393.         ssc->ss_if.if_baudrate = devicequery.BPS;
  394.         ssc->ss_hwtype         = devicequery.HardwareType;    
  395.         
  396.         /* These might be different on different hwtypes */
  397.         ssc->ss_if.if_output = sana_output;
  398.         ssc->ss_if.if_ioctl  = sana_ioctl;
  399.  
  400.         /* Initialize */ 
  401.         ssconfig(ssc, ifc);
  402.         
  403.         NewList((struct List*)&ssc->ss_freereq);
  404.  
  405.         if_attach((struct ifnet*)ssc);
  406.         ifinit();
  407.         
  408.         ssc->ss_next = ssq;
  409.         ssq = ssc;
  410.       }
  411.     }
  412.       }
  413.       if (!ssc)
  414.     CloseDevice((struct IORequest *)req);
  415.     }    
  416.     DeleteIOSana2Req(req);
  417.   }
  418.  
  419.   return (struct ifnet *)ssc;
  420. }
  421.  
  422. /*
  423.  * Allocate Sana-II IORequests for TCP/IP process
  424.  */
  425. static void
  426. sana_run(struct sana_softc *ssc, int requests, struct ifaddr *ifa)
  427. {
  428.   int i;
  429.   spl_t s = splimp();
  430.   struct IOIPReq *req, *next = ssc->ss_reqs;
  431.   
  432.   /*
  433.    * Configure the Sana-II device driver
  434.    * (now with factory address)
  435.    */
  436.   if ((ssc->ss_if.if_flags & IFF_RUNNING) == 0) {
  437.     struct IOSana2Req *req;
  438.  
  439.     if (req = CreateIOSana2Req(ssc)) {
  440.       req->ios2_Req.io_Command = S2_CONFIGINTERFACE;
  441.       bcopy(ssc->ss_hwaddr, req->ios2_SrcAddr, ssc->ss_if.if_addrlen);
  442.  
  443.       DoIO((struct IORequest*)req);
  444.       if (req->ios2_Req.io_Error)
  445.     sana2perror("S2_CONFIGINTERFACE", req);
  446.  
  447.       if (req->ios2_Req.io_Error == 0 ||
  448.       req->ios2_WireError == S2WERR_IS_CONFIGURED) {
  449.     /* Mark us as running */
  450.     ssc->ss_if.if_flags |= IFF_RUNNING;
  451.     if (ssc->ss_cflags & SSF_TRACK) {
  452. #ifdef INET
  453.       /* Ask for packet type specific statistics */
  454.       req->ios2_Req.io_Command = S2_TRACKTYPE;
  455.       req->ios2_PacketType = ssc->ss_ip.type;
  456.       DoIO((struct IORequest*)req);
  457.       /* It is *not* safe to turn tracking off */
  458.       if (req->ios2_Req.io_Error && 
  459.           req->ios2_WireError != S2WERR_ALREADY_TRACKED) 
  460.         sana2perror("S2_TRACKTYPE for IP", req);
  461.       if (ssc->ss_arp.reqno) {
  462.         req->ios2_Req.io_Command = S2_TRACKTYPE;
  463.         req->ios2_PacketType = ssc->ss_arp.type;
  464.         DoIO((struct IORequest*)req);
  465.         if (req->ios2_Req.io_Error  && 
  466.         req->ios2_WireError != S2WERR_ALREADY_TRACKED) 
  467.           sana2perror("S2_TRACKTYPE for ARP", req);
  468.       }
  469. #endif    
  470.     }
  471.       }
  472.       DeleteIOSana2Req(req);
  473.     }
  474.   }
  475.  
  476.   if ((ssc->ss_if.if_flags & IFF_RUNNING)) {
  477.     /* Initialize ioRequests, add them into free queue */
  478.     for (i = 0; i < requests ; i++) {
  479.       if (!(req = CreateIORequest(SanaPort, sizeof(*req))))
  480.     break;
  481.       req->ioip_s2.ios2_Req.io_Device    = ssc->ss_dev;    
  482.       req->ioip_s2.ios2_Req.io_Unit      = ssc->ss_unit;   
  483.       req->ioip_s2.ios2_BufferManagement = ssc->ss_bufmgnt;
  484.       aligned_bcopy(ssc->ss_hwaddr, req->ioip_s2.ios2_SrcAddr, ssc->ss_if.if_addrlen);
  485.       req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  486.       req->ioip_s2.ios2_Data = req;
  487.       req->ioip_if = ssc;
  488.       req->ioip_next = next;
  489.       AddTail((struct List*)&ssc->ss_freereq, (struct Node*)req);
  490.       next = req;
  491.     }
  492.     ssc->ss_reqs = next;
  493.   }
  494.   splx(s);
  495. }
  496.  
  497. /*
  498.  * Free Sana-II IO Requests 
  499.  * Note: this is protected by splimp();
  500.  */
  501. static void
  502. sana_unrun(struct sana_softc *ssc)
  503. {
  504.   struct IOIPReq *req, *next;
  505.   
  506.   for ( next = ssc->ss_reqs; req = next ;) {
  507.     next = req -> ioip_next;
  508.     WaitIO((struct IORequest *)req);
  509.     DeleteIORequest(req);
  510.   }
  511.   ssc->ss_reqs = next;
  512.   
  513.   ssc->ss_if.if_flags &= ~IFF_RUNNING;
  514. }
  515.  
  516. /*
  517.  * Generic SANA-II interface ioctl
  518.  *
  519.  * Interface setup is thru IOCTL.
  520.  */
  521. int 
  522. sana_ioctl(register struct ifnet *ifp, int cmd, caddr_t data)
  523. {
  524.   register struct sana_softc *ssc = (struct sana_softc*)ifp;
  525.   register struct ifaddr *ifa = (struct ifaddr *)data;
  526.   register struct ifreq *ifr = (struct ifreq *)data;
  527.   
  528.   spl_t s = splimp();
  529.   int error = 0;
  530.  
  531.   switch (cmd) {
  532.  
  533.   case SIOCSIFFLAGS:
  534.     if ((ifr->ifr_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))
  535.       sana_up(ssc);
  536.     /* Call sana_down() in every case */
  537.     if ((ifr->ifr_flags & IFF_UP) == 0) 
  538.       sana_down(ssc);
  539.     if ((ifr->ifr_flags & IFF_NOARP) == 0)
  540.       alloc_arptable(ssc, 0);
  541.     break;
  542.  
  543.     /*
  544.      * Set interface address (and mark interface up).
  545.      */
  546.   case SIOCSIFADDR:        /* Set Interface Address */
  547.     if (!(ssc->ss_if.if_flags & IFF_RUNNING)) 
  548.       sana_run(ssc, ssc->ss_reqno, ifa);
  549.     if ((ssc->ss_if.if_flags & IFF_RUNNING) && !(ssc->ss_if.if_flags & IFF_UP))
  550.       sana_up(ssc);
  551.     if ((ifr->ifr_flags & IFF_NOARP) == 0)
  552.       alloc_arptable(ssc, 0);
  553.     
  554.   case SIOCAIFADDR:        /* Alter Interface Address */
  555.     switch (ifa->ifa_addr->sa_family) {
  556. #if INET
  557.     case AF_INET:
  558.       ssc->ss_ipaddr = IA_SIN(ifa)->sin_addr;
  559.       break;
  560. #endif
  561.     }
  562.     break;
  563.  
  564.   case SIOCSIFDSTADDR:        /* Sets P-P-link destination address */
  565.     break;
  566.  
  567.   default:
  568.     error = EINVAL;
  569.     break;
  570.   }
  571.   splx(s);
  572.   return (error);
  573. }
  574.  
  575. /*
  576.  * sana_send_read(): 
  577.  * send read requests with given types, dispatcher & c  
  578.  * MUST be called at splimp()
  579.  */
  580. static inline WORD 
  581. sana_send_read(struct sana_softc *ssc, WORD count, ULONG type, ULONG mtu,
  582.            void (*dispatch)(struct sana_softc *, struct IOIPReq *),
  583.            UWORD command, UBYTE flags)
  584. {
  585.   struct IOIPReq *req = NULL;
  586.   WORD i;
  587.  
  588.   for (i = 0; i < count; i++) {
  589.     if (!(req = (struct IOIPReq*)RemHead((struct List*)&ssc->ss_freereq)))
  590.       return i;
  591.     req->ioip_dispatch = dispatch;
  592.     req->ioip_s2.ios2_PacketType = type;
  593.     req->ioip_Command = command;
  594.     req->ioip_s2.ios2_Req.io_Flags = flags;
  595.     if (!ioip_alloc_mbuf(req, mtu))
  596.       goto no_resources;
  597.     BeginIO((struct IORequest*)req);
  598.   }
  599.   return i;
  600.  
  601.  no_resources:
  602.   if (req)
  603.     AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
  604.   log(LOG_ERR, "sana_up: could not queue enough read requests\n");
  605.   return i;
  606. }
  607.  
  608. /*
  609.  * sana_up():
  610.  * send read requests
  611.  */
  612. static void
  613. sana_up(struct sana_softc *ssc)
  614. {
  615.   spl_t s = splimp();
  616.   ssc->ss_if.if_flags |= IFF_UP;
  617.   
  618.   /* Send read requests to device driver */
  619. #if    INET
  620.   /* IP */
  621.   ssc->ss_ip.sent += 
  622.     sana_send_read(ssc, ssc->ss_ip.reqno - ssc->ss_ip.sent, ssc->ss_ip.type,
  623.            ssc->ss_if.if_mtu, sana_ip_read, CMD_READ, 0);
  624.  
  625.   ssc->ss_arp.sent += 
  626.     sana_send_read(ssc, ssc->ss_arp.reqno - ssc->ss_arp.sent, ssc->ss_arp.type,
  627.            ARP_MTU, sana_arp_read, CMD_READ, 0);
  628.  
  629. #endif /* INET */
  630. #if    ISO
  631. #endif /* ISO */
  632. #if    CCITT
  633. #endif /* CCITT */
  634. #if    NS
  635. #endif /* NS */
  636. #if 0
  637.   ssc->ss_rawsent += 
  638.     sana_send_read(ssc, ssc->ss_rawreqno - ssc->ss_rawsent, 0,
  639.            ssc->ss_if.if_mtu, sana_raw_read, 
  640.            S2_READORPHAN, SANA2_IOF_RAW);
  641. #endif
  642.   splx(s);
  643.   return;
  644. }
  645.  
  646. #if __SASC
  647. /*
  648.  * "Fix" for numerous sana2 drivers, which expect to get Unit * in the
  649.  * register A3 when their AbortIO function is called.
  650.  * Note that Exec AbortIO() does NOT put it there.
  651.  */
  652. extern VOID _AbortSanaIO(struct IORequest *, struct Unit *);
  653. #pragma libcall DeviceBase _AbortSanaIO 24 B902
  654.  
  655. static inline __asm VOID 
  656. AbortSanaIO(register __a1 struct IORequest *ioRequest)
  657. {
  658. #define DeviceBase ioRequest->io_Device
  659.   _AbortSanaIO(ioRequest, ioRequest->io_Unit);
  660. #undef DeviceBase
  661. }
  662. #else /* implement later for other compilers */
  663. #define AbortSanaIO AbortIO
  664. #endif
  665.  
  666. /*
  667.  * sana_down(): Mark interface as down, abort all pending requests
  668.  */
  669. static BOOL
  670. sana_down(struct sana_softc *ssc)
  671. {
  672.   spl_t s = splimp();
  673.   struct IOIPReq *req = ssc->ss_reqs;
  674.  
  675.   /* Completed, Remove()'d requests are not aborted */
  676.   while (req) {
  677.     if (!CheckIO((struct IORequest*)req)) {
  678.       AbortSanaIO((struct IORequest*)req);
  679.     }
  680.     req = req->ioip_next;
  681.   }
  682.  
  683.   splx(s);
  684.  
  685.   return(TRUE);
  686. }
  687.  
  688. /*
  689.  * sana_read: deattach a packet from IORequest
  690.  *            resend the IORequest
  691.  */
  692. static struct mbuf *
  693. sana_read(struct sana_softc *ssc, struct IOIPReq *req, 
  694.       UWORD  flags, UWORD *sent, const char *banner, size_t mtu)
  695. {
  696.   register struct mbuf *m = req->ioip_packet;
  697.   register spl_t s = splimp();
  698.  
  699.   req->ioip_packet = NULL;
  700.  
  701.   switch (req->ioip_Error) {
  702.   case 0:
  703.     if (req->ioip_s2.ios2_Req.io_Flags & SANA2IOF_BCAST) 
  704.       m->m_flags |= M_BCAST;
  705.     if (req->ioip_s2.ios2_Req.io_Flags & SANA2IOF_MCAST)
  706.       m->m_flags |= M_MCAST;
  707.     break;
  708.   case S2ERR_OUTOFSERVICE:
  709.     /*
  710.      * Somebody put Sana-II driver offline.
  711.      * We put down also the network interface 
  712.      */
  713.     if (ssc->ss_if.if_flags & IFF_UP) {
  714.       /* Show a log message */
  715.       sana2perror(ssc->ss_if.if_name, (struct IOSana2Req *)req);
  716.  
  717.       /* tell it to protocols */
  718.       if_down((struct ifnet *)ssc); 
  719.  
  720.       /* Free mbufs allocated for packet */
  721.       m_freem(req->ioip_reserved);
  722.       req->ioip_reserved = NULL;
  723.  
  724.       /* Order an notify when driver is put back online */
  725.       ssc->ss_eventsent++;
  726.       req->ioip_s2.ios2_Req.io_Command = S2_ONEVENT;
  727.       req->ioip_s2.ios2_WireError = S2EVENT_ONLINE;
  728.       req->ioip_dispatch = sana_online;
  729.       BeginIO(req);
  730.       req = NULL;
  731.     }
  732.     ssc->ss_if.if_flags &= ~IFF_UP;
  733.     m_freem(m);
  734.     m = NULL;
  735.     break;
  736.   default:
  737.     if (debug_sana && req->ioip_Error != IOERR_ABORTED) 
  738.       sana2perror(banner, (struct IOSana2Req *)req);
  739.     m_freem(m);
  740.     m = NULL;
  741.   }
  742.  
  743.   if (ssc->ss_if.if_flags & IFF_UP) {
  744.     /* Return request to the Sana-II driver */
  745.     if (ioip_alloc_mbuf(req, mtu)) {
  746.       req->ioip_s2.ios2_Req.io_Flags = flags;
  747.       BeginIO((struct IORequest*)req); 
  748.       splx(s);
  749.       return m;
  750.     }
  751.     log(LOG_ERR, "sana_read (%s): not enough mbufs\n", ssc->ss_name);
  752.   } 
  753.  
  754.   /* do not resend, free used resources */
  755.   (*sent)--;
  756.   if (req) {
  757.     m_freem(req->ioip_reserved);
  758.     req->ioip_reserved = NULL;
  759.     req->ioip_dispatch = NULL;
  760.     AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
  761.   }
  762.  
  763.   if (m) {
  764.     m_freem(m);
  765.   }
  766.  
  767.   splx(s);
  768.   return NULL;
  769. }
  770.  
  771. /*
  772.  * sana_ip_read(): feed a packet to the IP queue
  773.  * (This routine is called from sana_poll)
  774.  */
  775. static void
  776. sana_ip_read(struct sana_softc *ssc, struct IOIPReq *req)
  777. {
  778.   struct mbuf *m = sana_read(ssc, req, 0, &ssc->ss_ip.sent, "sana_ip_read",
  779.                  ssc->ss_if.if_mtu);
  780.   spl_t s;
  781.  
  782.   if (m) {
  783.     s = splimp();
  784.     if (IF_QFULL(&ipintrq)) {
  785.       IF_DROP(&ipintrq);
  786.       m_freem(m);
  787.       /* m = NULL; */
  788.     } else {
  789.       /* Set interface pointer (needed for broadcasts) */
  790.       m->m_pkthdr.rcvif = (struct ifnet *)ssc; 
  791.       IF_ENQUEUE(&ipintrq, m);
  792.       /* A signal might be needed if we use PA_EXCEPTION port */
  793.       schednetisr_nosignal(NETISR_IP);
  794.       /* m = NULL; */
  795.     }
  796.     splx(s);
  797.   }
  798. }
  799.  
  800. /*
  801.  * sana_arp_read(): process an ARP packet
  802.  * (This routine is called from sana_poll)
  803.  */
  804. static void
  805. sana_arp_read(struct sana_softc *ssc, struct IOIPReq *req)
  806. {
  807.   struct mbuf *m; 
  808.   UBYTE hwaddr[MAXADDRSANA];
  809.  
  810.   bcopy(req->ioip_s2.ios2_SrcAddr, hwaddr, ssc->ss_if.if_addrlen);
  811.  
  812.   m = sana_read(ssc, req, 0, &ssc->ss_arp.sent, "sana_arp_read", ARP_MTU);
  813.  
  814.   if (m)
  815.     arpinput(ssc, m, hwaddr);
  816. }
  817.  
  818. /*
  819.  * sana_online(): process an ONLINE event
  820.  */
  821. static void
  822. sana_online(struct sana_softc *ssc, struct IOIPReq *req)
  823. {
  824.   LONG events = req->ioip_s2.ios2_WireError;
  825.  
  826.   if (req->ioip_s2.ios2_Req.io_Error == 0 &&
  827.       events & S2EVENT_ONLINE) {
  828.     ssc->ss_eventsent--;
  829.     req->ioip_dispatch = NULL;
  830.     AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
  831.     log(LOG_NOTICE, "%s is online again.", ssc->ss_name);
  832.     sana_up(ssc);
  833.     return;
  834.   }
  835.  
  836.   /* An error? */
  837.   if (debug_sana && req->ioip_Error != IOERR_ABORTED) { 
  838.     sana2perror("sana_online", (struct IOSana2Req *)req);
  839.     req->ioip_s2.ios2_Req.io_Command = S2_ONEVENT;
  840.     req->ioip_s2.ios2_WireError = S2EVENT_ONLINE;
  841.     BeginIO(req);
  842.   } else {
  843.     /* Aborted -- probably because "ifconfig xxx/0 down" */
  844.     ssc->ss_eventsent--;
  845.     req->ioip_dispatch = NULL;
  846.     AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
  847.   }
  848. }
  849.  
  850. /*
  851.  * sana_output: send a packet to Sana-II driver
  852.  */
  853. int
  854. sana_output(struct ifnet *ifp, struct mbuf *m0, 
  855.         struct sockaddr *dst, struct rtentry *rt)
  856. {
  857.   register struct sana_softc *ssc = (struct sana_softc *)ifp;
  858.   ULONG type;
  859.   int error = 0;
  860.   struct in_addr idst;
  861.  
  862.   /* If a broadcast, send a copy to ourself too */
  863.   struct mbuf *mcopy = (struct mbuf *)NULL;
  864.   struct IOIPReq *req = NULL;
  865.   register struct mbuf *m = m0;
  866.  
  867.   int len = m->m_pkthdr.len;
  868.   spl_t s = splimp();
  869.  
  870.   ifp->if_opackets++;        /* stats */
  871.  
  872.   /* Check if we are up and running... */
  873.   if ((ssc->ss_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
  874.     error = ENETDOWN;
  875.     goto bad;
  876.   }
  877.  
  878.   get_time(&ssc->ss_if.if_lastchange);
  879.  
  880.   /* Get a free Sana-II IO request */
  881.   if (!(req = (struct IOIPReq*)RemHead((struct List*)&ssc->ss_freereq))) {
  882.     error = ENOBUFS;
  883.     goto bad;
  884.   }
  885.  
  886.   req->ioip_s2.ios2_Req.io_Flags = 0;
  887.  
  888.   switch (dst->sa_family) {
  889. #if INET
  890.   case AF_INET:
  891.     idst = ((struct sockaddr_in *)dst)->sin_addr;
  892.  
  893.     /* If the address is not resolved, arpresolve
  894.      * stores the packet to its private queue for
  895.      * later transmit and broadcasts the resolve
  896.      * request packet to the (ether)net.
  897.      * (Now ARP works only with IP and ethernet.)
  898.      */
  899.     if ((ssc->ss_if.if_flags & IFF_NOARP) != IFF_NOARP &&
  900.     /* ssc = network interface 
  901.      * m = Packet to send 
  902.      * idst = destination IP address 
  903.      * ios2_DestAddr = destination hw address 
  904.      * error = error return
  905.      */
  906.     !arpresolve(ssc, m, &idst, req->ioip_s2.ios2_DstAddr, &error)) {
  907.       AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
  908.       splx(s);
  909.       return (0);
  910.     }
  911.     type = ssc->ss_ip.type;
  912.  
  913.     /* Send to loopback if we do not hear our broadcasts */
  914.     if ((ssc->ss_if.if_flags & IFF_SIMPLEX) && (m->m_flags & M_BCAST)) {
  915.       mcopy = m_copy(m, 0, (int)M_COPYALL);
  916.       (void) looutput(&ssc->ss_if, mcopy, dst, rt);
  917.     }
  918.     /* Set the message priority */
  919.     req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Pri =
  920.       (IPTOS_LOWDELAY & mtod(m, struct ip *)->ip_tos) ?
  921.     1 : 0;
  922.     break;
  923. #endif
  924. #if NS
  925. #error NS unimplemented!!!
  926.   case AF_NS:
  927.     type = ssc->ss_nstype;
  928.     /* There is hardware address straight in socket */
  929.     /* Dunno how this works, if we have a P-to-P device */
  930.     bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
  931.       (caddr_t)req->ioip_s2.ios2_DestAddr, ssc->ss_if.if_addrlen);
  932.     /* Local send */
  933.     if (!bcmp((caddr_t)req->ioip_s2.ios2_DestAddr,
  934.           (caddr_t)&ns_thishost, ssc->ss_if.if_addrlen)) {
  935.       AddHead(&ssc->ss_freereq, req);
  936.       return (looutput(ifp, m, dst, rt));
  937.     }
  938.     req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Pri = 0;
  939.     break;
  940. #endif
  941.   case AF_UNSPEC:
  942.     /* Raw packets. Sana-II address (a tuple of type and host)
  943.      * specifies the destination 
  944.      */
  945.     if (type = ((struct sockaddr_sana2*)dst)->ss2_type) {
  946.       bcopy(((struct sockaddr_sana2*)dst)->ss2_host, 
  947.         req->ioip_s2.ios2_DstAddr, 
  948.         ssc->ss_if.if_addrlen);
  949.     } else {
  950.       req->ioip_s2.ios2_Req.io_Flags = SANA2IOF_RAW;
  951.       type = 0L;
  952.     }
  953.     req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Pri = 0;
  954.     break;
  955.  
  956. #if    ISO
  957. #endif /* ISO */
  958. #if RMP
  959.   case AF_RMP:
  960. #endif
  961.  
  962.   default: 
  963.     log(LOG_ERR, "%s%ld: can't handle af%ld\n",
  964.     ssc->ss_if.if_name, ssc->ss_if.if_unit, dst->sa_family);
  965.     error = EAFNOSUPPORT; 
  966.     goto bad; 
  967.   }
  968.  
  969.   /*
  970.    * Queue packet to Sana-II driver
  971.    */
  972.   req->ioip_Command = (m->m_flags & M_BCAST) ? S2_BROADCAST : CMD_WRITE;
  973.   req->ioip_dispatch = free_written_packet;
  974.   req->ioip_packet = m;
  975.   req->ioip_s2.ios2_PacketType = type;
  976.   req->ioip_s2.ios2_DataLength = len;
  977.  
  978.   BeginIO((struct IORequest*)req);
  979.  
  980.   /* These statistics are somewhat redundant */
  981.   ifp->if_obytes += len;
  982.   if (m->m_flags & M_BCAST)
  983.     ifp->if_omcasts++;
  984.  
  985.   splx(s);
  986.   return 0;
  987.  
  988.  bad:
  989.   if (req)
  990.     AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
  991.   ifp->if_oerrors++;
  992.  
  993.   splx(s);
  994.   if (m)
  995.     m_freem(m);
  996.   return error;
  997. }
  998.  
  999. /*
  1000.  * free_written_packet(): free mbufs of written packet,
  1001.  *                        queue IOrequest for reuse
  1002.  * (This routine is called from sana_poll)
  1003.  */
  1004. static void
  1005. free_written_packet(struct sana_softc *ssc, struct IOIPReq *req)
  1006. {
  1007.   spl_t s = splimp();
  1008.  
  1009.   if (req->ioip_packet) {
  1010.     m_freem(req->ioip_packet);
  1011.     req->ioip_packet = NULL;
  1012.   }
  1013.   req->ioip_dispatch = NULL;
  1014.   if (debug_sana && req->ioip_Error)
  1015.     sana2perror("sana_output", (struct IOSana2Req *)req);
  1016.   AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
  1017.   splx(s);
  1018. }
  1019.