Annotation of sys/dev/pci/if_san_common.c, Revision 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