Annotation of sys/dev/pci/if_san_common.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_san_common.c,v 1.11 2005/11/08 20:23:42 canacar 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:
36: # include <sys/types.h>
37: # include <sys/param.h>
38: # include <sys/systm.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/proc.h>
47: # include <sys/socket.h>
48: # include <sys/kernel.h>
49: # include <sys/time.h>
50: # include <sys/timeout.h>
51:
52: # include <net/bpf.h>
53: # include <net/if_dl.h>
54: # include <net/if_types.h>
55: # include <net/if.h>
56: # include <net/netisr.h>
57: # include <net/route.h>
58: # include <net/if_media.h>
59: # include <net/ppp_defs.h>
60: # include <net/if_ppp.h>
61: # include <net/if_sppp.h>
62: # include <netinet/in_systm.h>
63: # include <netinet/in.h>
64: # include <netinet/in_var.h>
65: # include <netinet/udp.h>
66: # include <netinet/ip.h>
67:
68: # include <dev/pci/if_san_common.h>
69: # include <dev/pci/if_san_obsd.h>
70:
71: #ifdef _DEBUG_
72: #define STATIC
73: #else
74: #define STATIC static
75: #endif
76:
77: /* WAN link driver entry points */
78: #if 0
79: static int shutdown(sdla_t *card);
80: #endif
81:
82: /* Miscellaneous functions */
83: static int wan_ioctl(struct ifnet*, int, struct ifreq *);
84: static int sdla_isr(void *);
85:
86: static void release_hw(sdla_t *card);
87:
88: static int wan_ioctl_dump(sdla_t *, void *);
89: static int wan_ioctl_hwprobe(struct ifnet *, void *);
90:
91: /*
92: * Global Data
93: * Note: All data must be explicitly initialized!!!
94: */
95:
96: /* private data */
97: extern char *san_drvname;
98: LIST_HEAD(, sdla) wan_cardlist = LIST_HEAD_INITIALIZER(&wan_cardlist);
99:
100: #if 0
101: static san_detach(void)
102: {
103: wanpipe_common_t *common;
104: sdla_t *card, *tmp_card;
105: int err = 0;
106:
107: card = LIST_FIRST(&wan_cardlist);
108: while (card) {
109: if (card->disable_comm)
110: card->disable_comm(card);
111:
112: while ((common = LIST_FIRST(&card->dev_head))) {
113: LIST_REMOVE(common, next);
114: if (card->del_if) {
115: struct ifnet *ifp =
116: (struct ifnet*)&common->ifp;
117: log(LOG_INFO, "%s: Deleting interface...\n",
118: ifp->if_xname);
119: card->del_if(card, ifp);
120: }
121: }
122: log(LOG_INFO, "%s: Shutdown device\n", card->devname);
123: shutdown(card);
124: tmp_card = card;
125: card = LIST_NEXT(card, next);
126: LIST_REMOVE(tmp_card, next);
127: free(tmp_card, M_DEVBUF);
128: }
129:
130: log(LOG_INFO, "\n");
131: log(LOG_INFO, "%s: WANPIPE Generic Modules Unloaded.\n",
132: san_drvname);
133:
134: err = sdladrv_exit();
135: return err;
136: }
137: #endif
138:
139:
140: int
141: san_dev_attach(void *hw, u_int8_t *devname, int namelen)
142: {
143: sdla_t *card;
144: wanpipe_common_t *common = NULL;
145: int err = 0;
146:
147: card=malloc(sizeof(sdla_t), M_DEVBUF, M_NOWAIT);
148: if (!card) {
149: log(LOG_INFO, "%s: Failed allocate new card!\n",
150: san_drvname);
151: return (EINVAL);
152: }
153: bzero(card, sizeof(sdla_t));
154: card->magic = WANPIPE_MAGIC;
155: wanpipe_generic_name(card, card->devname, sizeof(card->devname));
156: strlcpy(devname, card->devname, namelen);
157: card->hw = hw;
158: LIST_INIT(&card->dev_head);
159:
160: sdla_getcfg(card->hw, SDLA_CARDTYPE, &card->type);
161: if (sdla_is_te1(card->hw))
162: sdla_te_defcfg(&card->fe_te.te_cfg);
163:
164: err = sdla_setup(card->hw);
165: if (err) {
166: log(LOG_INFO, "%s: Hardware setup Failed %d\n",
167: card->devname,err);
168: return (EINVAL);
169: }
170: err = sdla_intr_establish(card->hw, sdla_isr, (void*)card);
171: if (err) {
172: log(LOG_INFO, "%s: Failed set interrupt handler!\n",
173: card->devname);
174: sdla_down(card->hw);
175: return (EINVAL);
176: }
177:
178: switch (card->type) {
179: case SDLA_AFT:
180: #if defined(DEBUG_INIT)
181: log(LOG_INFO, "%s: Starting AFT Hardware Init.\n",
182: card->devname);
183: #endif
184: common = wan_xilinx_init(card);
185: break;
186: }
187: if (common == NULL) {
188: release_hw(card);
189: card->configured = 0;
190: return (EINVAL);
191: }
192: LIST_INSERT_HEAD(&card->dev_head, common, next);
193:
194: /* Reserve I/O region and schedule background task */
195: card->critical = 0;
196: card->state = WAN_DISCONNECTED;
197: card->ioctl = wan_ioctl;
198: return (0);
199: }
200:
201:
202: /*
203: * Shut down WAN link driver.
204: * o shut down adapter hardware
205: * o release system resources.
206: *
207: */
208: #if 0
209: static int
210: shutdown (sdla_t *card)
211: {
212: int err=0;
213:
214: if (card->state == WAN_UNCONFIGURED) {
215: return 0;
216: }
217: card->state = WAN_UNCONFIGURED;
218:
219: bit_set((u_int8_t*)&card->critical, PERI_CRIT);
220:
221: /* In case of piggibacking, make sure that
222: * we never try to shutdown both devices at the same
223: * time, because they depend on one another */
224:
225: card->state = WAN_UNCONFIGURED;
226:
227: /* Release Resources */
228: release_hw(card);
229:
230: /* only free the allocated I/O range if not an S514 adapter */
231: if (!card->configured) {
232: card->hw = NULL;
233: if (card->same_cpu) {
234: card->same_cpu->hw = NULL;
235: card->same_cpu->same_cpu = NULL;
236: card->same_cpu=NULL;
237: }
238: }
239:
240: bit_clear((u_int8_t*)&card->critical, PERI_CRIT);
241:
242: return err;
243: }
244: #endif
245:
246: static void
247: release_hw(sdla_t *card)
248: {
249: log(LOG_INFO, "%s: Master shutting down\n",card->devname);
250: sdla_down(card->hw);
251: sdla_intr_disestablish(card->hw);
252: card->configured = 0;
253: return;
254: }
255:
256:
257: /*
258: * Driver IOCTL Handlers
259: */
260:
261: static int
262: wan_ioctl(struct ifnet *ifp, int cmd, struct ifreq *ifr)
263: {
264: sdla_t *card;
265: wanpipe_common_t *common = WAN_IFP_TO_COMMON(ifp);
266: int err;
267:
268: SAN_ASSERT(common == NULL);
269: SAN_ASSERT(common->card == NULL);
270:
271: if ((err = suser(curproc, 0)) != 0)
272: return err;
273:
274: switch (cmd) {
275: case SIOC_WANPIPE_HWPROBE:
276: err = wan_ioctl_hwprobe(ifp, ifr->ifr_data);
277: break;
278:
279: case SIOC_WANPIPE_DUMP:
280: err = wan_ioctl_dump(card, ifr->ifr_data);
281: break;
282:
283: default:
284: err = ENOTTY;
285: break;
286: }
287: return err;
288: }
289:
290: static int
291: wan_ioctl_hwprobe(struct ifnet *ifp, void *u_def)
292: {
293: sdla_t *card = NULL;
294: wanpipe_common_t *common = WAN_IFP_TO_COMMON(ifp);
295: wanlite_def_t def;
296: unsigned char *str;
297: int err;
298:
299: SAN_ASSERT(common == NULL);
300: SAN_ASSERT(common->card == NULL);
301: card = common->card;
302: bzero(&def, sizeof(wanlite_def_t));
303: /* Get protocol type */
304: def.proto = common->protocol;
305:
306: /* Get hardware configuration */
307: err = sdla_get_hwprobe(card->hw, (void**)&str);
308: if (err)
309: return EINVAL;
310:
311: strlcpy(def.hwprobe, str, sizeof(def.hwprobe));
312: /* Get interface configuration */
313: if (IS_TE1(&card->fe_te.te_cfg)) {
314: if (IS_T1(&card->fe_te.te_cfg))
315: def.iface = IF_IFACE_T1;
316: else
317: def.iface = IF_IFACE_E1;
318:
319: bcopy(&card->fe_te.te_cfg, &def.te_cfg, sizeof(sdla_te_cfg_t));
320: }
321:
322: err = copyout(&def, u_def, sizeof(def));
323: if (err) {
324: log(LOG_INFO, "%s: Failed to copy to user space (%d)\n",
325: card->devname, __LINE__);
326: return ENOMEM;
327: }
328: return 0;
329: }
330:
331: static int
332: wan_ioctl_dump(sdla_t *card, void *u_dump)
333: {
334: sdla_dump_t dump;
335: void* data;
336: u_int32_t memory;
337: int err = 0;
338:
339: err = copyin(u_dump, &dump, sizeof(sdla_dump_t));
340: if (err)
341: return err;
342:
343: sdla_getcfg(card->hw, SDLA_MEMORY, &memory);
344: if (dump.magic != WANPIPE_MAGIC)
345: return EINVAL;
346:
347: if ((dump.offset + dump.length) > memory)
348: return EINVAL;
349:
350: data = malloc(dump.length, M_DEVBUF, M_NOWAIT);
351: if (data == NULL)
352: return ENOMEM;
353:
354: sdla_peek(card->hw, dump.offset, data, dump.length);
355: err = copyout(data, dump.ptr, dump.length);
356: if (err) {
357: log(LOG_INFO, "%s: Failed to copy to user space (%d)\n",
358: card->devname, __LINE__);
359: }
360: free(data, M_DEVBUF);
361: return err;
362: }
363:
364:
365: /*
366: * SDLA Interrupt Service Routine.
367: * o call protocol-specific interrupt service routine, if any.
368: */
369: int
370: sdla_isr(void *pcard)
371: {
372: sdla_t *card = (sdla_t*)pcard;
373:
374: if (card == NULL || card->magic != WANPIPE_MAGIC)
375: return 0;
376:
377: switch (card->type) {
378: case SDLA_AFT:
379: if (card->isr)
380: card->isr(card);
381: break;
382: }
383: return (1);
384: }
385:
386: struct mbuf*
387: wan_mbuf_alloc(int len)
388: {
389: struct mbuf *m;
390:
391: /* XXX handle len > MCLBYTES */
392: if (len <= 0 || len > MCLBYTES)
393: return (NULL);
394:
395: MGETHDR(m, M_DONTWAIT, MT_DATA);
396:
397: if (m == NULL || len <= MHLEN)
398: return (m);
399:
400: m->m_pkthdr.len = len;
401: m->m_len = len;
402: MCLGET(m, M_DONTWAIT);
403:
404: if ((m->m_flags & M_EXT) == 0) {
405: m_freem(m);
406: return (NULL);
407: }
408:
409: return (m);
410: }
411:
412: int
413: wan_mbuf_to_buffer(struct mbuf **m_org)
414: {
415: struct mbuf *m, *m0, *tmp;
416: char *buffer;
417: size_t len;
418:
419: if (m_org == NULL || *m_org == NULL)
420: return (EINVAL);
421:
422: m0 = *m_org;
423: #if 0
424: /* no need to copy if it is a single, properly aligned mbuf */
425: if (m0->m_next == NULL && (mtod(m0, u_int32_t) & 0x03) == 0)
426: return (0);
427: #endif
428: MGET(m, M_DONTWAIT, MT_DATA);
429:
430: if (m == NULL)
431: return (ENOMEM);
432:
433: MCLGET(m, M_DONTWAIT);
434:
435: if ((m->m_flags & M_EXT) == 0) {
436: m_freem(m);
437: return (ENOMEM);
438: }
439:
440: m->m_len = 0;
441:
442: /* XXX handle larger packets? */
443: len = MCLBYTES ;
444: buffer = mtod(m, caddr_t);
445:
446: len -= 16;
447: buffer += 16;
448:
449: /* make sure the buffer is aligned to a 4-byte boundary */
450: if (ADDR_MASK(buffer, 0x03)) {
451: unsigned int inc = 4 - ADDR_MASK(buffer, 0x03);
452: buffer += inc;
453: len -= inc;
454: }
455:
456: m->m_data = buffer;
457:
458: for (tmp = m0; tmp; tmp = tmp->m_next) {
459: if (tmp->m_len > len) {
460: m_freem(m);
461: return (EINVAL);
462: }
463: bcopy(mtod(tmp, caddr_t), buffer, tmp->m_len);
464: buffer += tmp->m_len;
465: m->m_len += tmp->m_len;
466: len -= tmp->m_len;
467: }
468:
469: m_freem(m0);
470: *m_org = m;
471:
472: return (0);
473: }
CVSweb