root/dev/pci/musycc_obsd.c

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

DEFINITIONS

This source file includes following definitions.
  1. musycc_match
  2. musycc_softc_attach
  3. musycc_ebus_attach
  4. musycc_ebus_print

    1 /*      $OpenBSD: musycc_obsd.c,v 1.9 2006/01/25 11:02:54 claudio Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2004,2005  Internet Business Solutions AG, Zurich, Switzerland
    5  * Written by: Claudio Jeker <jeker@accoom.net>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 #include <sys/param.h>
   21 #include <sys/types.h>
   22 
   23 #include <sys/device.h>
   24 #include <sys/malloc.h>
   25 #include <sys/systm.h>
   26 #include <sys/socket.h>
   27 
   28 #include <machine/cpu.h>
   29 #include <machine/bus.h>
   30 #include <machine/intr.h>
   31 
   32 #include <net/if.h>
   33 #include <net/if_media.h>
   34 #include <net/if_sppp.h>
   35 
   36 #include <dev/pci/musyccvar.h>
   37 #include <dev/pci/musyccreg.h>
   38 
   39 #include <dev/pci/pcivar.h>
   40 #include <dev/pci/pcireg.h>
   41 #include <dev/pci/pcidevs.h>
   42 
   43 int     musycc_match(struct device *, void *, void *);
   44 void    musycc_softc_attach(struct device *, struct device *, void *);
   45 void    musycc_ebus_attach(struct device *, struct musycc_softc *,
   46             struct pci_attach_args *);
   47 int     musycc_ebus_print(void *, const char *);
   48 
   49 struct cfattach musycc_ca = {
   50         sizeof(struct musycc_softc), musycc_match, musycc_softc_attach
   51 };
   52 
   53 struct cfdriver musycc_cd = {
   54         NULL, "musycc", DV_DULL
   55 };
   56 
   57 SLIST_HEAD(, musycc_softc) msc_list = SLIST_HEAD_INITIALIZER(msc_list);
   58 
   59 const struct pci_matchid musycc_pci_devices[] = {
   60         { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_MUSYCC8478 },
   61         { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_MUSYCC8474 },
   62         { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_MUSYCC8472 },
   63         { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_MUSYCC8471 }
   64 };
   65 
   66 int
   67 musycc_match(struct device *parent, void *match, void *aux)
   68 {
   69         return (pci_matchbyid((struct pci_attach_args *)aux, musycc_pci_devices,
   70             sizeof(musycc_pci_devices)/sizeof(musycc_pci_devices[0])));
   71 }
   72 
   73 void
   74 musycc_softc_attach(struct device *parent, struct device *self, void *aux)
   75 {
   76         struct musycc_softc     *sc = (struct musycc_softc *)self;
   77         struct pci_attach_args  *pa = aux;
   78         pci_chipset_tag_t        pc = pa->pa_pc;
   79         pci_intr_handle_t        ih;
   80         const char              *intrstr = NULL;
   81 
   82         if (pci_mapreg_map(pa, MUSYCC_PCI_BAR,
   83             PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
   84             &sc->mc_st, &sc->mc_sh, NULL, &sc->mc_iosize, 0)) {
   85                 printf(": can't map mem space\n");
   86                 return;
   87         }
   88         sc->mc_dmat = pa->pa_dmat;
   89 
   90         switch (PCI_PRODUCT(pa->pa_id)) {
   91         case PCI_PRODUCT_CONEXANT_MUSYCC8478:
   92                 sc->mc_ngroups = 8;
   93                 sc->mc_nports = 8;
   94                 break;
   95         case PCI_PRODUCT_CONEXANT_MUSYCC8474:
   96                 sc->mc_ngroups = 4;
   97                 sc->mc_nports = 4;
   98                 break;
   99         case PCI_PRODUCT_CONEXANT_MUSYCC8472:
  100                 sc->mc_ngroups = 2;
  101                 sc->mc_nports = 2;
  102                 break;
  103         case PCI_PRODUCT_CONEXANT_MUSYCC8471:
  104                 sc->mc_ngroups = 1;
  105                 sc->mc_nports = 1;
  106                 break;
  107         }
  108 
  109         if (pa->pa_function == 1)
  110                 return (musycc_ebus_attach(parent, sc, pa));
  111 
  112         sc->bus = parent->dv_unit;
  113         sc->device = pa->pa_device;
  114         SLIST_INSERT_HEAD(&msc_list, sc, list);
  115 
  116         /*
  117          * Allocate our interrupt.
  118          */
  119         if (pci_intr_map(pa, &ih)) {
  120                 printf(": couldn't map interrupt\n");
  121                 bus_space_unmap(sc->mc_st, sc->mc_sh, sc->mc_iosize);
  122                 return;
  123         }
  124 
  125         intrstr = pci_intr_string(pc, ih);
  126         sc->mc_ih = pci_intr_establish(pc, ih, IPL_NET, musycc_intr, sc,
  127             self->dv_xname);
  128         if (sc->mc_ih == NULL) {
  129                 printf(": couldn't establish interrupt");
  130                 if (intrstr != NULL)
  131                         printf(" at %s", intrstr);
  132                 printf("\n");
  133                 bus_space_unmap(sc->mc_st, sc->mc_sh, sc->mc_iosize);
  134                 return;
  135         }
  136 
  137         printf(": %s\n", intrstr);
  138 
  139         /* soft reset device */
  140         bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_SERREQ(0),
  141             MUSYCC_SREQ_SET(1));
  142         bus_space_barrier(sc->mc_st, sc->mc_sh, MUSYCC_SERREQ(0),
  143             sizeof(u_int32_t), BUS_SPACE_BARRIER_WRITE);
  144 
  145         /*
  146          * preload global configuration: set EBUS to sane defaults
  147          * so that the ROM access will work.
  148          * intel mode, elapse = 3, blapse = 3, alapse = 3, disable INTB
  149          */
  150         sc->mc_global_conf = MUSYCC_CONF_MPUSEL | MUSYCC_CONF_ECKEN |
  151             MUSYCC_CONF_ELAPSE_SET(3) | MUSYCC_CONF_ALAPSE_SET(3) |
  152             MUSYCC_CONF_BLAPSE_SET(3) | MUSYCC_CONF_INTB;
  153 
  154         /* Dual Address Cycle Base Pointer */
  155         bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_DACB_PTR, 0);
  156         /* Global Configuration Descriptor */
  157         bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_GLOBALCONF,
  158             sc->mc_global_conf);
  159 
  160         return;
  161 }
  162 
  163 void
  164 musycc_ebus_attach(struct device *parent, struct musycc_softc *esc,
  165     struct pci_attach_args *pa)
  166 {
  167         struct ebus_dev                  rom;
  168         struct musycc_attach_args        ma;
  169         struct musycc_softc             *sc;
  170         pci_chipset_tag_t                pc = pa->pa_pc;
  171 #if 0
  172         pci_intr_handle_t                ih;
  173         const char                      *intrstr = NULL;
  174 #endif
  175         struct musycc_rom                baseconf;
  176         struct musycc_rom_framer         framerconf;
  177         bus_size_t                       offset;
  178         int                              i;
  179 
  180         /* find HDLC controller softc ... */
  181         SLIST_FOREACH(sc, &msc_list, list)
  182                 if (sc->bus == parent->dv_unit && sc->device == pa->pa_device)
  183                         break;
  184         if (sc == NULL) {
  185                 printf(": corresponding hdlc controller not found\n");
  186                 return;
  187         }
  188 
  189         /* ... and link them together */
  190         esc->mc_other = sc;
  191         sc->mc_other = esc;
  192 
  193 #if 0
  194         /*
  195          * Allocate our interrupt.
  196          */
  197         if (pci_intr_map(pa, &ih)) {
  198                 printf(": couldn't map interrupt\n");
  199                 goto failed;
  200         }
  201 
  202         intrstr = pci_intr_string(pc, ih);
  203         esc->mc_ih = pci_intr_establish(pc, ih, IPL_NET, ebus_intr, esc,
  204             esc->mc_dev.dv_xname);
  205         if (esc->mc_ih == NULL) {
  206                 printf(": couldn't establish interrupt");
  207                 if (intrstr != NULL)
  208                         printf(" at %s", intrstr);
  209                 printf("\n");
  210                 goto failed;
  211         }
  212 
  213         /* XXX this printf should actually move to the end of the function */
  214         printf(": %s\n", intrstr);
  215 #endif
  216 
  217         if (ebus_attach_device(&rom, sc, 0, 0x400) != 0) {
  218                 printf(": failed to map rom @ %05p\n", 0);
  219                 goto failed;
  220         }
  221 
  222         offset = 0;
  223         ebus_read_buf(&rom, offset, &baseconf, sizeof(baseconf));
  224         offset += sizeof(baseconf);
  225 
  226         if (baseconf.magic != MUSYCC_ROM_MAGIC) {
  227                 printf(": bad rom\n");
  228                 goto failed;
  229         }
  230 
  231         /* Do generic parts of attach. */
  232         if (musycc_attach_common(sc, baseconf.portmap, baseconf.portmode))
  233                 goto failed;
  234 
  235         /* map and reset leds */
  236         /* (15 * 0x4000) << 2 */
  237         esc->mc_ledbase = ntohl(baseconf.ledbase) << 2;
  238         esc->mc_ledmask = baseconf.ledmask;
  239         esc->mc_ledstate = 0;
  240         bus_space_write_1(esc->mc_st, esc->mc_sh, esc->mc_ledbase, 0);
  241 
  242         printf("\n");
  243 
  244         for (i = 0; i < baseconf.numframer; i++) {
  245                 if (offset >= 0x400) {
  246                         printf("%s: bad rom\n", sc->mc_dev.dv_xname);
  247                         goto failed;
  248                 }
  249                 ebus_read_buf(&rom, offset, &framerconf, sizeof(framerconf));
  250                 offset += sizeof(framerconf);
  251 
  252                 strlcpy(ma.ma_product, baseconf.product, sizeof(ma.ma_product));
  253                 ma.ma_base = ntohl(framerconf.base);
  254                 ma.ma_size = ntohl(framerconf.size);
  255                 ma.ma_type = ntohl(framerconf.type);
  256                 ma.ma_gnum = framerconf.gnum;
  257                 ma.ma_port = framerconf.port;
  258                 ma.ma_flags = framerconf.flags;
  259                 ma.ma_slot = framerconf.slot;
  260 
  261                 (void)config_found(&sc->mc_dev, &ma, musycc_ebus_print);
  262         }
  263 
  264         return;
  265 failed:
  266         /* Failed! */
  267         pci_intr_disestablish(pc, sc->mc_ih);
  268         if (esc->mc_ih != NULL)
  269                 pci_intr_disestablish(pc, esc->mc_ih);
  270         bus_space_unmap(sc->mc_st, sc->mc_sh, sc->mc_iosize);
  271         bus_space_unmap(esc->mc_st, esc->mc_sh, esc->mc_iosize);
  272         return;
  273 }
  274 
  275 int
  276 musycc_ebus_print(void *aux, const char *pnp)
  277 {
  278         struct musycc_attach_args *ma = aux;
  279 
  280         if (pnp)
  281                 printf("framer at %s port %d slot %c",
  282                     pnp, ma->ma_port, ma->ma_slot);
  283         else
  284                 printf(" port %d slot %c", ma->ma_port, ma->ma_slot);
  285         return (UNCONF);
  286 }
  287 

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