2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
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,
24 #include <aros/debug.h>
28 #include <exec/errors.h>
30 #include <sys/param.h>
31 #include <sys/cdefs.h>
32 #include <sys/malloc.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>
46 #include <net/netisr.h>
52 #include <netinet/in.h>
53 #include <netinet/in_systm.h>
54 #include <netinet/in_var.h>
55 #include <netinet/ip.h>
60 #include <netns/ns_if.h>
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))
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[];
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
);
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.
119 SanaPort
= CreateMsgPort(); /* V36 function, creates a PA_SIGNAL port */
122 SanaPort
->mp_Node
.ln_Name
= (void *)"sana_if.port";
124 return (ULONG
) 1 << SanaPort
->mp_SigBit
;
131 * Clean up Sana-II Interfaces
133 * Note: main interface queue is SNAFU after deinitializing
138 struct sana_softc
*ssc
;
139 struct IOSana2Req
*req
;
145 if (ssq
->ss_if
.if_flags
& IFF_RUNNING
) {
151 req
= CreateIOSana2Req(ssc
);
153 CloseDevice((struct IORequest
*)req
);
154 DeleteIOSana2Req(req
);
156 __log(LOG_ERR
, "sana_deinit(): Couldn't close device %s\n",
162 /* Clear possible pending signals */
163 SetSignal(1<<SanaPort
->mp_SigBit
, 0L);
164 DeleteMsgPort(SanaPort
);
171 * This routine polls SanaPort and processes replied
172 * requests appropriately
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
);
186 __log(LOG_ERR
, "No dispatch function in request for %s\n",
187 io
->ioip_if
->ss_name
);
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
211 * AmiTCP uses internally only the Exec device name (ie. device name
216 * Map exec device name to
217 * interface structure pointer.
219 struct ifnet
*aifunit(register char *name
)
222 register struct ifnet
*ifp
;
227 /* AmigaTCP/IP uses the slash as unit number separator
228 * because Exec device name may contain digits.
233 for (up
= name
; *up
; up
++)
234 if (*up
== '/' || *up
== ':') {
238 /* Name is too long, or there is no unit number */
239 if (up
>= cp
+ IFNAMSIZ
|| cp
== ep
)
240 return ((struct ifnet
*)0);
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
250 *ep
= '\0'; /* sentinel */
251 for (unit
= 0, up
--; *up
>= '0' && *up
<= '9'; up
--)
252 unit
= unit
* 10 + *up
- '0';
258 /* Pathpart is not included in search */
259 for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
) {
260 if (bcmp(ifp
->if_name
, cp
, len
))
262 if (unit
== ifp
->if_unit
)
266 extern struct ifnet
*aiface_find(char *, long unit
);
267 *ep
= '\0'; /* sentinel */
269 ifp
= aiface_find(name
, unit
);
276 aiface_find(char *name
, long unit
)
278 struct = sana2tag_find_exec(name
, unit
);
280 /* No alias found, use defaults */
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
);
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");
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,
326 __log(LOG_ERR
, "iface_find: out of memory\n");
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
);
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"));
347 NewList((struct List
*)&ssc
->ss_freereq
);
349 if_attach((struct ifnet
*)ssc
);
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
);
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
);
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,
394 __log(LOG_ERR
, "iface_find: out of memory\n");
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
;
424 case S2WireType_IEEE802
:
425 ssc
->ss_if
.if_type
= IFT_IEEE80211
;
427 case S2WireType_Arcnet
:
428 ssc
->ss_if
.if_type
= IFT_ARCNET
;
430 case S2WireType_LocalTalk
:
431 ssc
->ss_if
.if_type
= IFT_LOCALTALK
;
434 ssc
->ss_if
.if_type
= IFT_PPP
;
436 case S2WireType_SLIP
:
437 case S2WireType_CSLIP
:
438 ssc
->ss_if
.if_type
= IFT_SLIP
;
440 case S2WireType_PLIP
:
441 ssc
->ss_if
.if_type
= IFT_PARA
;
444 ssc
->ss_if
.if_type
= IFT_OTHER
;
450 NewList((struct List
*)&ssc
->ss_freereq
);
452 if_attach((struct ifnet
*)ssc
);
461 CloseDevice((struct IORequest
*)req
);
463 DeleteIOSana2Req(req
);
466 return (struct ifnet
*)ssc
;
470 * Allocate Sana-II IORequests for TCP/IP process
473 sana_run(struct sana_softc
*ssc
, int requests
, struct ifaddr
*ifa
)
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
) {
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
);
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
;
537 req
->ioip_next
= next
;
538 AddTail((struct List
*)&ssc
->ss_freereq
, (struct Node
*)req
);
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
) {
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
;
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
;
565 * Free Sana-II IO Requests
566 * Note: this is protected by splimp();
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
);
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.
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
;
601 D(bug("[ATCP-SANA] sana_ioctl()\n"));
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"));
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"));
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);
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
;
644 D(bug("[ATCP-SANA] sana_ioctl: SIFADDR bringing interface UP .. \n"));
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
) {
659 ssc
->ss_ipaddr
= IA_SIN(ifa
)->sin_addr
;
665 case SIOCSIFDSTADDR
: /* Sets P-P-link destination address */
666 D(bug("[ATCP-SANA] sana_ioctl: SIOCSIFDSTADDR - [*] Set P-P-link destination address\n"));
670 D(bug("[ATCP-SANA] sana_ioctl: UNKNOWN SIOC\n"));
680 * send read requests with given types, dispatcher & c
681 * MUST be called at splimp()
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
;
691 for (i
= 0; i
< count
; i
++) {
692 if (!(req
= (struct IOIPReq
*)RemHead((struct List
*)&ssc
->ss_freereq
)))
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
))
700 BeginIO((struct IORequest
*)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");
712 * Called when interface goes online
715 sana_restore(struct sana_softc
*ssc
)
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
));
724 ssc
->ss_if
.if_flags
|= IFF_UP
;
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 */
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);
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);
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
);
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
);
782 __log(LOG_NOTICE
, "%s%d is now online.", ssc
->ss_name
, ssc
->ss_if
.if_unit
);
785 DeleteIOSana2Req(req
);
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
);
805 #else /* implement later for other compilers */
806 #define AbortSanaIO AbortIO
810 * sana_down(): Mark interface as down, abort all pending requests
813 sana_down(struct sana_softc
*ssc
)
815 struct IOSana2Req
* sreq
;
817 struct IOIPReq
*req
= ssc
->ss_reqs
;
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 */
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
);
840 DeleteIOSana2Req(sreq
);
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
);
848 gui_set_interface_state(&ssc
->ss_if
, MIAMIPANELV_AddInterface_State_Online
);
856 * sana_read: deattach a packet from IORequest
857 * resend the IORequest
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
) {
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
;
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 */
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
);
899 ssc
->ss_if
.if_flags
&= ~IFF_UP
;
900 gui_set_interface_state(&ssc
->ss_if
, MIAMIPANELV_AddInterface_State_Offline
);
906 if (debug_sana
&& req
->ioip_Error
!= IOERR_ABORTED
)
907 sana2perror(banner
, (struct IOSana2Req
*)req
);
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
);
920 __log(LOG_ERR
, "sana_read (%s): not enough mbufs\n", ssc
->ss_name
);
923 /* do not resend, free used resources */
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
);
941 * sana_ip_read(): feed a packet to the IP queue
942 * (This routine is called from sana_poll)
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",
953 if (IF_QFULL(&ipintrq
)) {
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
);
970 * sana_arp_read(): process an ARP packet
971 * (This routine is called from sana_poll)
974 sana_arp_read(struct sana_softc
*ssc
, struct IOIPReq
*req
)
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
);
984 arpinput(ssc
, m
, hwaddr
);
988 * sana_online(): process an ONLINE event
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
) {
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
);
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
);
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
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
);
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
;
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
;
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
)) {
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
))) {
1081 req
->ioip_s2
.ios2_Req
.io_Flags
= 0;
1083 switch (dst
->sa_family
) {
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
);
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
) ?
1120 #error NS unimplemented!!!
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
);
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;
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
);
1145 req
->ioip_s2
.ios2_Req
.io_Flags
= SANA2IOF_RAW
;
1148 req
->ioip_s2
.ios2_Req
.io_Message
.mn_Node
.ln_Pri
= 0;
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
;
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
)
1185 AddHead((struct List
*)&ssc
->ss_freereq
, (struct Node
*)req
);
1195 * free_written_packet(): free mbufs of written packet,
1196 * queue IOrequest for reuse
1197 * (This routine is called from sana_poll)
1200 free_written_packet(struct sana_softc
*ssc
, struct IOIPReq
*req
)
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
);
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
;
1227 case IFQ_DeviceUnit
:
1228 *((ULONG
*)tag
->ti_Data
) = ssc
->ss_execunit
;
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
);
1233 case IFQ_HardwareType
:
1234 *((ULONG
*)tag
->ti_Data
) = ssc
->ss_hwtype
;
1236 case IFQ_NumReadRequests
:
1237 __log(LOG_CRIT
, "IFQ_NumReadRequests is not implemented");
1239 /* *((LONG *)tag->ti_Data) = *** TODO ***
1241 case IFQ_MaxReadRequests
:
1242 __log(LOG_CRIT
, "IFQ_MaxReadRequests is not implemented");
1244 /* *((LONG *)tag->ti_Data) =
1246 case IFQ_NumWriteRequests
:
1247 __log(LOG_CRIT
, "IFQ_NumWriteRequests is not implemented");
1249 /* *((LONG *)tag->ti_Data) =
1251 case IFQ_MaxWriteRequests
:
1252 __log(LOG_CRIT
, "IFQ_MaxWriteRequests is not implemented");
1254 /* *((LONG *)tag->ti_Data) =
1256 case IFQ_GetDebugMode
:
1257 *((LONG
*)tag
->ti_Data
) = debug_sana
;
1259 case IFQ_GetSANA2CopyStats
:
1260 __log(LOG_CRIT
, "IFQ_GetSANA2CopyStats is not implemented");
1262 /* (struct Sana2CopyStats *)tag->ti_Data
1264 case IFQ_NumReadRequestsPending
:
1265 __log(LOG_CRIT
, "IFQ_NumReadRequestsPending is not implemented");
1267 /* *((LONG *)tag->ti_Data =
1269 case IFQ_NumWriteRequestsPending
:
1270 __log(LOG_CRIT
, "IFQ_NumWriteRequestsPending is not implemented");
1272 /* *((LONG *)tag->ti_Data =