root/dev/pci/if_san_common.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. san_detach
  2. san_dev_attach
  3. shutdown
  4. release_hw
  5. wan_ioctl
  6. wan_ioctl_hwprobe
  7. wan_ioctl_dump
  8. sdla_isr
  9. wan_mbuf_alloc
  10. wan_mbuf_to_buffer

    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 }

/* [<][>][^][v][top][bottom][index][help] */