Annotation of sys/dev/pci/if_san_obsd.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_san_obsd.c,v 1.12 2006/05/13 19:04:30 brad Exp $ */
2:
3: /*-
4: * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
5: * All rights reserved. www.sangoma.com
6: *
7: * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above
15: * copyright notice, this list of conditions and the following disclaimer
16: * in the documentation and/or other materials provided with the
17: * distribution.
18: * 3. Neither the name of Sangoma Technologies nor the names of its
19: * contributors may be used to endorse or promote products derived
20: * from this software without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
23: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32: * THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: #include <sys/types.h>
36: #include <sys/param.h>
37: #include <sys/systm.h>
38: #include <sys/proc.h>
39: #include <sys/syslog.h>
40: #include <sys/ioccom.h>
41: #include <sys/conf.h>
42: #include <sys/malloc.h>
43: #include <sys/errno.h>
44: #include <sys/exec.h>
45: #include <sys/mbuf.h>
46: #include <sys/sockio.h>
47: #include <sys/socket.h>
48: #include <sys/kernel.h>
49: #include <sys/device.h>
50: #include <sys/time.h>
51: #include <sys/timeout.h>
52:
53: #include "bpfilter.h"
54: #if NBPFILTER > 0
55: # include <net/bpf.h>
56: #endif
57: #include <net/if.h>
58: #include <net/if_media.h>
59: #include <net/netisr.h>
60: #include <net/if_sppp.h>
61: #include <netinet/in_systm.h>
62: #include <netinet/in.h>
63:
64: #include <netinet/udp.h>
65: #include <netinet/ip.h>
66:
67: #include <dev/pci/if_san_common.h>
68: #include <dev/pci/if_san_obsd.h>
69:
70:
71: #ifdef _DEBUG_
72: #define STATIC
73: #else
74: #define STATIC static
75: #endif
76:
77: #define PPP_HEADER_LEN 4 /* should be globaly defined by sppp */
78:
79:
80: static sdla_t *wanpipe_generic_getcard(struct ifnet *);
81: static int wanpipe_generic_ioctl(struct ifnet *, u_long, caddr_t);
82: static void wanpipe_generic_watchdog(struct ifnet*);
83: static void wanpipe_generic_start(struct ifnet *);
84:
85:
86: static char *san_ifname_format = "san%d";
87:
88:
89:
90: static sdla_t *
91: wanpipe_generic_getcard(struct ifnet *ifp)
92: {
93: sdla_t* card;
94:
95: if (ifp->if_softc == NULL) {
96: log(LOG_INFO, "%s: Invalid device private structure pointer\n",
97: ifp->if_xname);
98: return (NULL);
99: }
100: card = ((sdla_t*)((wanpipe_common_t*)ifp->if_softc)->card);
101: if (card == NULL) {
102: log(LOG_INFO, "%s: Invalid Sangoma device card\n",
103: ifp->if_xname);
104: return (NULL);
105: }
106: return (card);
107: }
108:
109: int
110: wanpipe_generic_name(sdla_t *card, char *ifname, int len)
111: {
112: static int ifunit = 0;
113:
114: snprintf(ifname, len, san_ifname_format, ifunit++);
115: return (0);
116: }
117:
118: int
119: wanpipe_generic_register(sdla_t *card, struct ifnet *ifp, char *ifname)
120: {
121: wanpipe_common_t* common = WAN_IFP_TO_COMMON(ifp);
122:
123: if (ifname == NULL || strlen(ifname) > IFNAMSIZ)
124: return (EINVAL);
125: else
126: bcopy(ifname, ifp->if_xname, strlen(ifname));
127:
128: IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
129: IFQ_SET_READY(&ifp->if_snd);
130: ifp->if_mtu = PP_MTU;
131: ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
132: common->protocol = IF_PROTO_CISCO;
133:
134: ((struct sppp *)ifp)->pp_flags |= PP_CISCO;
135: ((struct sppp *)ifp)->pp_flags |= PP_KEEPALIVE;
136: ((struct sppp *)ifp)->pp_framebytes = 3;
137:
138: ifp->if_ioctl = wanpipe_generic_ioctl; /* Will set from new_if() */
139: ifp->if_start = wanpipe_generic_start;
140: ifp->if_watchdog = wanpipe_generic_watchdog;
141:
142: if_attach(ifp);
143: if_alloc_sadl(ifp);
144: sppp_attach(ifp);
145:
146: #if NBPFILTER > 0
147: bpfattach(&ifp->if_bpf, ifp, DLT_PPP, PPP_HEADER_LEN);
148: #endif /* NBPFILTER > 0 */
149:
150: return (0);
151: }
152:
153: void
154: wanpipe_generic_unregister(struct ifnet *ifp)
155: {
156: log(LOG_INFO, "%s: Unregister interface!\n", ifp->if_xname);
157:
158: sppp_detach(ifp);
159: if_free_sadl(ifp);
160: if_detach(ifp);
161: }
162:
163: static void
164: wanpipe_generic_start(struct ifnet *ifp)
165: {
166: sdla_t *card;
167: struct mbuf *opkt;
168: int err = 0;
169:
170: if ((card = wanpipe_generic_getcard(ifp)) == NULL)
171: return;
172:
173: while (1) {
174: if (sppp_isempty(ifp)) {
175: /* No more packets in send queue */
176: break;
177: }
178:
179: if ((opkt = sppp_dequeue(ifp)) == NULL) {
180: /* Should never happened, packet pointer is NULL */
181: break;
182: }
183: if (card->iface_send == NULL) {
184: m_freem(opkt);
185: break;
186: }
187: /* report the packet to BPF if present and attached */
188: #if NBPFILTER > 0
189: if (ifp->if_bpf)
190: bpf_mtap(ifp->if_bpf, opkt, BPF_DIRECTION_OUT);
191: #endif /* NBPFILTER > 0 */
192:
193: if (wan_mbuf_to_buffer(&opkt)) {
194: m_freem(opkt);
195: break;
196: }
197:
198: err = card->iface_send(opkt, ifp);
199: if (err)
200: break;
201: }
202: }
203:
204:
205: static int
206: wanpipe_generic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
207: {
208: struct proc *p = curproc;
209: struct ifreq *ifr = (struct ifreq*)data;
210: sdla_t *card;
211: wanpipe_common_t* common = WAN_IFP_TO_COMMON(ifp);
212: struct if_settings ifsettings;
213: unsigned long ts_map;
214: int err = 0, s;
215:
216: if ((card = wanpipe_generic_getcard(ifp)) == NULL)
217: return (EINVAL);
218:
219: s = splnet();
220:
221: switch (cmd) {
222: case SIOCSIFADDR:
223: // XXX because sppp does an implicit setflags
224: log(LOG_INFO, "%s: Bringing interface up.\n",
225: ifp->if_xname);
226: if (card->iface_up)
227: card->iface_up(ifp);
228: wanpipe_generic_start(ifp);
229: err = 1;
230: break;
231:
232: case SIOCSIFMEDIA:
233: /* You can't set new media type while card is running */
234: if (card->state != WAN_DISCONNECTED) {
235: log(LOG_INFO, "%s: Unable to change media type!\n",
236: ifp->if_xname);
237: err = EINVAL;
238: } else
239: err = ifmedia_ioctl(ifp, ifr, &common->ifm, cmd);
240: goto ioctl_out;
241:
242: case SIOCGIFMEDIA:
243: err = ifmedia_ioctl(ifp, ifr, &common->ifm, cmd);
244: goto ioctl_out;
245:
246: case SIOCSIFTIMESLOT:
247: if ((err = suser(p, p->p_acflag)) != 0)
248: goto ioctl_out;
249: if (card->state != WAN_DISCONNECTED) {
250: log(LOG_INFO, "%s: Unable to change timeslot map!\n",
251: ifp->if_xname);
252: err = EINVAL;
253: goto ioctl_out;
254: }
255:
256: err = copyin(ifr->ifr_data, &ts_map, sizeof(ts_map));
257: if (err == 0)
258: sdla_te_settimeslot(card, ts_map);
259:
260: goto ioctl_out;
261:
262: case SIOCGIFTIMESLOT:
263: ts_map = sdla_te_gettimeslot(card);
264: err = copyout(ifr->ifr_data, &ts_map, sizeof(ts_map));
265: goto ioctl_out;
266:
267: case SIOCSIFFLAGS:
268: /*
269: ** If the interface is marked up - enable communications.
270: ** If down - disable communications. IFF_UP is taken
271: ** care of before entering this function.
272: */
273: err = 1;
274: if ((ifp->if_flags & IFF_UP) == 0) {
275: if ((ifp->if_flags & IFF_RUNNING) == 0)
276: break;
277: /* bring it down */
278: log(LOG_INFO, "%s: Bringing interface down.\n",
279: ifp->if_xname);
280: if (card->iface_down)
281: card->iface_down(ifp);
282: } else { /* bring it up */
283: if (ifp->if_flags & IFF_RUNNING)
284: break;
285: log(LOG_INFO, "%s: Bringing interface up.\n",
286: ifp->if_xname);
287: if (card->iface_up)
288: card->iface_up(ifp);
289: wanpipe_generic_start(ifp);
290: }
291: break;
292:
293: case SIOC_WANPIPE_DEVICE:
294: err = copyin(ifr->ifr_data, &ifsettings,
295: sizeof(struct if_settings));
296:
297: if (err) {
298: log(LOG_INFO, "%s: Failed to copy from user space!\n",
299: card->devname);
300: goto ioctl_out;
301: }
302:
303: switch (ifsettings.type) {
304: case IF_GET_PROTO:
305: ifsettings.type = common->protocol;
306: err = copyout(&ifsettings, ifr->ifr_data,
307: sizeof(struct if_settings));
308: if (err)
309: log(LOG_INFO,
310: "%s: Failed to copy to uspace!\n",
311: card->devname);
312: break;
313:
314: case IF_PROTO_CISCO:
315: case IF_PROTO_PPP:
316: if ((err = suser(p, p->p_acflag)) != 0)
317: goto ioctl_out;
318: err = wp_lite_set_proto(ifp, (struct ifreq*)data);
319: break;
320:
321: case IF_IFACE_T1:
322: case IF_IFACE_E1:
323: if ((err = suser(p, p->p_acflag)) != 0)
324: goto ioctl_out;
325: err = wp_lite_set_te1_cfg(ifp, (struct ifreq*)data);
326: break;
327:
328: default:
329: if (card->iface_ioctl)
330: err = card->iface_ioctl(ifp, cmd,
331: (struct ifreq*)data);
332: break;
333: }
334: goto ioctl_out;
335:
336: default:
337: if (card->iface_ioctl) {
338: /* Argument seqeunce is change for Linux order */
339: err = card->iface_ioctl(ifp, cmd, (struct ifreq*)data);
340: }
341: break;
342: }
343:
344: if (err)
345: err = sppp_ioctl(ifp, cmd, data);
346:
347: ioctl_out:
348: splx(s);
349: return (err);
350: }
351:
352: static void
353: wanpipe_generic_watchdog(struct ifnet *ifp)
354: {
355: return;
356: }
357:
358: int
359: wanpipe_generic_open(struct ifnet *ifp)
360: {
361: return (0);
362: }
363:
364: int
365: wanpipe_generic_close(struct ifnet *ifp)
366: {
367: return (0);
368: }
369:
370: int
371: wanpipe_generic_input(struct ifnet *ifp, struct mbuf *m)
372: {
373: sdla_t *card;
374: #if NBPFILTER > 0
375: #endif /* NBPFILTER > 0 */
376:
377: if ((card = wanpipe_generic_getcard(ifp)) == NULL) {
378: return (-EINVAL);
379: }
380: m->m_pkthdr.rcvif = ifp;
381: #if NBPFILTER > 0
382: if (ifp->if_bpf)
383: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
384: #endif /* NBPFILTER > 0 */
385: ifp->if_ipackets ++;
386: sppp_input(ifp, m);
387: return (0);
388: }
389:
390: int
391: wp_lite_set_proto(struct ifnet *ifp, struct ifreq *ifr)
392: {
393: wanpipe_common_t *common;
394: struct if_settings *ifsettings;
395: int err = 0;
396:
397: if ((common = ifp->if_softc) == NULL) {
398: log(LOG_INFO, "%s: Private structure is null!\n",
399: ifp->if_xname);
400: return (EINVAL);
401: }
402:
403: ifsettings = (struct if_settings*) ifr->ifr_data;
404:
405: switch (ifsettings->type) {
406: case IF_PROTO_CISCO:
407: if (common->protocol == IF_PROTO_CISCO)
408: return 0;
409: ((struct sppp *)ifp)->pp_flags |= PP_CISCO;
410: ((struct sppp *)ifp)->pp_flags |= PP_KEEPALIVE;
411: common->protocol = IF_PROTO_CISCO;
412: break;
413: case IF_PROTO_PPP:
414: if (common->protocol == IF_PROTO_PPP)
415: return 0;
416: ((struct sppp *)ifp)->pp_flags &= ~PP_CISCO;
417: ((struct sppp *)ifp)->pp_flags |= PP_KEEPALIVE;
418: common->protocol = IF_PROTO_PPP;
419: break;
420: }
421:
422: err = sppp_ioctl(ifp, SIOCSIFFLAGS, ifr);
423: return (err);
424: }
425:
426: int
427: wp_lite_set_te1_cfg(struct ifnet *ifp, struct ifreq *ifr)
428: {
429: sdla_t *card;
430: struct if_settings *ifsettings;
431: sdla_te_cfg_t te_cfg;
432: int err = 0;
433:
434: if ((card = wanpipe_generic_getcard(ifp)) == NULL)
435: return (EINVAL);
436:
437: ifsettings = (struct if_settings*)ifr->ifr_data;
438: err = copyin(ifsettings->ifs_te1, &te_cfg, sizeof(sdla_te_cfg_t));
439:
440: if (ifsettings->flags & SANCFG_CLOCK_FLAG)
441: card->fe_te.te_cfg.te_clock = te_cfg.te_clock;
442:
443: switch (ifsettings->type) {
444: case IF_IFACE_T1:
445: if (ifsettings->flags & SANCFG_LBO_FLAG)
446: card->fe_te.te_cfg.lbo = te_cfg.lbo;
447: break;
448: }
449:
450: return (err);
451: }
CVSweb