Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / network / stacks / AROSTCP / bsdsocket / net / if_sana.c
blob4eb2fbf1df37ae09fce4d7ee590a20e554d5e81f
1 /*
2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
4 * All rights reserved.
5 * Copyright (C) 2005 - 2012 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
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,
19 * MA 02111-1307, USA.
23 #define DEBUG 0
24 #include <aros/debug.h>
26 #include <conf.h>
28 #include <exec/errors.h>
30 #include <sys/param.h>
31 #include <sys/cdefs.h>
32 #include <sys/malloc.h>
33 #include <sys/mbuf.h>
34 #include <sys/socket.h>
35 #include <sys/errno.h>
36 #include <sys/sockio.h>
37 #include <sys/systm.h>
38 #include <sys/syslog.h>
40 #include <kern/amiga_includes.h>
41 #include <kern/amiga_gui.h>
43 #include <sys/synch.h>
45 #include <net/if.h>
46 #include <net/netisr.h>
48 #define NDEBUG
49 #include <assert.h>
51 #if INET
52 #include <netinet/in.h>
53 #include <netinet/in_systm.h>
54 #include <netinet/in_var.h>
55 #include <netinet/ip.h>
56 #endif
58 #if NS
59 #include <netns/ns.h>
60 #include <netns/ns_if.h>
61 #endif
63 #include <net/if_sana.h>
64 #include <net/if_types.h>
65 #include <net/sana2arp.h>
67 #include <net/sana2config.h>
68 #include <net/sana2request.h>
69 #include <net/sana2errno.h>
71 #include <libraries/bsdsocket.h>
72 #include <libraries/miamipanel.h>
73 #include <proto/dos.h>
75 #define ARP_MTU (sizeof(struct s2_arppkt))
77 int debug_sana = 1;
79 /* Global port for all SANA-II network interfaces */
80 struct MsgPort *SanaPort = NULL;
82 /* queue for sana network interfaces */
83 struct sana_softc *ssq = NULL;
85 /* These are wire type dependant parameters of
86 * Sana-II Network Interface
88 //extern struct wiretype_parameters wiretype_table[];
90 /*
91 * Local prototypes
93 struct ifnet *iface_make(struct ssconfig *ifc);
94 static void sana_run(struct sana_softc *ssc, int requests, struct ifaddr *ifa);
95 static void sana_unrun(struct sana_softc *ssc);
96 static void sana_up(struct sana_softc *ssc);
97 static BOOL sana_down(struct sana_softc *ssc);
98 static struct mbuf *
99 sana_read(struct sana_softc *ssc, struct IOIPReq *req,
100 UWORD flags, UWORD *sent, const char *banner, size_t mtu);
101 static void sana_ip_read(struct sana_softc *ssc, struct IOIPReq *req);
102 static void sana_arp_read(struct sana_softc *ssc, struct IOIPReq *req);
103 static void sana_online(struct sana_softc *ssc, struct IOIPReq *req);
104 static void sana_connect(struct sana_softc *ssc, struct IOIPReq *req);
105 static void free_written_packet(struct sana_softc *ssc, struct IOIPReq *req);
106 static int sana_query(struct ifnet *ifn, struct TagItem *tag);
109 * Initialize Sana-II interface
111 * This routine creates needed message port for Sana-II IO
112 * It returns our signal mask, or 0L on an error.
114 ULONG
115 sana_init(void)
117 assert(!SanaPort);
119 SanaPort = CreateMsgPort(); /* V36 function, creates a PA_SIGNAL port */
121 if (SanaPort) {
122 SanaPort->mp_Node.ln_Name = (void *)"sana_if.port";
123 loattach();
124 return (ULONG) 1 << SanaPort->mp_SigBit;
127 return 0L;
131 * Clean up Sana-II Interfaces
133 * Note: main interface queue is SNAFU after deinitializing
135 void
136 sana_deinit(void)
138 struct sana_softc *ssc;
139 struct IOSana2Req *req;
141 assert(SanaPort);
143 while (ssq) {
144 sana_down(ssq);
145 if (ssq->ss_if.if_flags & IFF_RUNNING) {
146 sana_unrun(ssq);
148 ssc = ssq;
149 ssq = ssc->ss_next;
150 /* Close device */
151 req = CreateIOSana2Req(ssc);
152 if (req) {
153 CloseDevice((struct IORequest*)req);
154 DeleteIOSana2Req(req);
155 } else {
156 __log(LOG_ERR, "sana_deinit(): Couldn't close device %s\n",
157 ssc->ss_name);
161 if (SanaPort) {
162 /* Clear possible pending signals */
163 SetSignal(1<<SanaPort->mp_SigBit, 0L);
164 DeleteMsgPort(SanaPort);
165 SanaPort = NULL;
170 * sana_poll()
171 * This routine polls SanaPort and processes replied
172 * requests appropriately
174 BOOL
175 sana_poll(void)
177 struct IOIPReq * io;
178 spl_t s = splnet();
180 while (io = (struct IOIPReq *)GetMsg(SanaPort)) {
181 /* touch the network interface */
182 GetSysTime(&io->ioip_if->ss_if.if_lastchange);
183 if (io->ioip_dispatch) {
184 (*io->ioip_dispatch)(io->ioip_if, io);
185 } else {
186 __log(LOG_ERR, "No dispatch function in request for %s\n",
187 io->ioip_if->ss_name);
191 net_poll();
193 splx(s);
195 return FALSE;
198 #ifdef COMPAT_AMITCP2
200 * Name points to the full device name.
201 * Device name is a legal DOS file name,
202 * appended with a slash and a decimal unit number
204 * Some explanation on the device names:
205 * There is a DOS wrapper around Exec OpenDevice() function.
206 * The device is first searched from the Exec list, if that fails
207 * DOS tries to load the segment file with the device name.
208 * If that fails too, the filename is catenated to string "DEVS:" and
209 * DOS tries again.
211 * AmiTCP uses internally only the Exec device name (ie. device name
212 * without pathpart)
216 * Map exec device name to
217 * interface structure pointer.
219 struct ifnet *aifunit(register char *name)
221 register char *cp;
222 register struct ifnet *ifp;
223 long unit;
224 unsigned len;
225 char *ep, c;
227 /* AmigaTCP/IP uses the slash as unit number separator
228 * because Exec device name may contain digits.
230 char *up;
231 cp = ep = name - 1;
232 /* Find pathpart */
233 for (up = name; *up; up++)
234 if (*up == '/' || *up == ':') {
235 cp = ep;
236 ep = up;
238 /* Name is too long, or there is no unit number */
239 if (up >= cp + IFNAMSIZ || cp == ep)
240 return ((struct ifnet *)0);
241 cp++;
244 * cp points first char in device name,
245 * ep to unit number separator ('/')
246 * and up to NUL ('\0') at the end of string
248 len = ep - cp;
249 c = *ep;
250 *ep = '\0'; /* sentinel */
251 for (unit = 0, up--; *up >= '0' && *up <= '9'; up--)
252 unit = unit * 10 + *up - '0';
253 if (up != ep) {
254 *ep = c;
255 return NULL;
258 /* Pathpart is not included in search */
259 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
260 if (bcmp(ifp->if_name, cp, len))
261 continue;
262 if (unit == ifp->if_unit)
263 break;
266 extern struct ifnet *aiface_find(char *, long unit);
267 *ep = '\0'; /* sentinel */
268 if (ifp == 0)
269 ifp = aiface_find(name, unit);
270 *ep = c;
272 return (ifp);
275 struct ifnet *
276 aiface_find(char *name, long unit)
278 struct = sana2tag_find_exec(name, unit);
280 /* No alias found, use defaults */
281 if (sifp == NULL) {
282 static short sana_units = 0;
283 struct interface_parameters sifp[1];
284 const static long tag_end = TAG_END;
286 sifp->ifname = "sana";
287 sifp->unit = sana_units++;
288 sifp->execname = name;
289 sifp->execunit = unit;
290 sifp->tags = (struct TagItem *)&tag_end;
291 return make_iface(sifp, sifp->unit);
293 return make_iface(sifp, sifp->unit);
295 #endif
297 struct ifnet *
298 iface_make(struct ssconfig *ifc)
300 register struct sana_softc *ssc = NULL;
301 register struct IOSana2Req *req;
302 struct Sana2DeviceQuery devicequery;
304 /* Allocate the request for opening the device */
305 if ((req = CreateIOSana2Req(NULL)) == NULL)
307 __log(LOG_ERR, "iface_find(): CreateIOSana2Req failed\n");
309 else
311 req->ios2_BufferManagement = buffermanagement;
313 DSANA(__log(LOG_DEBUG,"Opening device %s unit %ld", ifc->args->a_dev, *ifc->args->a_unit);)
314 if (OpenDevice(ifc->args->a_dev, *ifc->args->a_unit,
315 (struct IORequest *)req, 0L))
317 sana2perror("OpenDevice", req);
319 /* Allocate the interface structure */
320 ssc = (struct sana_softc *)
321 bsd_malloc(sizeof(*ssc) + strlen(ifc->args->a_dev) + 1,
322 M_IFNET, M_WAITOK);
324 if (!ssc)
326 __log(LOG_ERR, "iface_find: out of memory\n");
328 else
330 aligned_bzero_const(ssc, sizeof(*ssc));
332 /* Save request pointers */
333 ssc->ss_dev = req->ios2_Req.io_Device;
334 ssc->ss_unit = req->ios2_Req.io_Unit;
336 ssc->ss_if.if_type = IFT_OTHER;
337 ssc->ss_if.if_flags &= ~(IFF_RUNNING|IFF_UP);
339 /* Initialize */
341 D(bug("[AROSTCP] if_sana.c: iface_make: Current IP from config = %s\n", ifc->args[0].a_ip));
342 ifc->args[0].a_ip = "0.0.0.0";
343 D(bug("[AROSTCP] if_sana.c: iface_make: IP set to 0.0.0.0\n"));
345 ssconfig(ssc, ifc);
347 NewList((struct List*)&ssc->ss_freereq);
349 if_attach((struct ifnet*)ssc);
350 ifinit();
352 ssc->ss_next = ssq;
353 ssq = ssc;
356 else
358 /* Ask for our type, address length, MTU
359 * Obl. bitch: nobody tells, WHO is supplying
360 * DevQueryFormat and DeviceLevel
362 req->ios2_Req.io_Command = S2_DEVICEQUERY;
363 req->ios2_StatData = &devicequery;
364 devicequery.SizeAvailable = sizeof(devicequery);
365 devicequery.DevQueryFormat = 0L;
367 DoIO((struct IORequest *)req);
368 if (req->ios2_Req.io_Error)
370 sana2perror("S2_DEVICEQUERY", req);
372 else
374 /* Get Our Station address */
375 req->ios2_StatData = NULL;
376 req->ios2_Req.io_Command = S2_GETSTATIONADDRESS;
377 DoIO((struct IORequest *)req);
379 if (req->ios2_Req.io_Error)
381 sana2perror("S2_GETSTATIONADDRESS", req);
383 else
385 req->ios2_Req.io_Command = 0;
387 /* Allocate the interface structure */
388 ssc = (struct sana_softc *)
389 bsd_malloc(sizeof(*ssc) + strlen(ifc->args->a_dev) + 1,
390 M_IFNET, M_WAITOK);
392 if (!ssc)
394 __log(LOG_ERR, "iface_find: out of memory\n");
396 else
398 aligned_bzero_const(ssc, sizeof(*ssc));
400 /* Save request pointers */
401 ssc->ss_dev = req->ios2_Req.io_Device;
402 ssc->ss_unit = req->ios2_Req.io_Unit;
403 ssc->ss_bufmgnt = req->ios2_BufferManagement;
405 /* Address must be full bytes */
406 ssc->ss_if.if_addrlen = (devicequery.AddrFieldSize + 7) >> 3;
407 bcopy(req->ios2_DstAddr, ssc->ss_hwaddr, ssc->ss_if.if_addrlen);
408 ssc->ss_if.if_mtu = devicequery.MTU;
409 ssc->ss_maxmtu = devicequery.MTU;
410 ssc->ss_if.if_baudrate = devicequery.BPS;
411 ssc->ss_hwtype = devicequery.HardwareType;
413 /* These might be different on different hwtypes */
414 ssc->ss_if.if_output = sana_output;
415 ssc->ss_if.if_ioctl = sana_ioctl;
416 ssc->ss_if.if_query = sana_query;
418 /* Map SANA-II hardware types to RFC1573 standard */
419 switch (ssc->ss_hwtype)
421 case S2WireType_Ethernet:
422 ssc->ss_if.if_type = IFT_ETHER;
423 break;
424 case S2WireType_IEEE802:
425 ssc->ss_if.if_type = IFT_IEEE80211;
426 break;
427 case S2WireType_Arcnet:
428 ssc->ss_if.if_type = IFT_ARCNET;
429 break;
430 case S2WireType_LocalTalk:
431 ssc->ss_if.if_type = IFT_LOCALTALK;
432 break;
433 case S2WireType_PPP:
434 ssc->ss_if.if_type = IFT_PPP;
435 break;
436 case S2WireType_SLIP:
437 case S2WireType_CSLIP:
438 ssc->ss_if.if_type = IFT_SLIP;
439 break;
440 case S2WireType_PLIP:
441 ssc->ss_if.if_type = IFT_PARA;
442 break;
443 default:
444 ssc->ss_if.if_type = IFT_OTHER;
447 /* Initialize */
448 ssconfig(ssc, ifc);
450 NewList((struct List*)&ssc->ss_freereq);
452 if_attach((struct ifnet*)ssc);
453 ifinit();
455 ssc->ss_next = ssq;
456 ssq = ssc;
460 if (!ssc)
461 CloseDevice((struct IORequest *)req);
463 DeleteIOSana2Req(req);
466 return (struct ifnet *)ssc;
470 * Allocate Sana-II IORequests for TCP/IP process
472 static void
473 sana_run(struct sana_softc *ssc, int requests, struct ifaddr *ifa)
475 int i;
476 spl_t s = splimp();
477 struct IOIPReq *req, *next = ssc->ss_reqs;
479 DSANA(__log(LOG_DEBUG,"sana_run(%s%d) called",ssc->ss_if.if_name, ssc->ss_if.if_unit);)
481 * Configure the Sana-II device driver
482 * (now with factory address)
484 if ((ssc->ss_if.if_flags & IFF_RUNNING) == 0) {
485 struct IOSana2Req *req;
487 if (req = CreateIOSana2Req(ssc)) {
488 req->ios2_Req.io_Command = S2_CONFIGINTERFACE;
489 bcopy(ssc->ss_hwaddr, req->ios2_SrcAddr, ssc->ss_if.if_addrlen);
491 DoIO((struct IORequest*)req);
493 if (req->ios2_Req.io_Error == 0 ||
494 req->ios2_WireError == S2WERR_IS_CONFIGURED) {
495 /* Mark us as running */
496 ssc->ss_if.if_flags |= IFF_RUNNING;
497 if (ssc->ss_cflags & SSF_TRACK) {
498 #ifdef INET
499 /* Ask for packet type specific statistics */
500 req->ios2_Req.io_Command = S2_TRACKTYPE;
501 req->ios2_PacketType = ssc->ss_ip.type;
502 DoIO((struct IORequest*)req);
503 /* It is *not* safe to turn tracking off */
504 if (req->ios2_Req.io_Error &&
505 req->ios2_WireError != S2WERR_ALREADY_TRACKED)
506 sana2perror("S2_TRACKTYPE for IP", req);
507 if (ssc->ss_arp.reqno) {
508 req->ios2_Req.io_Command = S2_TRACKTYPE;
509 req->ios2_PacketType = ssc->ss_arp.type;
510 DoIO((struct IORequest*)req);
511 if (req->ios2_Req.io_Error &&
512 req->ios2_WireError != S2WERR_ALREADY_TRACKED)
513 sana2perror("S2_TRACKTYPE for ARP", req);
515 #endif
518 else
520 sana2perror("S2_CONFIGINTERFACE", req);
522 DeleteIOSana2Req(req);
526 if ((ssc->ss_if.if_flags & IFF_RUNNING)) {
527 /* Initialize ioRequests, add them into free queue */
528 for (i = 0; i < requests ; i++) {
529 if (!(req = CreateIORequest(SanaPort, sizeof(*req)))) break;
530 req->ioip_s2.ios2_Req.io_Device = ssc->ss_dev;
531 req->ioip_s2.ios2_Req.io_Unit = ssc->ss_unit;
532 req->ioip_s2.ios2_BufferManagement = ssc->ss_bufmgnt;
533 aligned_bcopy(ssc->ss_hwaddr, req->ioip_s2.ios2_SrcAddr, ssc->ss_if.if_addrlen);
534 req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
535 req->ioip_s2.ios2_Data = req;
536 req->ioip_if = ssc;
537 req->ioip_next = next;
538 AddTail((struct List*)&ssc->ss_freereq, (struct Node*)req);
539 next = req;
541 ssc->ss_reqs = next;
543 /* Order a notify when driver connects to a (wireless) network */
544 if (ssc->ss_if.if_data.ifi_aros_usedhcp == 1) {
545 if ((req = CreateIORequest(SanaPort, sizeof(*req))) != NULL) {
546 ssc->ss_eventsent++;
547 req->ioip_s2.ios2_Req.io_Device = ssc->ss_dev;
548 req->ioip_s2.ios2_Req.io_Unit = ssc->ss_unit;
549 req->ioip_s2.ios2_BufferManagement = ssc->ss_bufmgnt;
550 req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
551 req->ioip_if = ssc;
552 req->ioip_next = NULL;
553 req->ioip_s2.ios2_Req.io_Command = S2_ONEVENT;
554 req->ioip_s2.ios2_WireError = S2EVENT_OFFLINE | S2EVENT_CONNECT;
555 req->ioip_dispatch = sana_connect;
556 BeginIO((struct IORequest *)req);
557 ssc->ss_connectreq = req;
561 splx(s);
565 * Free Sana-II IO Requests
566 * Note: this is protected by splimp();
568 static void
569 sana_unrun(struct sana_softc *ssc)
571 struct IOIPReq *req, *next;
573 for ( next = ssc->ss_reqs; req = next ;) {
574 next = req -> ioip_next;
575 WaitIO((struct IORequest *)req);
576 DeleteIORequest((struct IORequest *)req);
578 ssc->ss_reqs = next;
580 WaitIO((struct IORequest *)ssc->ss_connectreq);
581 DeleteIORequest((struct IORequest *)ssc->ss_connectreq);
583 ssc->ss_if.if_flags &= ~IFF_RUNNING;
587 * Generic SANA-II interface ioctl
589 * Interface setup is thru IOCTL.
591 int
592 sana_ioctl(register struct ifnet *ifp, int cmd, caddr_t data)
594 register struct sana_softc *ssc = (struct sana_softc*)ifp;
595 register struct ifaddr *ifa = (struct ifaddr *)data;
596 register struct ifreq *ifr = (struct ifreq *)data;
598 spl_t s = splimp();
599 int error = 0;
601 D(bug("[ATCP-SANA] sana_ioctl()\n"));
603 switch (cmd) {
605 case SIOCSIFFLAGS:
606 D(bug("[ATCP-SANA] sana_ioctl: SIOCSIFFLAGS - \n"));
608 if (((ifr->ifr_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) && ((ssc->ss_if.if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING))
610 D(bug("[ATCP-SANA] sana_ioctl: SIFFLAGS bringing interface up .. \n"));
611 sana_up(ssc);
613 /* Call sana_down() in every case */
614 if ((ifr->ifr_flags & IFF_UP) == 0)
616 D(bug("[ATCP-SANA] sana_ioctl: SIFFLAGS bringing interface DOWN .. \n"));
617 sana_down(ssc);
619 if ((ifr->ifr_flags & IFF_NOARP) == 0)
621 D(bug("[ATCP-SANA] sana_ioctl: SIFFLAGS Allocating interface ARP tables .. \n"));
622 alloc_arptable(ssc, 0);
624 break;
627 * Set interface address (and mark interface up).
629 case SIOCSIFADDR: /* Set Interface Address */
630 D(bug("[ATCP-SANA] sana_ioctl: SIOCSIFADDR - Set Interface Address\n"));
631 if (!(ssc->ss_if.if_flags & IFF_RUNNING))
633 D(bug("[ATCP-SANA] sana_ioctl: SIFADDR set interface as running .. \n"));
634 sana_run(ssc, ssc->ss_reqno, ifa);
636 if ((ssc->ss_if.if_flags & IFF_RUNNING) && !(ssc->ss_if.if_flags & IFF_UP)) {
637 if (ssc->ss_if.if_flags & IFF_NOUP)
639 D(bug("[ATCP-SANA] sana_ioctl: SIFADDR Clearing interface NOUP flag .. \n"));
640 ssc->ss_if.if_flags &= ~IFF_NOUP;
642 else
644 D(bug("[ATCP-SANA] sana_ioctl: SIFADDR bringing interface UP .. \n"));
645 sana_up(ssc);
648 if ((ssc->ss_if.if_flags & IFF_NOARP) == 0)
650 D(bug("[ATCP-SANA] sana_ioctl: SIFADDR Allocating interface ARP tables .. \n"));
651 alloc_arptable(ssc, 0);
654 case SIOCAIFADDR: /* Alter Interface Address */
655 D(bug("[ATCP-SANA] sana_ioctl: SIOCAIFADDR - Alter Interface Address\n"));
656 switch (ifa->ifa_addr->sa_family) {
657 #if INET
658 case AF_INET:
659 ssc->ss_ipaddr = IA_SIN(ifa)->sin_addr;
660 break;
661 #endif
663 break;
665 case SIOCSIFDSTADDR: /* Sets P-P-link destination address */
666 D(bug("[ATCP-SANA] sana_ioctl: SIOCSIFDSTADDR - [*] Set P-P-link destination address\n"));
667 break;
669 default:
670 D(bug("[ATCP-SANA] sana_ioctl: UNKNOWN SIOC\n"));
671 error = EINVAL;
672 break;
674 splx(s);
675 return (error);
679 * sana_send_read():
680 * send read requests with given types, dispatcher & c
681 * MUST be called at splimp()
683 static inline WORD
684 sana_send_read(struct sana_softc *ssc, WORD count, ULONG type, ULONG mtu,
685 void (*dispatch)(struct sana_softc *, struct IOIPReq *),
686 UWORD command, UBYTE flags)
688 struct IOIPReq *req = NULL;
689 WORD i;
691 for (i = 0; i < count; i++) {
692 if (!(req = (struct IOIPReq*)RemHead((struct List*)&ssc->ss_freereq)))
693 return i;
694 req->ioip_dispatch = dispatch;
695 req->ioip_s2.ios2_PacketType = type;
696 req->ioip_Command = command;
697 req->ioip_s2.ios2_Req.io_Flags = flags;
698 if (!ioip_alloc_mbuf(req, mtu))
699 goto no_resources;
700 BeginIO((struct IORequest*)req);
702 return i;
704 no_resources:
705 if (req)
706 AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
707 __log(LOG_ERR, "sana_send_read: could not queue enough read requests\n");
708 return i;
712 * Called when interface goes online
714 static void
715 sana_restore(struct sana_softc *ssc)
717 spl_t s;
718 struct timeval now;
720 DSANA(__log(LOG_DEBUG,"sana_restore(%s%d) called", ssc->ss_if.if_name, ssc->ss_if.if_unit);)
721 D(bug("[ATCP-SANA] sana_restore('%s%d')\n", ssc->ss_if.if_name, ssc->ss_if.if_unit));
723 s = splimp();
724 ssc->ss_if.if_flags |= IFF_UP;
725 GetSysTime(&now);
726 ssc->ss_if.if_data.ifi_aros_ontime.tv_secs = now.tv_secs;
727 ssc->ss_if.if_data.ifi_aros_ontime.tv_micro = now.tv_micro;
728 ssc->ss_if.if_data.ifi_aros_lasttotal = ssc->ss_if.if_ibytes + ssc->ss_if.if_obytes;
729 gui_set_interface_state(&ssc->ss_if, MIAMIPANELV_AddInterface_State_Online);
730 /* Send read requests to device driver */
731 #if INET
732 /* IP */
733 ssc->ss_ip.sent +=
734 sana_send_read(ssc, ssc->ss_ip.reqno - ssc->ss_ip.sent, ssc->ss_ip.type,
735 ssc->ss_if.if_mtu, sana_ip_read, CMD_READ, 0);
737 ssc->ss_arp.sent +=
738 sana_send_read(ssc, ssc->ss_arp.reqno - ssc->ss_arp.sent, ssc->ss_arp.type,
739 ARP_MTU, sana_arp_read, CMD_READ, 0);
741 #endif /* INET */
742 #if ISO
743 #endif /* ISO */
744 #if CCITT
745 #endif /* CCITT */
746 #if NS
747 #endif /* NS */
748 #if 0
749 ssc->ss_rawsent +=
750 sana_send_read(ssc, ssc->ss_rawreqno - ssc->ss_rawsent, 0,
751 ssc->ss_if.if_mtu, sana_raw_read,
752 S2_READORPHAN, SANA2_IOF_RAW);
753 #endif
754 splx(s);
755 return;
759 * sana_up():
760 * send read requests
762 static void
763 sana_up(struct sana_softc *ssc)
765 struct IOSana2Req *req;
766 DSANA(__log(LOG_DEBUG,"sana_up(%s%d) called", ssc->ss_if.if_name, ssc->ss_if.if_unit);)
767 D(bug("[ATCP-SANA] sana_up('%s%d')\n", ssc->ss_if.if_name, ssc->ss_if.if_unit));
769 gui_set_interface_state(&ssc->ss_if, MIAMIPANELV_AddInterface_State_GoingOnline);
771 if (req = CreateIOSana2Req(ssc))
773 req->ios2_Req.io_Command = S2_ONLINE;
774 req->ios2_Req.io_Error = S2ERR_NO_ERROR;
776 DoIO((struct IORequest*)req);
778 if ((req->ios2_Req.io_Error) && (req->ios2_WireError != S2WERR_UNIT_ONLINE)) {
779 sana2perror("S2_ONLINE", req);
780 gui_set_interface_state(&ssc->ss_if, MIAMIPANELV_AddInterface_State_Offline);
781 } else {
782 __log(LOG_NOTICE, "%s%d is now online.", ssc->ss_name, ssc->ss_if.if_unit);
783 sana_restore(ssc);
785 DeleteIOSana2Req(req);
789 #if __SASC
791 * "Fix" for numerous sana2 drivers, which expect to get Unit * in the
792 * register A3 when their AbortIO function is called.
793 * Note that Exec AbortIO() does NOT put it there.
795 extern VOID _AbortSanaIO(struct IORequest *, struct Unit *);
796 #pragma libcall DeviceBase _AbortSanaIO 24 B902
798 static inline __asm VOID
799 AbortSanaIO(register __a1 struct IORequest *ioRequest)
801 #define DeviceBase ioRequest->io_Device
802 _AbortSanaIO(ioRequest, ioRequest->io_Unit);
803 #undef DeviceBase
805 #else /* implement later for other compilers */
806 #define AbortSanaIO AbortIO
807 #endif
810 * sana_down(): Mark interface as down, abort all pending requests
812 static BOOL
813 sana_down(struct sana_softc *ssc)
815 struct IOSana2Req * sreq;
816 spl_t s = splimp();
817 struct IOIPReq *req = ssc->ss_reqs;
818 BOOL success;
820 DSANA(__log(LOG_DEBUG,"sana_down(%s%d) called", ssc->ss_if.if_name, ssc->ss_if.if_unit);)
821 gui_set_interface_state(&ssc->ss_if, MIAMIPANELV_AddInterface_State_GoingOffline);
822 /* Completed, Remove()'d requests are not aborted */
823 while (req) {
824 if (!CheckIO((struct IORequest*)req)) {
825 AbortSanaIO((struct IORequest*)req);
827 req = req->ioip_next;
829 if (ssc->ss_dev && (ssc->ss_dev->dd_Library.lib_OpenCnt == 1)) {
830 if (sreq = CreateIOSana2Req(ssc)) {
831 sreq->ios2_Req.io_Command = S2_OFFLINE;
833 DoIO((struct IORequest*)sreq);
834 if (sreq->ios2_Req.io_Error) {
835 sana2perror("S2_OFFLINE", sreq);
836 success = FALSE;
838 else
839 success = TRUE;
840 DeleteIOSana2Req(sreq);
842 } else
843 success = TRUE;
844 if (success) {
845 __log(LOG_NOTICE, "%s%d is now offline.", ssc->ss_name, ssc->ss_if.if_unit);
846 gui_set_interface_state(&ssc->ss_if, MIAMIPANELV_AddInterface_State_Offline);
847 } else
848 gui_set_interface_state(&ssc->ss_if, MIAMIPANELV_AddInterface_State_Online);
850 splx(s);
852 return(TRUE);
856 * sana_read: deattach a packet from IORequest
857 * resend the IORequest
859 static struct mbuf *
860 sana_read(struct sana_softc *ssc, struct IOIPReq *req,
861 UWORD flags, UWORD *sent, const char *banner, size_t mtu)
863 register struct mbuf *m = req->ioip_packet;
864 register spl_t s = splimp();
866 req->ioip_packet = NULL;
868 switch (req->ioip_Error) {
869 case 0:
870 if (req->ioip_s2.ios2_Req.io_Flags & SANA2IOF_BCAST)
871 m->m_flags |= M_BCAST;
872 if (req->ioip_s2.ios2_Req.io_Flags & SANA2IOF_MCAST)
873 m->m_flags |= M_MCAST;
874 ssc->ss_if.if_ibytes += req->ioip_s2.ios2_DataLength;
875 break;
876 case S2ERR_OUTOFSERVICE:
878 * Somebody put Sana-II driver offline.
879 * We put down also the network interface
881 if (ssc->ss_if.if_flags & IFF_UP) {
882 /* Show a log message */
883 sana2perror(ssc->ss_if.if_name, (struct IOSana2Req *)req);
885 /* tell it to protocols */
886 if_down((struct ifnet *)ssc);
888 /* Free mbufs allocated for packet */
889 m_freem(req->ioip_reserved);
890 req->ioip_reserved = NULL;
892 /* Order an notify when driver is put back online */
893 ssc->ss_eventsent++;
894 req->ioip_s2.ios2_Req.io_Command = S2_ONEVENT;
895 req->ioip_s2.ios2_WireError = S2EVENT_ONLINE;
896 req->ioip_dispatch = sana_online;
897 BeginIO((struct IORequest *)req);
898 req = NULL;
899 ssc->ss_if.if_flags &= ~IFF_UP;
900 gui_set_interface_state(&ssc->ss_if, MIAMIPANELV_AddInterface_State_Offline);
902 m_freem(m);
903 m = NULL;
904 break;
905 default:
906 if (debug_sana && req->ioip_Error != IOERR_ABORTED)
907 sana2perror(banner, (struct IOSana2Req *)req);
908 m_freem(m);
909 m = NULL;
912 if (ssc->ss_if.if_flags & IFF_UP) {
913 /* Return request to the Sana-II driver */
914 if (ioip_alloc_mbuf(req, mtu)) {
915 req->ioip_s2.ios2_Req.io_Flags = flags;
916 BeginIO((struct IORequest*)req);
917 splx(s);
918 return m;
920 __log(LOG_ERR, "sana_read (%s): not enough mbufs\n", ssc->ss_name);
923 /* do not resend, free used resources */
924 (*sent)--;
925 if (req) {
926 m_freem(req->ioip_reserved);
927 req->ioip_reserved = NULL;
928 req->ioip_dispatch = NULL;
929 AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
932 if (m) {
933 m_freem(m);
936 splx(s);
937 return NULL;
941 * sana_ip_read(): feed a packet to the IP queue
942 * (This routine is called from sana_poll)
944 static void
945 sana_ip_read(struct sana_softc *ssc, struct IOIPReq *req)
947 struct mbuf *m = sana_read(ssc, req, 0, &ssc->ss_ip.sent, "sana_ip_read",
948 ssc->ss_if.if_mtu);
949 spl_t s;
951 if (m) {
952 s = splimp();
953 if (IF_QFULL(&ipintrq)) {
954 IF_DROP(&ipintrq);
955 m_freem(m);
956 /* m = NULL; */
957 } else {
958 /* Set interface pointer (needed for broadcasts) */
959 m->m_pkthdr.rcvif = (struct ifnet *)ssc;
960 IF_ENQUEUE(&ipintrq, m);
961 /* A signal might be needed if we use PA_EXCEPTION port */
962 schednetisr_nosignal(NETISR_IP);
963 /* m = NULL; */
965 splx(s);
970 * sana_arp_read(): process an ARP packet
971 * (This routine is called from sana_poll)
973 static void
974 sana_arp_read(struct sana_softc *ssc, struct IOIPReq *req)
976 struct mbuf *m;
977 UBYTE hwaddr[MAXADDRSANA];
979 bcopy(req->ioip_s2.ios2_SrcAddr, hwaddr, ssc->ss_if.if_addrlen);
981 m = sana_read(ssc, req, 0, &ssc->ss_arp.sent, "sana_arp_read", ARP_MTU);
983 if (m)
984 arpinput(ssc, m, hwaddr);
988 * sana_online(): process an ONLINE event
990 static void
991 sana_online(struct sana_softc *ssc, struct IOIPReq *req)
993 LONG events = req->ioip_s2.ios2_WireError;
995 if (req->ioip_s2.ios2_Req.io_Error == 0 &&
996 events & S2EVENT_ONLINE) {
997 ssc->ss_eventsent--;
998 req->ioip_dispatch = NULL;
999 AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
1000 __log(LOG_NOTICE, "%s is online again.", ssc->ss_name);
1001 sana_restore(ssc);
1002 return;
1005 /* An error? */
1006 if (debug_sana && req->ioip_Error != IOERR_ABORTED) {
1007 sana2perror("sana_online", (struct IOSana2Req *)req);
1008 req->ioip_s2.ios2_Req.io_Command = S2_ONEVENT;
1009 req->ioip_s2.ios2_WireError = S2EVENT_ONLINE;
1010 BeginIO((struct IORequest *)req);
1011 } else {
1012 /* Aborted -- probably because "ifconfig xxx/0 down" */
1013 ssc->ss_eventsent--;
1014 req->ioip_dispatch = NULL;
1015 AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
1020 * sana_online(): process a CONNECT event
1022 static void
1023 sana_connect(struct sana_softc *ssc, struct IOIPReq *req)
1025 LONG events = req->ioip_s2.ios2_WireError;
1027 if (req->ioip_s2.ios2_Req.io_Error == 0 &&
1028 events == S2EVENT_CONNECT) {
1030 /* New network -> new address */
1031 kill_dhclient((struct ifnet *) ssc);
1032 run_dhclient((struct ifnet *) ssc);
1035 /* Send request back for next event */
1036 if (req->ioip_s2.ios2_Req.io_Error == 0 && !(events & S2EVENT_OFFLINE)) {
1037 req->ioip_s2.ios2_Req.io_Command = S2_ONEVENT;
1038 req->ioip_s2.ios2_WireError = S2EVENT_OFFLINE | S2EVENT_CONNECT;
1039 BeginIO((struct IORequest *)req);
1040 } else {
1041 ssc->ss_eventsent--;
1046 * sana_output: send a packet to Sana-II driver
1049 sana_output(struct ifnet *ifp, struct mbuf *m0,
1050 struct sockaddr *dst, struct rtentry *rt)
1052 register struct sana_softc *ssc = (struct sana_softc *)ifp;
1053 ULONG type;
1054 int error = 0;
1055 struct in_addr idst;
1057 /* If a broadcast, send a copy to ourself too */
1058 struct mbuf *mcopy = (struct mbuf *)NULL;
1059 struct IOIPReq *req = NULL;
1060 register struct mbuf *m = m0;
1062 int len = m->m_pkthdr.len;
1063 spl_t s = splimp();
1065 ifp->if_opackets++; /* stats */
1067 /* Check if we are up and running... */
1068 if ((ssc->ss_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
1069 error = ENETDOWN;
1070 goto bad;
1073 GetSysTime(&ssc->ss_if.if_lastchange);
1075 /* Get a free Sana-II IO request */
1076 if (!(req = (struct IOIPReq*)RemHead((struct List*)&ssc->ss_freereq))) {
1077 error = ENOBUFS;
1078 goto bad;
1081 req->ioip_s2.ios2_Req.io_Flags = 0;
1083 switch (dst->sa_family) {
1084 #if INET
1085 case AF_INET:
1086 idst = ((struct sockaddr_in *)dst)->sin_addr;
1088 /* If the address is not resolved, arpresolve
1089 * stores the packet to its private queue for
1090 * later transmit and broadcasts the resolve
1091 * request packet to the (ether)net.
1092 * (Now ARP works only with IP and ethernet.)
1094 if ((ssc->ss_if.if_flags & IFF_NOARP) != IFF_NOARP &&
1095 /* ssc = network interface
1096 * m = Packet to send
1097 * idst = destination IP address
1098 * ios2_DestAddr = destination hw address
1099 * error = error return
1101 !arpresolve(ssc, m, &idst, req->ioip_s2.ios2_DstAddr, &error)) {
1102 AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
1103 splx(s);
1104 return (0);
1106 type = ssc->ss_ip.type;
1108 /* Send to loopback if we do not hear our broadcasts */
1109 if ((ssc->ss_if.if_flags & IFF_SIMPLEX) && (m->m_flags & M_BCAST)) {
1110 mcopy = m_copy(m, 0, (int)M_COPYALL);
1111 (void) looutput(&ssc->ss_if, mcopy, dst, rt);
1113 /* Set the message priority */
1114 req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Pri =
1115 (IPTOS_LOWDELAY & mtod(m, struct ip *)->ip_tos) ?
1116 1 : 0;
1117 break;
1118 #endif
1119 #if NS
1120 #error NS unimplemented!!!
1121 case AF_NS:
1122 type = ssc->ss_nstype;
1123 /* There is hardware address straight in socket */
1124 /* Dunno how this works, if we have a P-to-P device */
1125 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
1126 (caddr_t)req->ioip_s2.ios2_DestAddr, ssc->ss_if.if_addrlen);
1127 /* Local send */
1128 if (!bcmp((caddr_t)req->ioip_s2.ios2_DestAddr,
1129 (caddr_t)&ns_thishost, ssc->ss_if.if_addrlen)) {
1130 AddHead(&ssc->ss_freereq, req);
1131 return (looutput(ifp, m, dst, rt));
1133 req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Pri = 0;
1134 break;
1135 #endif
1136 case AF_UNSPEC:
1137 /* Raw packets. Sana-II address (a tuple of type and host)
1138 * specifies the destination
1140 if (type = ((struct sockaddr_sana2*)dst)->ss2_type) {
1141 bcopy(((struct sockaddr_sana2*)dst)->ss2_host,
1142 req->ioip_s2.ios2_DstAddr,
1143 ssc->ss_if.if_addrlen);
1144 } else {
1145 req->ioip_s2.ios2_Req.io_Flags = SANA2IOF_RAW;
1146 type = 0L;
1148 req->ioip_s2.ios2_Req.io_Message.mn_Node.ln_Pri = 0;
1149 break;
1151 #if ISO
1152 #endif /* ISO */
1153 #if RMP
1154 case AF_RMP:
1155 #endif
1157 default:
1158 __log(LOG_ERR, "%s%ld: can't handle af%ld\n",
1159 ssc->ss_if.if_name, ssc->ss_if.if_unit, dst->sa_family);
1160 error = EAFNOSUPPORT;
1161 goto bad;
1165 * Queue packet to Sana-II driver
1167 req->ioip_Command = (m->m_flags & M_BCAST) ? S2_BROADCAST : CMD_WRITE;
1168 req->ioip_dispatch = free_written_packet;
1169 req->ioip_packet = m;
1170 req->ioip_s2.ios2_PacketType = type;
1171 req->ioip_s2.ios2_DataLength = len;
1173 BeginIO((struct IORequest*)req);
1175 /* These statistics are somewhat redundant */
1176 ifp->if_obytes += len;
1177 if (m->m_flags & M_BCAST)
1178 ifp->if_omcasts++;
1180 splx(s);
1181 return 0;
1183 bad:
1184 if (req)
1185 AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
1186 ifp->if_oerrors++;
1188 splx(s);
1189 if (m)
1190 m_freem(m);
1191 return error;
1195 * free_written_packet(): free mbufs of written packet,
1196 * queue IOrequest for reuse
1197 * (This routine is called from sana_poll)
1199 static void
1200 free_written_packet(struct sana_softc *ssc, struct IOIPReq *req)
1202 spl_t s = splimp();
1204 if (req->ioip_packet) {
1205 m_freem(req->ioip_packet);
1206 req->ioip_packet = NULL;
1208 req->ioip_dispatch = NULL;
1209 if (debug_sana && req->ioip_Error)
1210 sana2perror("sana_output", (struct IOSana2Req *)req);
1211 AddHead((struct List*)&ssc->ss_freereq, (struct Node*)req);
1212 splx(s);
1216 * SANA-II-dependent part of QueryInterfaceTagList()
1218 static int sana_query(struct ifnet *ifn, struct TagItem *tag)
1220 struct sana_softc *ssc = (struct sana_softc *)ifn;
1222 switch (tag->ti_Tag)
1224 case IFQ_DeviceName:
1225 *((STRPTR *)tag->ti_Data) = ssc->ss_execname;
1226 break;
1227 case IFQ_DeviceUnit:
1228 *((ULONG *)tag->ti_Data) = ssc->ss_execunit;
1229 break;
1230 case IFQ_HardwareAddress: /* Temporary, we should extract it from if_addrlist instead */
1231 memcpy((void *)tag->ti_Data, ssc->ss_hwaddr, ssc->ss_if.if_addrlen);
1232 break;
1233 case IFQ_HardwareType:
1234 *((ULONG *)tag->ti_Data) = ssc->ss_hwtype;
1235 break;
1236 case IFQ_NumReadRequests:
1237 __log(LOG_CRIT, "IFQ_NumReadRequests is not implemented");
1238 return -1;
1239 /* *((LONG *)tag->ti_Data) = *** TODO ***
1240 break;*/
1241 case IFQ_MaxReadRequests:
1242 __log(LOG_CRIT, "IFQ_MaxReadRequests is not implemented");
1243 return -1;
1244 /* *((LONG *)tag->ti_Data) =
1245 break;*/
1246 case IFQ_NumWriteRequests:
1247 __log(LOG_CRIT, "IFQ_NumWriteRequests is not implemented");
1248 return -1;
1249 /* *((LONG *)tag->ti_Data) =
1250 break;*/
1251 case IFQ_MaxWriteRequests:
1252 __log(LOG_CRIT, "IFQ_MaxWriteRequests is not implemented");
1253 return -1;
1254 /* *((LONG *)tag->ti_Data) =
1255 break;*/
1256 case IFQ_GetDebugMode:
1257 *((LONG *)tag->ti_Data) = debug_sana;
1258 break;
1259 case IFQ_GetSANA2CopyStats:
1260 __log(LOG_CRIT, "IFQ_GetSANA2CopyStats is not implemented");
1261 return -1;
1262 /* (struct Sana2CopyStats *)tag->ti_Data
1263 break;*/
1264 case IFQ_NumReadRequestsPending:
1265 __log(LOG_CRIT, "IFQ_NumReadRequestsPending is not implemented");
1266 return -1;
1267 /* *((LONG *)tag->ti_Data =
1268 break;*/
1269 case IFQ_NumWriteRequestsPending:
1270 __log(LOG_CRIT, "IFQ_NumWriteRequestsPending is not implemented");
1271 return -1;
1272 /* *((LONG *)tag->ti_Data =
1273 break;*/
1274 default:
1275 return -1;
1277 return 0;